言語AIの進化史⑧埋め込みベクトル
前回は、トークン化とTF-IDFについて解説しました。TF-IDFは、Bag-of-Words(BoW)と同様に文章全体の特徴をベクトルで表現する手法です。その統計的特徴量の計算の仕方に特色がありました。
これで文書や文章の分類や類似性の計算することがある程度はできるようになりました。しかし、まだ前回に問題提起した課題が残っています。
前回からの再引用ですが、次の2つの文章を比べて下さい。
男は犬を撫でた。
男は犬を噛んだ。
この二つの文章は、BoWやTF-IDFでは同等です。なぜなら、トークンの前後関係などから生じる文脈を捉えられないからです。
この解決方法として、トークン間の関係を機械学習モデルで扱えるように数値化(ベクトル化)することが考えられます。
よって、今回はトークンの数値化、特に埋め込みベクトルについて解説します。
整数エンコーディング
整数エンコーディング (Integer Encoding)は、各トークンに一意の整数値を割り当てます。
例えば、語彙が ["cat", "dog", "mouse"] ならば以下のようになります。
"cat" --> 1
"dog" --> 2
"mouse" --> 3この手法はシンプルで分かりやすく、語彙が増えても効率的に対処できるので便利です。
しかし、数値の大小が意図しない意味を持つ可能性があります。
例えば、モデルへの入力として上述の整数値をそのまま使うと、「cat」は1で、「dog」には2なので、モデルは「dog」の方が「cat」より重要であるかのように振る舞うかもしれません。
なぜならば、機械学習モデルでは、数値の大きい特徴量の方が重要なものとして扱われる傾向があるからです。
この問題を解決するのがワンホット・エンコーディングです。
ワンホット・エンコーディング
ワンホット・エンコーディング (One-Hot Encoding)は、各トークンをベクトルに変換し、該当するトークンの位置だけを1にして、他の位置は0にします。
また、この手法で生成されたベクトルをワンホット・ベクトルと呼びます。
例えば、語彙として ["cat", "dog", "mouse"] だけしかないとします。この場合のワンホット・エンコーディングを次のように設定することができます。
"cat" --> [1, 0, 0]
"dog" --> [0, 1, 0]
"mouse" --> [0, 0, 1]これによって、「cat」と「dog」と「mouse」はそれぞれユニークなベクトルとして表現されています。
また、数値に大小の差がありません。このベクトルは、大小の差を作らずに、異なるトークンを区別しています。
ただし、問題があります。語彙の数だけベクトルの要素数(次元数)が必要なので、語彙数が大きくなると無駄にメモリを消費することになります。
例えば、100万個のトークンを表現することを想像してみて下さい。一つの要素だけ1でそれ以外の999,999個の要素は0になります。
しかも、新しいトークンを追加するごとに全てのトークンのワンホット・エンコーディングの要素数が増えることになります。
よって、ワンホット・エンコーディングはカテゴリを区別するなど語彙が限定的な用途では便利ですが、語彙数が大量でしかも増える可能性がある場合は使いづらい手法です。
なお、前回に紹介したBag-of-Words(BoW)は、ワンホット・エンコーディングをさらに発展させたものと考えることもできます。それぞれのトークンをワンホットのベクトルで表現して総和を求めればBoWベクトルになります。
単語の埋め込み
トークンの数値化の表現形式について考えてみましょう。
局所表現
ワンホット・ベクトルはトークンの数だけ次元が増えるので多くの文章を扱うには非常に高次元なものが必要となります。また、トークン同士の意味の近さなどを計算することもできません。
このようにトークンごとに別々に表現する(1つのトークンを1つの成分で表す)ことを局所表現(local representation)と呼びます。
分散表現
逆に、1つのトークンをベクトルの複数の成分で表すことを分散表現(distributed representation)と呼びます。
例えば、犬のトークンを3次元ベクトルで$${[0.8, 0.4, 9.5]}$$と表現したとします。ワンホット・ベクトルと異なり、すべての要素を使ってトークンを表現します。つまり、局所ではなく分散された表現になっています。
語彙にあるすべてのトークンを3次元ベクトルで分散表現したとしたらメモリ効率がとても高くなります。
ただし、3次元ベクトルだと要素数が少ないので様々な特徴を表現するのは難しいです。もちろん、3つの実数値の組み合わせは無限に存在するので多くのことが表現できますが、コンピュータの数値計算の精度には限度がありまし、自由度の低さが問題となります。
なぜなら、ある特徴(あるいは特徴の集合)の大小関係を、一つの要素で表現しているので、3次元では3つの変数を持つ線形の式でトークンの特徴を表現していることになります。つまり、この3つの変数に複雑な特徴を押し込めているわけです。
変数の数が少ない、つまり自由度が低いと、トークン間の関係や文章の文脈を表現するが難しくなります。よって、分散表現が有限の次元数を使うといってもある程度の自由度は確保されている必要があります。
オリジナルのトランスフォーマーは、512の要素を持つベクトルを使いました。
また、分散表現を単語の埋め込み(word embedding)とも呼びます。「分散表現を生成する」という意味でもよく使われます。
ワンホット・ベクトルなどの局所表現ではトークン間の意味的な関係性を表現することが難しかったため、単語をより豊かな情報を持つ低次元のベクトルに変換する技術が「単語の埋め込み」として発展しました。
埋め込みベクトル
単語の埋め込みとは、単語を高次元の空間から低次元の連続的なベクトル空間に埋め込むプロセスを意味します。単語の意味的な情報を保持しながら、局所表現よりもコンパクトな分散表現のベクトルを生成します。また、単語の埋め込みによって生成さえたベクトルを埋め込みベクトルと呼びます。
例えば、犬と猫と人を次のような3次元の埋め込みベクトルで表現したとします。
犬:$${[0.8, 0.4, 2.5]}$$
猫:$${[0.7, 0.5, 8.5]}$$
人:$${[0.1, 0.9, -3.5]}$$
多くある特徴を少ない次元である3つの要素(変数)に押し込めて(埋め込んで)いるわけです。
例えばの話ですが、埋め込みベクトルのそれぞれの要素が次のような特徴に関するものだとします。
第一要素:走行の姿勢や能力
第二要素:言語や知性の発達
第三要素:危険察知や用心深さ
犬と猫は第一要素(走行)と第二要素(知性)で近く、第三要素(用心深さ)で異なっています。また、人は犬や猫とは3つの要素で異なっているのが数値として表現されています。
猫の方が用心深いとなっていますが、あくまでも例ですのであしからず。
つまり、似た概念のトークンが似た成分を持つようになるので意味の近さを計算することが可能となります。
よって、トークンを単なる記号として扱うのではなく、その意味や関係性を反映したベクトル空間に埋め込むことが可能となるということです。
埋め込みによってトークンのシーケンスが数値化されるので、機械学習モデルへの入力として使うことができます。
では、そもそも分散表現は具体的にどのように生成されるのでしょうか。
Word2Vec
分布仮説
word2vec(word to vectorの略)は分散表現の代表的な手法です。Googleのトマス・ミコロフらによって2013年に特許が取得され公開されました。
word2vecは分布仮説(単語の意味はその単語の周辺の単語によって定まる)を分散表現を行うための理論的な根拠としています。
なお、word2vecが分散表現を生成する手法にはCBOW(Continuous Bag-of-Words)とスキップグラム(skip-gram)の2種類があります。
CBOW
CBOWでは各単語の文脈(前後周りの単語)を入力として、その文脈に当てはまる単語を予測・推論します。
例えば、「猫がマットの上に座っている」という文章で「座って」という部分を見せずに予測させるものです。

これは大量のラベルなしデータを使うことが可能な手法です。
ニューラルネットワークを使った学習の処理は、以下のようになります。
ワンホット・ベクトルで局所表現(例えば1万次元に)された周辺単語を文脈としてニューラルネットワークに入力する。
ニューラルネットワークの隠れ層によって文脈の単語が低次元(例えば100次元)の埋め込みへと線形変換される。
これらを加算して一つの埋め込みベクトルにまとめる。
この隠れ層(中間層)から出力される埋め込みベクトルが予測される単語の分散表現となるわけです。
学習の損失計算のために埋め込みベクトルは、再び高次元(上例では1万次元)に変換され、ソフトマックスによって各単語(トークン)に対する確率分布へと変換されます。これに対して交差エントロピー損失を計算してニューラルネットワークのパラメータを調節します。
以上の処理によって、ターゲットとなる単語の意味が周辺の単語によって決まるように、埋め込みベクトルの分散表現が決まります。
なお、CBOWは連続したBoW(continuous Bag-of-Words)という名前からもわかるように、単語の順番を考慮しない学習手法です。入力自体は連続した単語の順番になっていますが、CBOWのモデル自体は文脈内の単語の順序情報を直接利用しません。
CBOWは周辺単語を順番や関係にかかわらず同じ重みで扱い、それらを加算して一つのベクトルにまとめます。そのため、モデルは入力された単語の並び順を認識せず、単に周辺単語が何であるかに基づいてターゲット単語を予測します。
順序情報を考慮するモデルとしては、例えばRNNやLSTM、あるいはTransformerなどがあります。これらの言語モデルは単語の順番や関係を含めた文脈を分散表現に含めることが可能です。
スキップグラム
逆に、スキップグラムではある単語を入力として文脈(前後周りの単語)を予測します。

CBOWと同様でニューラルネットワークを使います。ただし、そのアプローチは逆でターゲット(中心単語)からその周りの文脈(周辺単語)を予測します。その訓練は、以下のようになります。
ターゲットの単語をワンホット・ベクトルで局所表現(例えば1万次元)としてニューラルネットワークに入力する。
ニューラルネットワークの隠れ層によってターゲットの単語が低次元(例えば100次元)の埋め込みへと線形変換される。これが分散表現です。
隠れ層で得られた埋め込みベクトルを使い、周辺の各文脈単語を予測します。
予測として出力された各周辺単語における語彙全体に対する確率分布が計算されます。これが実際の文脈単語を比較され損失関数(クロスエントロピー損失)が計算されます。この損失を最小化するように、モデルの重みが更新されます。
スキップグラムは、比較的に低頻度の単語に強いと言われています。逆に高頻度の単語は多くの異なる文脈で現れるため、文脈予測が不明確になる可能性があります。
まとめると、スキップグラムは、ターゲット単語の周辺の文脈を予測することで、単語の意味や関係性を学習し、分散表現として埋め込みベクトルを生成します。これにより、単語の意味が周辺の文脈に基づいて効果的に学習されます。
主成分分析
Word2Vec(CBOW、スキップグラム)によって抽出された分散表現は単語の意味をうまく捉えているため、ベクトル演算を行うことができます。
有名な例は、「王様」ー「男性」+「女性」=「女王」があります。

上図では「王様」という埋め込みベクトルから、「男性」という埋め込みベクトルを引き算して、さらに「女性」という埋め込みベクトルを加算することで「女王」様子を表しています。
また、国名と首都名のベクトル値を関係性を表すこともできます。下図は、主成分分析(PCA)によって関係性を2次元に圧縮して表現したものです。

fastText
fastTextは、FacebookのAI研究チームによって2015年以降に開発された、単語の分散表現を学習するためのツールです。この研究にはGoogleからFacebookに移籍したトマス・ミコロフも含まれています。word2vecをベースにを開発しました。
サブワード情報の活用
fastTextは、単語をサブワード(n-gram)に分割し、それらのn-gramのベクトルを学習します。これにより、未知の単語や形態が異なる単語でも適切にベクトル表現を生成できるようになります。
例えば、"playing" という単語は "play" と "-ing" というサブワードに分割されます。これにより、"played" や "plays" などの関連単語も同様の意味を持つベクトルとして学習されます。
未知語への対応
Word2Vecなどの従来のモデルでは、学習中に出現しなかった単語(未知語、out of vocabulary、OOV)に対して、適切なベクトルを生成することができませんでした。fastTextはサブワードを利用することで、未知語にも対応でき、より柔軟に新しい単語を扱えるようになっています。
高速な学習
fastTextは名前の通り、学習速度が非常に速いのも特徴です。特に大規模データセットに対して効率的に学習できるように最適化されています。
ELMo
文脈によって変わる意味
word2vecでは多義性(単語には1つ以上の意味がある)を扱うことができません。そこで、ELMo(Embeddings from Language Models)がAllen Institute for AI (AI2) の研究チームによって開発されました。
2018年に発表されたこの研究では、文脈を考慮した分散表現が得られるようになりました。
つまり、文脈に基づいて同じ単語(トークン)に対して異なる埋め込みベクトルを生成できます。よって、単語の意味が文脈に応じて変わることを考慮できるようになりました。
双方向LSTM
ELMoは文全体の情報を反映した動的な単語ベクトルを生成するために双方向LSTMを用いています。
通常のLSTMは、テキストを一方向(例えば、左から右など)で処理しますが、双方向LSTMは前後両方の文脈を考慮するために順方向と逆方向にLSTMを適用します。
例えば、次のような文章から「銀行」の分散表現を作成することを考えます。
私は銀行にお金を預けに行きたい「銀行」の意味が周りの文脈によって決まるとしても、左から右へと文章を処理しただけでは、「銀行」が持つ意味を明確に捉えることができません。
むしろ、この文章では「銀行」の意味が「お金を預けに」という後続の文脈によって明白になり「金融機関」を指すことがわかります。
よって、右から左へと文章のシーケンスを処理することも含めることで「銀行」の前後の文脈を同時に捉えることができます。
CBOWに似ていますが、異なるのは文脈によって異なる意味を持つ単語を適切に扱うことができる点です。
文脈によってトークンの意味や関係が変わることを考慮した初期のモデルとして、Transformerのような後の技術の基礎と繋がるところがあります。
言語モデリング
ELMoは、事前に大量のテキストデータに対して言語モデリングを行い、各単語の文脈依存の分散表現を学習します。
最近はよく知られていることですが、言語モデルを訓練するための標準的な目的は、「与えられたシーケンスに続く、次に来るトークンを予測する」モデルを訓練することです。これを言語モデリングと呼び言語自体を学習(モデル化)します。
GPTやBERTが事前学習として言語モデリングを行うことで有名となりました。
この学習済みのモデルは、文脈に応じた動的な埋め込みベクトルを生成することができ、様々な自然言語処理タスクに利用できます。
実際にELMoを使う場合、まずELMoにトークンシーケンスを入力して文脈に依存した分散表現(埋め込みベクトル)を取得します。その後、この分散表現をタスク特有のモデルに入力して予測や処理を行います。
例えば、感情分析や質問応答、機械翻訳などのタスクで、文脈に応じた適切な単語ベクトルが使用されることで、パフォーマンスが向上します。
次回予告
今回は2018年のELMoまでを取り上げたことでだいぶ近年に近づいてきました。まだ、RNNやLSTMも紹介していないので少し飛ばしすぎた感がありますが、分散表現の進化の流れを追う意味では良い繋がりです。
また、分散表現と言語モデルの進化は密接に絡み合っており、分散表現の背景知識があれば、その後の言語モデルの発展をより深く理解する助けになります。
一方で、トークン化に関しては前回に紹介した初期のトークン化手法で止まっています。そこで次回は、より近代的なトークン化であるBPEやSentencePieceを取り上げます。
お楽しみに!
