人工知能入門:Text Embedding Vector、「似ている言葉」の話

私のメルマガ「週間 life is beautiful」で、人工知能入門というタイトルで、人工知能技術の基礎を解説しているのですが、時々、数ヶ月前に書いたものを引用したくなる時があります。そんな時に、読者が簡単に参照できるように、noteにもコピーを作ることにしました。

今日のテーマは、ChatGPTで使われているLLM(大規模言語モデル)の基礎となる技術、Text Embeddingについて解説します。自然言語(人間は話す言葉)を扱う上で、「どの言葉がどの言葉に似ているか」を判断する際に使われる仕組みです。

私たちは、毎日のように「あの人は、芸能人の誰々さんに似ている」「このラーメンのスープって、中華三昧のスープに似ている」のように、何かと何かを比較して、「似ている」とか「似ていない」と評価しています。私たちの脳は、そんな判断を瞬時にする能力を持っていますが、実際に「どう似ているか」を説明するのは簡単ではありません。突き詰めれば、「目元が似ている」「雰囲気が似ている」、「出汁に鰹節を使っている」などの言葉が出てくることもありますが、実際のところは、とても曖昧で説明が付きにくい比較を私たちの脳はしています。

一方のコンピュータは、そんな曖昧な比較が不得意です。なんでも数値化し、数字を使ってしか評価が出来ません。

分かりやすい例が「色」です。私たちは、色を見ただけで、二つの色が似ているかどうかを瞬時に判断できます。しかし、コンピュータにはそんな器用なことが出来ません。数値化した上で、比較する必要があるのです。

色の数値化には二つの方法がありますが(「赤・緑・青」の色の三原色に分解する方法と、「色相・彩度・明度」の三つの色属性に分ける方法)、ここでは、分かりやすい「赤・緑・青」を使って説明します。

それぞれの色の強さを、0.00から1.00の間の数字で表すと、虹の7色は以下のように表現できます。

  • 赤:(1.00, 0.00, 0.00)

  • 橙:(1.00, 0.64, 0.00)

  • 黄:(1.00, 1.00, 0.00)

  • 緑:(0.00, 0.50, 0.00)

  • 青:(0.00, 1.00, 1.00)

  • 藍:(0.00, 0.00, 1.00)

  • 紫:(0.50, 0.00, 0.50)

この例のように、複数の数字から作られたデータのことを「ベクトル」もしくは「ベクター」と呼びます(同義語で、ベクトルはドイツ語のVektor、ベクターは英語のVectorをローマ字にしたものです)。数字の数を「次数」と呼び、このケースでは、「色は『3次ベクトル』で表現可能である」のように言います。

コンピュータが二つの色の「近さ」を調べる際には、(高校の物理や数学の授業で教わった)「ベクトルの内積」を使います。レールの上に乗ったトロッコを引っ張る際に、レールに沿って引っ張った方が引っ張りやすいのは、レールの方向(ベクトル)と引っ張る方向(ベクトル)が一致しているからです。内積は、二つのベクトルがどのくらい同じ方向を向いているかを調べるのに適した演算(=計算方法)です。

人工知能や自然言語処理の研究をしていていた研究者たちは、「言葉」をコンピュータの中で効率よく扱うには、上の色と同じように、なんらかのベクトルに変換すれば良いことに随分前(1980年代)から気がついていました。言葉のベクトル化(Text Embedding Vector、もしくは、単にEmbedding)の研究(特に人工知能への応用)が本格的に始まったのは、2010年代で、ChatGPTのベースである、GPT3.5/GPT4にもEmbeddingは使われており、その次元は、1,536もあります。

OpenAIのEmbedding APIを活用すると、任意の言葉のEmbeddingを求めることが出来ます。

  • 紫陽花(あじさい): [0.008374308, -0.004348531, 0.015492181, 0.012114794, ...以下略]

  • 向日葵(ひまわり): [0.00897903, -0.028575271, -0.011562964, 0.026796354, ...]

  • 鰯(いわし): [0.014147074, -0.018954331, -0.040955342, 0.015233389, ...]

  • 鯵(あじ): [0.02712337, 0.009231063, 0.025325274, 0.009623604, ...]

なんだか分からない数字が出てきますが、それそれの単語の内積を求めると面白い結果が得られます("・"は内積を表します)。

  • 紫陽花・向日葵 = 0.416

  • 紫陽花・鰯 = 0.218

  • 紫陽花・鯵 = 0.201

  • 向日葵・鰯 = 0.171

  • 向日葵・鯵 = 0.263

  • 鰯・鯵 = 0.653

紫陽花と向日葵、鰯と鯵のペアがそれぞれ「近い関係」であることが、計算だけで分かるのです。

試しに「花」「魚」という単語との関係を調べてみると以下のようになります。

  • 花・紫陽花 = 0.605

  • 花・向日葵 = 0.422

  • 花・鰯 = 0.338

  • 花・鯵 = 0.380

  • 魚・紫陽花 = 0.282

  • 魚・向日葵 = 0.249

  • 魚・鰯 = 0.414

  • 魚・鯵 = 0.507

片方が英語でも大丈夫です。

  • Flower・紫陽花 = 0.453

  • Flower・向日葵 = 0.406

  • Flower・鰯 = 0.224

  • Flower・鯵 = 0.243

単語だけでなく、文章のEmbeddingも計算可能で、同様の比較が可能です。

  • "I love you"・あなたを愛してます = 0.473

  • "I love you"・君が好き = 0.428

  • "I love you"・君が大好き = 0.439

  • "I live you"・"I like you" = 0.576

  • "I love you"・お前は嫌いだ = 0.251

  • "I love you"・あっち行け = 0.138

そのため、Embeddingを使うと、文章の「意味検索」が出来るようになります。通常の文字検索だと、"I love you" で検索すると、文字通り "I love you"の単語が文章中に並んでいないと見つけてくれませんが、Embeddingを使った検索をすると、似たような意味の、「あなたを愛してます」や「I like you」を見つけてくれるのです。

なんだか魔法のような技術ですが、これがText Embedding Vectorであり、この技術が、ChatGPTなどの「自然言語を理解する人工知能」の基礎になっているのです。

OpenAIのEmbedding APIが、どうやって計算しているか知りたい人もいるでしょうが、「十分な数のパラメータを持つニューラルネットに、たくさんの入力データと期待する答えを与えて、徐々にパラメータを調節した結果作った、Embedding Modelというニューラルネットを使って計算している」というのが答えです。

ニューラルネット一般に言える話ですが、1,536もある次元のそれぞれの数字が何を意味するのか、設計者も知りません。どこにどんな数字を置けば良いのかは、ニューラルネットワーク自身が、学習過程で自分で見つけ出したのです。

この記事が気に入ったらサポートをしてみませんか?