前提
単語の意味はその周囲にある単語によって決定される(分布仮説)ので、周囲にある単語が類似している=その単語の意味が類似しているとみなすこともできる
- 例
-
the car
という単語の連続はよく見るが、car drive
という2つの単語には明らかに関連性がある - しかし
the
の出現頻度が高いのでカウントベースの方法では「car
という単語はdrive
という単語よりthe
という単語の方が関連性が高い」ということになる(実際の感覚とはかなりズレる)
-
これには単語の出現頻度が悪さをしている。the
は出現頻度がめちゃくちゃ多いので、色々な単語との関連性を示しやすい。出現頻度を考慮して単語同士の関連性を関連性をはかりたい。
相互情報量の導入
相互情報量(Pointwise Mutual Information)の数式は以下
PMI(x,y) = \log{2}{\frac{P(x,y)}{P(x)P(y)}}
分母の$P(x,y)$は単語x
と単語y
が共起する確率、$P(x)$と$P(y)$は文中に単語x
,y
が出現する確率を示す。
共起する確率を「それぞれ文中にどれだけ出現するか」で除することで、頻度による偽の関連性を取り除くことができる。
実際には共起回数が0の時にPMIが-∞に発散するので、実用上は正の相互情報量(Positive PMI)が用いられる。
PPMI(x,y) = MAX(0,PMI(x,y))
共起行列をPPMIの行列に変換してみる
以下のような文章text
について
text = 'You say goodbye and I say hello.'
共起行列C
は以下のようになる
C = np.array([
[0, 1, 0, 0, 0, 0, 0],
[1, 0, 1, 0, 1, 1, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 0, 1, 0, 1, 0, 0],
[0, 1, 0, 1, 0, 0, 0],
[0, 1, 0, 0, 0, 0, 1],
[0, 0, 0, 0, 0, 1, 0],
], dtype=np.int32)
相互情報量に変換すると以下のようになる。ほぼ0だから次元削減したくなるが、コーパスが増えると計算量が指数関数的に増えるのでミニバッチで少しずつ計算しよう、という思想になる。word2vecの始まり。
[[0. 1.8073549 0. 0. 0. 0. 0. ]
[1.8073549 0. 0.8073549 0. 0.8073549 0.8073549 0. ]
[0. 0.8073549 0. 1.8073549 0. 0. 0. ]
[0. 0. 1.8073549 0. 1.8073549 0. 0. ]
[0. 0.8073549 0. 1.8073549 0. 0. 0. ]
[0. 0.8073549 0. 0. 0. 0. 2.807355 ]
[0. 0. 0. 0. 0. 2.807355 0. ]]
大いに参考