深層学習

単語埋め込み

単語を共起する文脈から低次元の連続ベクトルへ写像し、Skip-gram や CBOW で単語間の近さを計算可能にする方法。

  • A|中核
  • 深層学習

数式の記号で止まったら 記号の読み方 (∂・⊙・転置・上付き添字を、読み方から)

ひとことで言うと

単語埋め込みは、語彙の各単語を、学習可能な低次元の実数ベクトルへ写像する方法です。単語IDをそのまま特徴量にするのではなく、似た文脈に現れる単語がベクトル空間でも近くなるように、予測タスクを通じて表現を学習します。

単語を社員証の番号だけで管理するのが one-hot 表現です。番号同士には「部署が近い」「担当が似ている」という関係がありません。埋め込みは、業務上の関係を反映した座標に社員を置き直す作業です。

なぜ必要か

語彙数を VV とすると、one-hot ベクトルは VV 次元で、1箇所だけが1、それ以外が0です。単語を区別するには十分ですが、異なる単語の内積は常に0なので、語彙中の2語がどれだけ似ているかを表せません。語彙が増えるほど入力も疎で高次元になります。

埋め込み行列を EinRV×dE in \mathbb{R}^{V\times d}、埋め込み次元を dd とすると、単語 ww のベクトルは one-hot ベクトル xw\mathbf{x}_w に対して ew=ETxw\mathbf{e}_w=E^{\mathsf T}\mathbf{x}_w と取り出せます。通常は d≪Vd\ll V です。学習後は cosine 類似度

cos⁡(ei,ej)=eiTej∥ei∥∥ej∥\operatorname{cos}(\mathbf{e}_i,\mathbf{e}_j)=\frac{\mathbf{e}_i^{\mathsf T}\mathbf{e}_j}{\lVert\mathbf{e}_i\rVert\lVert\mathbf{e}_j\rVert}

(ei,ej\mathbf{e}_i,\mathbf{e}_j は2単語の埋め込み)で近さを比較できます。これは辞書の定義を直接教えた結果ではなく、共起する文脈を予測する圧力から生じる近さです。

仕組み

文中の中心語を wtw_t、その周辺の語を wt+jw_{t+j} とします。Skip-gram は中心語から周辺語を予測し、CBOW(Continuous Bag-of-Words)は周辺語から中心語を予測します。

方式入力予測するもの文脈の順序
Skip-gram中心語 wtw_t周辺語 wt+jw_{t+j}周辺語ごとに扱う
CBOW周辺語のベクトル中心語 wtw_t平均するため使わない

出力側のベクトルを uw\mathbf{u}_w とし、Skip-gram の基本的な確率を

p(wo∣wi)=exp⁡(uwoTewi)∑w=1Vexp⁡(uwTewi)p(w_o\mid w_i)=\frac{\exp(\mathbf{u}_{w_o}^{\mathsf T}\mathbf{e}_{w_i})}{\sum_{w=1}^{V}\exp(\mathbf{u}_{w}^{\mathsf T}\mathbf{e}_{w_i})}

とします。wiw_i は入力語、wow_o は正解の出力語、VV は語彙数です。正解の周辺語の対数確率を最大化すると、同じ文脈で予測される語の内積が上がり、共起のパターンが埋め込みに分散して入ります。CBOW では入力側の周辺語ベクトルを平均して ectx\mathbf{e}_{\mathrm{ctx}} とし、同じ形式で中心語を予測します。

この式の分母は全語彙の計算を要求するため、1例ごとのコストが VV に依存します。階層的 softmax は語彙を二分木に置き、対象語までの経路上の二値分類だけを計算します。経路長はおおむね log⁡2V\log_2 V で、原論文では頻度の高い語に短い符号を割り当てる Huffman 木を使っています。負例サンプリングは、正例と少数の負例を二値分類することで全語彙の正規化を避ける別の工夫です。したがって、どちらも「埋め込みの意味を定義する別手法」ではなく、出力確率の学習コストを下げる方法です。

Skip-gram と CBOW の違いを「入力層が one-hot か dense か」で覚えると混乱します。両方とも単語を埋め込みへ写像します。違うのは予測の向きで、Skip-gram は中心語 →→ 周辺語、CBOW は周辺語 →→ 中心語です。

試験でどう問われるか

問われ方正解に寄る条件引っかけ
one-hot と分散表現の比較one-hot は語の同一性、分散表現は低次元の連続値で関係を表すone-hot の距離だけで意味の近さを測れる
Skip-gram と CBOW の対応中心語から周辺語が Skip-gram、周辺語から中心語が CBOW名称を入力側の表現形式で区別する
学習後の類似度ベクトルの cosine 類似度などで比較する単語IDの差や one-hot の内積を使う
高速化の選択階層的 softmax は木の経路、負例サンプリングは少数の負例を使うどちらも語彙全体の softmax を毎回計算する
論文の主張の範囲共起から得たベクトルが統語・意味の類似度評価で有効だった埋め込みが単語の意味を完全に定義すると言い切る

実装で確かめる

小さな Skip-gram を NumPy だけで学習します。pairs は同じ文の中心語と周辺語の組で、更新後に中心語 0 と 1 の cosine 類似度を表示します。

import numpy as np
rng = np.random.default_rng(0)
pairs, V, d = [(0, 2), (1, 2), (2, 0), (2, 1)] * 20, 3, 2
E, U = rng.normal(0, .2, (V, d)), rng.normal(0, .2, (V, d))
for _ in range(100):
    for i, o in pairs:
        s = U @ E[i]; p = np.exp(s - s.max()); p /= p.sum()
        g = p.copy(); g[o] -= 1
        old = U.copy()
        U -= .02 * g[:, None] * E[i]
        E[i] -= .02 * (g @ old)
sim = E[0] @ E[1] / (np.linalg.norm(E[0]) * np.linalg.norm(E[1]))
print(f"cosine(0, 1)={sim:.6f}")

実行結果は cosine(0, 1)=0.999074 です。語 0 と 1 が同じ文脈語 2 を予測する対を繰り返したため、入力側のベクトルが近づきました。実データでは、窓幅、頻度、負例の選び方で得られる空間が変わります。

取り違えやすいもの

用語単語埋め込みとの違い
one-hot 表現語彙の各語に固有の座標を割り当てる疎表現。類似度を学習していない
分散表現複数の次元に情報を分散して持たせる考え方。word2vec はその学習方法の一つ
CBOW周辺語から中心語を予測するモデル。埋め込みそのものの別名ではない
Skip-gram中心語から周辺語を予測するモデル。入力と出力のどちらの行列を使うかも実装で確認する
文脈依存表現同じ単語でも文脈でベクトルが変わる。word2vec 系の静的な埋め込みとは扱う情報が違う

想起チェック

one-hot では単語間の意味的な近さを表しにくい理由は

異なる単語の one-hot ベクトルの内積が0になるためです。語彙数 VV に比例する疎な座標であり、共起から得た連続的な近さを持ちません。

Skip-gram と CBOW は何から何を予測するか

Skip-gram は中心語から周辺語、CBOW は周辺語から中心語を予測します。

階層的 softmax と負例サンプリングは何を軽くするか

どちらも出力側の全語彙 softmax の計算を避ける工夫です。前者は二分木の経路、後者は正例と少数の負例を使います。

学習されたベクトルの近さは何に由来するか

単語そのものの定義を直接符号化したものではなく、文脈中の共起を予測する学習から生じます。

出典