単語を、適当な次元のベクトルで分散的に表す表現を(ひとつの成分だけ1、他は0と言った局所表現に対して)単語の分散表現といって、word2vec(Skipgram)やLDA・共起表現などのようないろいろな手法がある。
これと同じように、文(単語の連続, “I saw him swimming.” など、ピリオドまでのまとまり)の分散表現を作るにはどうすればよいか?というのが今回のテーマだ(筆者個人的には、文や単語をベクトルで表現する事自体が良いアプローチではない、と考えている:別記事で後述予定)。
今回は、その方法の一つであるRecursive Autoencoderについて取り扱う。
Autoencoderとは何か
Recursive Autoencoderは、Autoencoder(オートエンコーダー)を組み合わせることによって文の意味表現もひとつのベクトルとして表そうとしたモデルである。
Autoencoderというのは、インプットベクトルを受け取ったら、それと同じアウトプットを出力することを目的とした特殊なニューラルネットワークモデルのひとつで、次のような図で表される。
入力次元よりも隠れ層の次元が大きければ入力をただ単に出力
に受け流すという自明な解が存在するので、通常隠れ層の次元は入力層より小さいのが一般的である。そのとき、隠れ層の値は入力ベクトルの圧縮表現になっている。つまり、隠れ層は「学習した重みと掛け合わせることでインプットが再現できるベクトル」であり、隠れ層の次元は入力ベクトルの次元より小さくなっているので、オートエンコーダーはベクトルの次元縮約器と解釈できる。(アウトプットは特に重要ではないので捨てちゃうのが普通)
Autoencoderは教師データが必要ない(入力が教師データなので)ので、無教師学習に分類される。を出力層として、二乗誤差は
Cross Entropy誤差は
と表される。もちろん、は
を隠れ層、
をバイアス
を重みとして、
と表される。はsigmoidなどの活性化関数である。トレーニングなどは通常のNNと同じ。
ちなみに、Autoencoderの最も代表的な使いみちは深層学習のプレトレーニングで使われるStacked Autoencoderだろう。こちらに関しては既に扱っている文献が多いのでそちらを参照されたい。
Recursive Autoencoder
Recursive Autoencoderは、Autoencoderを次のように積み上げる。
一番下の各は、文内の各単語の分散表現だ。まず文章内の単語を二分木で表すのが第一ステップとなる。
は、ベクトル
と
を単に縦に連結させたベクトルである。この2つのベクトルをAutoencoderで圧縮し、その隠れ層をベクトル
とする。(出力はいらないので無視)次に、
と
の連結を圧縮し、
を作る。このように単語を再帰的に圧縮していってできた最後のベクトル
が、この文の分散表現となる。
文から上図のような木を作る手法は様々だが、次のようなgreedyな手法が用いられることが多い。
- 文中の単語数をn個として、隣り合うn-1個のペアを考える。
- それぞれのペアのReconstruction Errorを計算する。
- その中で一番小さいエラーのペアを選択し、実際にペアを作る
- ペアをひとつの単語(ノード)に見立てて、1〜3を繰り替えす。
隣り合う単語しか見ないので完全なアルゴリズムではないが、妥当な時間でそこそこ良い結果を与えることが知られている。
オートエンコーダーの性能の尺度であるReconstruction Error(ノードのエラー)は次のように表される。
はノード
に含まれている単語数。長い単語の連続ほど再現が難しくなるので、重みをつけている。また、全ツリーのコストは単にこれらのエラーの和とすればよい。
これを使って文のクラス識別器を作る場合、上図のように最終的に得られたn-1個の隠れ層を入力として、各クラスの確率分布を出力とするニューラルネットを新たに作れば良い。各
のラベルはすべて文のクラス(ラベル)と同じとする。教師データは該当クラスが1、他が0担っているベクトルである。
これはあくまでクラス識別や類似性評価に使うものであるので、このベクトル自体から文の意味を抽出して推論などができるかと言われれば、それはできない。しかし、Recursive Autoencoderを使えば文のクラス識別を、人間の手作りの特徴(e.g.センチメント解析ならポジティブ・ネガティブを表す特徴語)を使うことなく行うことができるという点では非常に便利なモデルである。
Be First to Comment