読者です 読者をやめる 読者になる 読者になる

終末 A.I.

Deep Learning を中心に、週末に機械学習するエンジニアのブログ

Skip-Thought Vectors を解説してみる

機械学習 RNN 自然言語処理 論文

本日は、インスピレーションと予算の枯渇のため、実験ができていなかったので、論文の解説をいたします。まあ、解説とか偉そうなことを言っていますが、主に自分用のメモみたいなものなのですが。

紹介する論文は、「Skip-Thought Vectors」です。この手法は、文(センテンス)をベクトル化する手法の一つで、様々なNLPタスクで好成績を挙げたことで知られている去年の6月にarxivに公開された論文です。ちなみに著者の方が Theano 上で動くソースコードを公開しているので、実際に動かしてみることも可能です。(ただし、学習に時間がかかる) github.com

さて、この Skip-Thought Vectorsのですが、最大の特徴は教師なし学習でかなり質の高い文ベクトルを生成できる点にあります。実際に使用する入力データは、文章のコーパス(論文中ではブックコーパス)だけでできてしまいます。計算資源さえあればOKという、日曜大工な人間には最高に相性の良い手法となっています。

その構造ですが、下記の図が一番わかりやすいでしょう。入力しているのは、文書中のi番目の文。出力は、同じくi-1番目とi+1番目の文である入力文書の前後の文です。正確に言うと、入力文を元に文ベクトルを生成するエンコーダと、文ベクトルを元に前の文と次の文を生成する2つのデコーダから成っているモデルです。

論文中では、エンコーダに用いたモデルはGRU、デコーダに用いたモデルは conditional GRUを使用していますが、エンコーダ・デコーダとして使用できればモデル上なんでもいいことになります。

f:id:KSKSKSKS2:20160424184856p:plain

では実際にどのように学習していくのか。手順は下記になります。

  1. エンコーダに入力となる文を最後まで入力する(入力に用いる単語ベクトルはあらかじめ用意しておく。ID形式とかなんでもOK)。
  2. エンコーダの学習により獲得した隠れ層の値を入力文のベクトルとして使用する。
  3. デコーダに入力文の引数と、生成する文の一つ前の単語を入力する(最初の単語の場合は、eos 記号を入力とする)。
  4. デコーダのこの時の隠れ層の値と、出力される単語に対応する語彙ベクトルの内積を求め、この値をその時点での該当単語の出力される確率として扱う。
  5. 出力文の最後まで 3−4 の操作を繰り返し、単語生成確率の和を求め、この値が最大化されるようにエンコーダとデコーダのパラメータを学習する

デコーダは、前の文を生成するものと次の文を生成するものの2つがあり、基本的にそれぞれで使用するパラメータは違うものを使用しますが、語彙ベクトルだけは共通のものを使用します。というわけで、以上で学習は完了です。簡単ですね!

注意点としては、学習時に出現していない単語がテストセットに含まれている時の扱いです。論文中では、テストセットと学習セットに含まれる単語をword2vec等でベクトル化した後、学習セットに含まれる単語のベクトルを word2vec ベクトルから学習時に使用したベクトルに射影する線形変換を学習しすることにより、未知語の表現を獲得しエンコーダでも使用できるようにしています。 デコード時に出力される語彙に関する言及は特にないので、増やすことについての考慮は特にされていないと思われます。難しそうですものね。

また、学習時に使用する文ですが、 attention mechanism (参照:Neural machine translation by jointly learning to align and translate.) を使用して、適切な単語のみを考慮して学習できるように一部改変しながらもちているようです。

というわけで、後はエンコードしたりデコードしたりして遊んでみてねーとのことですね。エンコーダ・デコーダに使用するモデルを変更してみても面白いかもしてません。

2016.04.30 追記

attention mechanism については、エンコーダーデコーダーモデルにそういう+αもあるよという一般的な説明であって、実際に論文で説明している手法には使用されていないようです。