ベクトル埋め込みってなんやねん Vol.2
表現方法について
コンピュータは文字列をそのまま計算できないため、まずは表現方法を考えよう。
AIは関数だと思ってみる
AI、機械学習、ニューラルネットワークなどと言うと急に難しそうに聞こえるが、やっていることをかなり乱暴に言えば、入力を受け取って何かを返す関数を作ることである。
例えば、犬か猫かを判定する関数を考える。
\[f(画像) = (猫である確率, 犬である確率)\]ある画像を入力した結果が、
\[f(画像) = (0.7, 0.3)\]だったら、「このモデルは猫である確率を0.7、犬である確率を0.3と見積もった」と解釈できる。
厳密には、この0.7が本当に現実の確率と一致しているとは限らない。モデルが出した値を、ここでは判定のための推定確率として扱うことにする。
機械学習では、このような関数を人間が作るのではなく、犬や猫の画像と正解ラベルを大量に見せて、入力と出力の対応関係を学習させる。
完璧な関数を近似する
犬か猫かを判定する場合、画像に対して正解ラベルを返す理想的な判定規則を考えることはできる。
ただし、世の中のすべての画像に対して「これは絶対に犬」「これは絶対に猫」と言えるとは限らない。遠くに写っていたり、犬と猫が一緒に写っていたり、そもそも人間同士で意見が分かれたりする画像もある。
そのため、実際には完璧な関数というより、あるデータの範囲でうまく判定できる関数を作ることになる。
ニューラルネットワークには、適切な活性化関数と十分な大きさを持たせると、一定の条件のもとで複雑な連続関数を任意の精度で近似できる、という性質がある。これは万能近似定理と呼ばれる。
ここで注意したいのは、「層を深くすれば必ず正しい答えを学習できる」という意味ではないことだ。ネットワークがその関数を表現できることと、実際に学習できること、未知のデータに対して正しく判定できることは、それぞれ別の話である。
特徴量を使って判断する
何かを判断するとき、そのものを直接見るよりも、判断に役立ちそうな特徴に分けて考えられると都合がよい。
画像なら、画素の明るさや色、線の位置、輪郭、模様などが特徴になる。例えばMNISTの手書き数字なら、「黒い画素がどの位置に集まっているか」「線がどのようにつながっているか」といった特徴を使って、数字を判定できそうである。
単に黒い画素が多いかどうかだけでは、1と8を区別できない。どこに黒い画素があり、どんな形を作っているのかが重要になる。
音声も、特定の周波数が一つ出ているかどうかだけで判断するわけではない。時間ごとの周波数成分を並べたスペクトログラムのような表現にすると、音の変化を扱いやすくなる。
音声の中のある音を判定するときには、周波数の分布、倍音、音の長さ、前後の音への変化などが関係する。つまり、音声でも「何Hzが出ているか」だけでなく、「時間とともにどのようなパターンになっているか」が特徴になる。
昔の機械学習では、人間がこのような特徴量を設計することが多かった。一方、ニューラルネットワークでは、入力に近い層から出力に近い層までの計算の中で、判定に役立つ特徴表現そのものを学習させることができる。
自然言語の特徴はどこにあるのか
では、自然言語では何が特徴になるのだろうか。
画像なら画素、音声なら時間ごとの周波数というように考えられる。しかし、単語には「この数値が高ければ犬」「この位置が黒ければ猫」のような、最初から決まった特徴量があるわけではない。
例えば、次の文を考える。
犬は可愛い。
猫は可愛い。
犬と猫は、どちらも「は可愛い」という文脈に現れている。さらに、次のような文も大量に出てきたとする。
犬が庭を走る。
猫が庭を走る。
このような文がたくさん集まると、犬と猫は似た文脈に登場する単語だと分かってくる。
ここで登場するのが分布仮説である。分布仮説とは、簡単に言えば、
単語の意味や類似性は、その単語がどのような文脈に現れるかの分布から捉えられる
という考え方である。
似た文脈に現れる単語は、似た意味を持つ傾向がある。そこで、単語を「その単語がどのような単語と一緒に現れるか」を表す数値の並びに変換すれば、単語同士の類似度を計算できるのではないか、と考えられる。
犬と猫は同じ意味なのか
ここで、「犬」と「猫」が似た文脈に現れるからといって、どんな文でも入れ替えられるわけではない。
犬は吠えるし、猫は鳴く。犬にはリードを付けるが、猫には猫じゃらしを与えたい。犬と猫には共通する文脈もあるが、それぞれ固有の文脈もある。
したがって、分布仮説から得られるのは「完全に同じ意味」ではなく、「文章中で似た使われ方をする」という関係である。
また、学習されたベクトルのある次元、特徴量が、そのまま「可愛い」という一つの特徴を表しているとも限らない。複数の次元が組み合わさって、単語同士の関係を表していることもある。
単語をベクトルにする
ここまでの話をまとめると、単語をそのまま「犬」や「猫」という文字列として扱うのではなく、文章中での使われ方をもとに数値の並びへ変換する。
この数値の並びがベクトルである。
似た文脈に現れる単語が、ベクトル空間でも近い位置に配置されるように学習できれば、単語同士の類似度を距離や内積で計算できるようになる。
ただし、単語をベクトルに変換するだけで、すべての意味を完全に表現できるわけではない。「銀行」のように文脈によって意味が変わる単語もあるし、「犬は人を噛んだ」と「人は犬を噛んだ」のように、同じ単語が登場していても語順によって意味が変わる。
このあたりをどう扱うかによって、単語一つに一つのベクトルを割り当てる方法と、文脈ごとに異なる表現を作る方法に分かれていく。
次は、単語を番号やone-hotベクトルで表現し、そこからどのように埋め込みベクトルを学習するのかを考える。