TensorFlow: Recurrent Neural Networks
Introduction
まず,LSTM articleを読んだほうがいい.わかりやすいので読んだほうがいい.
rnn_cell.pyを見ると,
- BasicRNNCell: 普通のRNN
- BasicLSTMCell: peep-holeがないLSTM
- LSTMCell: peep-holeがあるLSTM. さらに,cell clippingとprojection layerがoptionとして用意されている
- GRUCell: Gated Recurrent Unit, input gateとforget gateを一緒にして,さらに,cell stateとhidden stateを一緒にしたLSTM簡易版
が,現時点(20151228)LSTMのアーキテクチャとして用意されている.
他にもいろいろバリアンスは考えれるけれど,Greff, et al. (2015)によると,どれも大差なく,forget gateの役割があることとoutput activation functionがあることが重要とのこと.また,Jozefowicz, et al. (2015)によると,LSTMのアーキテクチャは,タスク依存の部分もあるとのこと.なので,上記くらいのLSTMのアーキがあれば,基本は十分と思われる.
また,rnn_cell.pyをみると,InputProjectionWrapper, DropoutWrapper, EmbeddingWrapper, OutputProjectionWrapperと典型的にLSTM前後に挟むレイヤーのラッパーが用意されている.
ちなみに,この記事を書いている時点では,RNNCellはstateを保持しない実装になっている.この辺は議論されているよう.なので,python apiにはrnnの項目がまだない.
Language Modeling
単語列が与えられたらその次に出てくる単語を当てるという問題.Penn Tree Bank (PTB) Datasetを使って行う.
Tutorial Files
File | Purpose |
ptb_word_lm.py | The code to train a language model on the PTB dataset. |
reader.py | The code to read the dataset |
Download and Prepare the Data
wget http://www.fit.vutbr.cz/~imikolov/rnnlm/simple-examples.tgz
で既に前処理済みのデータを持ってくる.10,000単語くらいあって,rare wordsは"<unk>" symbolになっていて,end-of-sentence markerも付いている.
simple-examples.tgzの中身をみると,data以外にも幾つかサンプルがある.charactor-basd RNNのサンプルも入っている.
./simple-examples/data/ptb.train.txt を見るとptbデータは非常に長い1doc分のデータのようになっている.
The Model
モデルの説明.
LSTM
RNNでもbatch単位で実行するのは一緒.擬似コードは以下.
lstm = rnn_cell.BasicLSTMCell(lstm_size) # Initial state of the LSTM memory. state = tf.zeros([batch_size, lstm.state_size]) loss = 0.0 for current_batch_of_words in words_in_dataset: # The value of state is updated after processing each batch of words. output, state = lstm(current_batch_of_words, state) # The LSTM output can be used to make next word predictions logits = tf.matmul(output, softmax_w) + softmax_b probabilities = tf.nn.softmax(logits) loss += loss_function(probabilities, target_words)
Truncated Backpropagation
長ーい系列を全部を見て,backpropするとうまく学習できないので,ある程度の長さでgradientを打ち切る.
が本問題のサンプルコードになっている.サンプルコード上は,PTBModelのinitでunrolled graphを作って,run_epochでデータセットを一回なめている.1 epoch経つとstateを0に戻す.
扱うタスクに依っては,RNNではbatch単位でstateを忘れたり(0に戻す)するが,ptbは,非常に長い系列なので,データの作り方を工夫(reader.py#ptb_iterator)して,batch単位でstateを忘れないようにし,batch単位でstateを引き継いでいる.そして,次のepochではstate を0にしている.
サンプルコードはいちからtruncated backprop用のunrolled graphを作っているが,rnn.pyにcellだけ指定すれば,RNNを作ってくれる便利モデルがある.
def rnn(cell, inputs, initial_state=None, dtype=None, sequence_length=None, scope=None): """Creates a recurrent neural network specified by RNNCell "cell".
こんな感じのインターフェイスになっているので,documentをまたぐとかuserをまたぐときに,initial_stateを0にして,前の状態を忘れればいいと思う.
Inputs
この次の単語予測の問題では,indexingされた単語が入力なので,
# embedding_matrix is a tensor of shape [vocabulary_size, embedding size]
word_embeddings = tf.nn.embedding_lookup(embedding_matrix, word_ids)
な感じで,word embeddingしてからLSTMに入れる.
これでは,線形変換の行列は,での変換だけれども,rnn_cell.pyのlinear関数では,の変換になっており,わざわざcell sizeにprojectionしないでも良いようになっている.
Loss Fuction
over wordsで誤差を計算する.
このインプリは簡単だけど,sequence_loss_by_exampleが定義されているので,これを使って良いとのこと.
実際の典型的な評価基準は, average per-word perplexity (just called perplexity)を使う.
lossにexpをつけただけ.
Stacking multiple LSTMs
LSTMをstackしたかったら,interfaceが用意されていて,
lstm = rnn_cell.BasicLSTMCell(lstm_size) stacked_lstm = rnn_cell.MultiRNNCell([lstm] * number_of_layers)
な感じで,cellを作ってから,積み重ねたい分(number_of_layers)だけ,cellを積み重ねる.
Run the Code
とりあえず,動かしたいなら
cd tensorflow/models/rnn/ptb python ptb_word_lm --data_path=${/tmp/simple-examples/data} --model small
こうする.
modelのサイズに依ってperplexityが変わることがわかる.small, medium, largeが用意されていて,largeなほどperplexityが小さくなる.