単語埋め込み 入門

語は短い数の並びになり、類似度は角度になる。本ページのすべての図は、実際に訓練した 1 つの skip-gram モデル —— 41 トークン、1 語 8 個の数、60 エポック —— から読み出している。だからコサインも、類推も、負例を切ったときの潰れも、平面が描けない 28% の空間も、すべて図解ではなく実測である。

01

語はまず数にならねばならない

ネットワークは掛けて足すだけ、語は記号。誰もが最初に架ける橋は、意味を何ひとつ運べない橋でもある。

語彙のすべての語に添字を与え、その位置だけ 1、他はすべて 0 のベクトルとして書く。これが one-hot 符号化で、8 語の語彙なら符号全体がちょうど 1 枚の絵に収まる。語彙をスライドさせ、ただ 1 つの 1 が対角線を降りていくのを見てほしい:

king —— 8 行中 1 行目、1 は 1 番目のスロット

この表そのものが符号だという点に注目してほしい。8 語には 8 スロットが要り、どの行も 87.5% がゼロである。1 が担うのは語の同一性だけで、長さも綴りも、どんな語と連れ立つかも入っていない。どの 2 語をとっても、2 行はちょうど 2 か所で違う。

いま書いた一文が問題のすべてで、これは読むより触るほうが早い。1 つ目の語と2 つ目の語を選び、ドット積がするように対応するスロットを掛け合わせてみよう:

1 つ目の語:king · 2 つ目の語:dog · cos 0.00

積の行を見てほしい。2 本のスライダーが同じ語に乗らないかぎり、積は 0 × 1 か 1 × 0 か 0 × 0 なので和はゼロ、コサインもゼロになる。cat と kitten の類似度は cat と calculator とまったく同じ。この符号に「惜しい」はなく、同一か無関係かしかない。

2 つめの問題は算術のほうだ。実在のトークナイザは 8 項ではない。GPT-2 は 50,257、 Llama-3 は 128,256 項ある。次の図は 1 行を実寸で描いたもので、出発点はここまで使ってきた 8 語、目印は使用中のスロットの上にある —— 語彙を増やして、行が埋まっていくのを見てほしい:

8 語 —— 1 語あたり 32 バイト、役に立つのは 1 つだけ

ではスロットの幅は 1 ピクセルの百分の一 —— 目印はそれを指しているだけで、描いてはいない —— 1 行は float32 で 201 KB を食い、働いているのは 4 バイトだけだ。誰もこのベクトルを実体化しない。one_hot(i) @ W は W の i 行そのもので、どのフレームワークも行を取って掛け算を飛ばす。

そこで本ページの残りが答える問いが立つ。引いてくる行のほうが本体なら、なぜそれは長くて空でなければならないのか。各語に自由に選べる短い数の並びを与えると、訓練はこういうものを作る —— 語彙をドラッグして8 つのスロットを見てほしい:

king —— 長さ 2.82、8 スロットすべて使用中

どのスロットも使われていて、しかも手で決めたものは 1 つもない。1 語 201 KB ではなく 32 バイト。そして何より、2 つの行が部分的に似ることができるようになった。本ページの残りは、それで何が買えて、何を支払い、この数の読み方をどこで 3 度間違えるかの話である。

02

類似度とは角度のことである

語が方向になった瞬間、「この 2 つはどれだけ関係があるか」に数を伴う答えが生まれる —— そしてその数は距離ではない。

まずはスロットが 2 つしかない 2 語から始めよう。空間全体が 1 ページに収まる。ドット積は対応するスロットを掛けて足す:v · w = v₁w₁ + v₂w₂。v を w のまわりで振って、コサインを見てほしい:

角度 41 度、cos 0.76. ドラッグで動かせます。矢印キーで微調整、Home で最初の位置に戻ります。
角度 41 度、cos 0.76

符号がどこで反転するかに注目してほしい。2 本が同じ側へ傾いているあいだコサインは正、垂線の上でちょうどゼロ、v がそれを越えると負になる。コサインは方向の一致度の尺度で、ベクトルがどれだけ大きくなっても [−1, 1] の中にいる。

ドット積はそうではない。‖v‖ ‖w‖ cos θ なので、大きさについての問いにも同時に答えてしまう。v を自分の射線に沿って伸ばし、 2 つの数が離れていくのを見てほしい:

長さ 1.00

影が伸びていくあいだ、コサインは動かない。 ではドット積がほぼ 3 倍になり、角度は 1 度も動いていない。検索システムが生の内積ではなくコサインで並べるのはこのためだ。この割り算を省くと、長いだけの文書が本当に関連する文書を押しのける。しかもこの不具合は例外を投げない —— 黙って間違ったものを 1 位に返すだけである。

ここからが本番。以降の図はすべて同じ訓練済み空間である。skip-gram モデル、 41 トークン、1 語あたり 8 個の数、そして「どの語が同じ顔ぶれの中に出るか」以外の教師信号は一切ない。その 8 語を平面に置いたのが次の図だ。クエリをドラッグして、どの語に最も近いか見てほしい:

クエリは −0.20、0.10 —— 最近傍は cat. クエリ点は平面のどこへでもドラッグできます。矢印キーで微調整、Home で戻ります。
クエリは −0.20、0.10 —— 最近傍は cat

クエリは絵の上の点ではなく、8 次元空間の本物のベクトルである。読み出しのコサインは実際の行に対して計算されている。人は片側、動物は反対側 —— そしてそれをどこかに書いた者は誰もいない。

役に立つ操作は、ある語に自分の近傍を尋ねることだ。1 語選んで、最も近い 3 語がコサインとともに浮かび上がるのを見てほしい:

king の近傍

king と queen が同じ枠 —— 玉座、宮殿、王冠 —— に現れるため、モデルは両者に 0.78 を与えるしかない。 8 語のうち最も遠い cat は 0.20 である。これが分布仮説のすべてであり、訓練信号に入っているのはこれだけである。

03

この絵は影である

あなたが見てきた埋め込みの散布図はどれも、紙に載るために空間の大半を捨てている。この図が捨てているのは 28%。それだけで答えが変わる。

前節の平面は空間そのものではなく、射影である。8 本のベクトルは各 8 個の数を持ち、紙面には 2 個ぶんしか場所がない。どの 2 個にするかは我々の選択だ。2 組の異なる方向を切り替えて、地図が描き直されるのを見てほしい:

PC1 × PC2 —— ばらつきの 72% を保持

何も動いていないことに注目してほしい。2 つの枠でベクトルは同一で、変わったのは眺める向きに選んだ 2 方向だけ。それだけでばらつきの 72% が 41% になる。軸は性別でも王族でもない。この 8 行がたまたま最も大きく変化する方向にすぎない。

載りきらなかった分は消えたのではなく、紙の裏にある。それを各点のまわりの輪として、半径がちょうど平面の外に残った長さになるように描き、各語に空間が与える近傍を尋ねよう:

king —— 平面はその 60% を保つ。空間は queen、紙面は man と言う

2 本の線が食い違うのを見てほしい。8 語すべてで、紙面上の最も近い点は空間で最も近い語ではない。紙面は king の隣に man を置き、空間は queen だと言う。平面は king の 60% しか保っておらず、半径 1.33 の輪は、 2 つの候補を分ける 0.58 よりずっと大きい。

では 1 語に必要な数はいくつなのか。この曲線の各点は、同じコーパスを異なる幅で訓練した別々の実行結果である。d を下へドラッグして、すべてのペアが互いに潰れていくのを見てほしい:

8 スロット —— 全ペアの平均は 0.44

では全ペアが 1.00 になる。数が 1 つでは大きさしか符号化できないからだ。2 スロットで 0.85、3 で 0.53、8 で 0.44 に落ち着く。

この下限を決めるのは幅ではなくコーパスだ。ここの枠は 4 種類の区別しか持たないので、 4〜5 方向で足り、曲線はそこから平らになる。実運用の幅が 300(word2vec)、768(GPT-2)、 4,096(Llama-3)なのは、実コーパスがはるかに多くを符号化するからである。

04

訓練が実際に動かすもの

規則は 2 つだけ。それを数十万回。共起した組は引き寄せ、共起しない組は押し離す。

skip-gram はある語と本文中の隣語を取り、はい/いいえの問いを 1 つだけ立てる —— この 2 つは一緒に現れたか。モデルの答えは σ(w · c) で、各ステップはそれを 1 へ寄せる。勾配ステップを増やし、対象語と文脈語が互いに振れていくのを見てほしい:

0 ステップ —— この組へのスコアは 0.09

2 本とも動くことに注目してほしい。対象語が上へ、文脈語が横へ振れる。w についての勾配は (σ − 1)·c、c についての勾配は (σ − 1)·w なので、どちらも相手に沿って押される。でモデルはこの実在の組に 0.09 を付ける。誤差が大きいので、最初の一歩も大きい。

引く力だけでは自明な最適解がある。すべてのベクトルを同じ巨大なベクトルにすればドット積はどれも大きい。押す力が要る。skip-gram は 1 ステップごとにk 個の語を無作為に引き、それらを逆向きに押す。 k をゼロから上げてみよう:

負例なし —— すべてのベクトルが同じ向きに潰れる

で何が起きるかを見てほしい。無関係な語が対象語から 0.85 の位置に落ち着く。本物の文脈語は 0.90 である —— モデルは見たこともない組について自信満々で、しかも損失はずっと下がり続けていた。これが例外を投げない失敗だ。word2vec は負例を 5〜20 個使う。この訓練器は 5 個引く。

アルゴリズムはこれで全部である。コーパス(41 トークン、13 の枠、60 エポック)で回すと、 1 エポック目では 8 語はまだ原点近くのひとかたまりだ。各軌跡が 1 語、その上の点がいまの位置なので、エポックをドラッグしてking と queen が動物たちと袂を分かつのを見てほしい:

60 エポック中 1 番目

最初の 10 エポックがほぼすべての仕事を終える。1 エポック目はどのペアも似て見える ——king/queen 0.95、king/dog 0.99 —— 10 エポック目には king/dog が 0.24 まで落ち、king/queen は 0.81 を保つ。両者をこじ開けたのは負例である。

ここが不変量であり、本節から持ち帰るべき唯一のものである。更新が触るのは組どうしのドット積だけだ。空間全体を回転させてもドット積は変わらず、したがって損失も変わらない。解は回転の分だけ不定である —— だからどの埋め込みでも、個々の座標には意味がない。

最小化されている数は、それらのはい/いいえの負の対数尤度である。損失の曲線の上をドラッグしてほしい:

エポック 1 —— 損失 3.77

曲線が単調でないことに注目してほしい。各エポックは負例を引き直すので、報告される損失は同じ目的関数の別の無作為部分標本になる。1 エポック目 3.77、 60 エポック目 1.19、その間はかなり揺れる。負例サンプリング下で一度も揺れない損失は、たいていいま合わせたミニバッチの上で計算された損失である。

05

誰も頼んでいない幾何

目的関数は語と語のあいだの方向に一言も触れていない。それでも方向は現れる —— 有名な例が匂わせるより有用で、しかも壊れやすい形で。

2 語の差 —— woman 引く man —— を取り、第 3 の語に足す。この差はただのベクトルなので、どこからでも出発できる。それをking にだんだん多く足して、和がどこに落ちるか見てほしい:

オフセットを 0.00 —— 最近傍は queen

足すと、和は queen と 1.00、次点とは 0.44 になる。このモデルに性別の方向を入れた者はいない。he と she を分ける枠が、触れるすべての語に同じ変位を与えるから存在するのだ。

この主張の有名版は 2 点で言い過ぎており、どちらも目に見える。第 1 に、和は勝った語の上には決して落ちない。3 つの類推について、和と勝った語のあいだに残差を描いた:

king − man + woman

残差の長さは 0.247、クエリの長さは 2.90 なので、平行四辺形は 8.5% ずれる —— 動物の組では 13% だ。答えは最も近い語であって正しい語ではない。しかもここでの「最も近い」は入力 3 語を名簿から消したあとの最も近いという意味でもある。残しておくと king が 0.73 で 3 位に戻ってくる。

第 2 に、この方向は存在するための場所を必要とする。下の各棒は、訓練器が実際に走った幅のひとつにおける、類推クエリと 1 語のコサインである。d を下げて、順位が崩れるのを見てほしい:

8 スロット —— 類推が返すのは queen

では類推は prince を 0.999 で返し、princess・queen・king が 2 千分の 1 以内に並ぶ。算術に誤りはない。性別と地位と年齢が同時に別々の方向でいられる場所がないだけで、だから共有され、勝敗はノイズが決める。

空間全体についてもう 1 つ。稼働中の検索システムを持つ人ほど驚く性質である。 12 語の 66 ペアすべてを取り、コサインをビンに数え上げる ——縦線が直角の位置だ:

重心を 0% 除去 —— 全ペアのスコアは 0.44

その左側に何もないことに注目してほしい。全ペアが正、平均は 0.44、最小値は 0.071。 12 語は重心から 43.8°〜48.7° の円錐に収まる。実際の埋め込み空間で「無関係」は直交を意味しない。

重心を引くと円錐は開く。するとペア平均は 0.36、最小のペアは −0.74。最近傍探索の前に平均中心化を行うのが定石なのは、この 1 行のためだ。

06

「1 語 1 ベクトル」の限界

ルックアップ表はトークンごとにちょうど 1 行。言語はトークンごとにちょうど 1 つの意味ではない。この隙間から Transformer が始まる。

1 つのトークンが無関係な 2 つの意味を背負う場合を考えよう。bank が川岸と金融機関を兼ねるように。このコーパスにそんな語はないので作る —— あるときは dog、残りはking を意味するトークンだ。出現のたびに勾配が積まれるので、その行は頻度重み付き平均になる。割合をゼロから上げてほしい:

2 つ目の意味が 0%

でも、この行は多数派の意味と 0.97、少数派とは 0.50 にしかならない。まれな読みはほぼ表現されない。半々にすると 0.86 と 0.75 —— どちらにも近く、どちらの良い一致でもない。

このスライダーには、この行が正しく振る舞う位置が存在しない。表は 1 行しかなく、語には意味が 2 つあるからだ。これは word2vec の不具合ではなく、文脈モデルが存在する理由そのものである。Transformer はこのルックアップを第 1 層として残し、周囲の文を使ってアテンションにベクトルを書き換えさせる。bank は第 0 層を平均として出発し、第 12 層にはどちらかの意味として着く。

最後に知っておく価値があるのは、この表の値段だ。どのモデルもいまだに表から始まり、形はつねに V × d である —— モデルを選び、その位置から 2 つの数を読み取ってほしい:

toy

の表は 50,257 × 768 = 38.6 M パラメータ、float32 で 154 MB。1.24 億パラメータのモデルで最大の単一行列であり、全体の 31% を占める。GPT-2 はこの表を出力射影と結び付けて 1 回ぶんだけ払う。 Llama-3 8B は結び付けないので、128,256 × 4,096 = 525 M が帳簿に 2 度現れ、 80 億パラメータのモデルの 13% になる。

この表は §04 の目的関数があの形になっている理由でもある。正しいのは語彙全体に対する softmax で、トークンごとにすべての行に触れる。サンプリングが触るのはそのうち k + 1 行だけだ。下の 2 本の棒は同じ表を同じ縮尺で描いたものである:

負例 5 個 —— 積和 4,608 回

softmax は O(V·d)、 GPT-2 の 1 トークンで 3,860 万回の積和。サンプリングは O((k+1)·d) で、k = 5 なら 4,608 回。差は 8,000 倍 —— 琥珀色の棒が空に見えるのはそのためだ。

07

黙って失敗する 4 つ

形の誤りは例外を投げる。この 4 つは数を返す。

正規化しない順位付け。q · v は最長のベクトルを好む。意味があると思われた軸。損失は回転不変で、座標も PCA 軸も図の性質。行列の取り違え。skip-gram は 2 表を訓練し、公表結果は入力表を使う。ずらしていない円錐。生のコサインは 0.07 を下回らない。