【Coursera】Deep Learning Specialization - Course 5: Week1 Recurrent Neural Networks
今回からCourse 5のSequence Modelsをやっていきます。 まずはWeek 1です。前回の記事はこちら
Recurrent Neural Networks
Why sequence models
- シーケンス(Sequence)データを扱う例
- 入力と出力は少なくともどちらか一方はシーケンスデータである.
Notation
- 今後は以下の表記を用いる,
- 入出力データにおける 番目の要素をと表す.
- 番目のトレーニングデータについて、入力データと出力データの長さをと表す(ただしとは限らない.)
- つまり番目のトレーニングデータの 番目の要素はと書ける.
- どのように各単語をデータとして扱うか?
- 頻出の単語の上位リストやオンライン辞書を用いて辞書のリストを構築する(商業用ではふつう10万語くらいのサイズに及ぶ.)
- 各単語はOne-hotベクトル(1つの要素のみ"1"で残りが全て"0"なベクトル)にして扱う.
- 辞書にない単語が現れたらどうするのか?
- "Unknown word"というトークンを用意してそれを割り当てればよい.
Recurrent Neural Network Model
- NNをそのまま適用するには2つの問題がある.RNNはこれらの問題を解決する.
- 入力および出力はデータごとに異なる長さを持つ.
- テキストの異なる位置の特徴を共有できない(つまり、ConvNetのように異なる位置にあっても似た特徴は同じように学習されてほしい.)
- RNN(Recurrent Neural Network, 再帰型ニューラルネットワーク)では活性化関数の出力を次のタイムステップの活性化関数に渡している.
- の活性化関数に渡す値はランダムに初期化しても良いが、0でpaddingしたベクトルを用いるのが一般的.
- RNNの弱点は、ある入力に対してそれ以前のシーケンスの情報しか見ないという点である.
- ふつう特定の単語に対して、その単語の後ろの文からも意味を推測するはずである.
- この問題はBRNN(Bidirectional RNN, 双方向再帰型ニューラルネットワーク)を扱う際に説明する.
- 2種類の活性化関数を計算する.
-
- のように書くとシンプルな表現で済む(行列を横に並べただけ)
- ReLUでもよいがtanhを用いるのが一般的.
-
- 目的に応じて関数を選ぶ(2値問題であればsigmoid.)
-
Backpropagation through time
- ロス関数は次のように定義できる.
- 時間軸とは逆方向に伝播することからBackpropagation through time(BPTT)と呼ばれる.
Different types of RNNs
- 入力の次元と出力の次元が一致しない場合はどうするか?
- RNNアーキテクチャは4種類存在する.
- (One-to-one:これは単なるNNなのでRNNにする意味はない)
- One-to-many:各タイムステップの出力を次のタイムステップの入力に用いる(ex. 音楽生成)
- Many-to-one:最後のタイムステップでのみ出力する(ex. 感情分類)
- Many-to-many(入力と出力に対応がある場合):各タイムステップでを出力(ex. 固有表現抽出)
- Many-to-many(入力と出力に対応がない場合):全ての入力した(Encoder層)後に出力(Decoder層)を設計する(ex. 機械翻訳)
Language model and sequence generation
Sampling novel sequences
- 構築した言語モデルがどのようになっているかを直感的に理解するにはサンプリングを行うのが良い.
- 各タイムステップにおける出力から確率の高いものをランダムに選び、それを次のタイムステップの入力とする.
- これを繰り返して出来上がった文章を見ると、トレーニングデータの文章の雰囲気に近いことが分かる.
- アプリケーションによっては、単語単位ではなく文字単位で言語モデルを構築することもある.
- 辞書を作らなくてよいので
を考慮する必要がなくなるメリットがある. - 文章のように多くの単語を幅広く見る際には適さず、学習する計算コストも高くなる.
- そのため大抵は単語レベルでの言語モデルが一般的.
- 辞書を作らなくてよいので
Vanishing gradients with RNNs
- RNNはどのレイヤでも同じパラメータを採用しているため、勾配消失や勾配爆発の問題が起きやすい.そのため、1ステップ前や2ステップ前の影響は大きいが、早い段階のタイムステップからの影響は小さくなるため、広範囲のタイムステップでの学習は難しい.
- 勾配が爆発しているときは計算結果がNaNとなってしまうため発見が容易である.この場合は、勾配がしきい値以上になったらスケーリングを行う手法(Gradient clipping)を用いることで対応できる.
- 勾配消失問題を解決する方法は次のビデオから説明していく.
Gated Recurrent Unit (GRU)
- 新しい変数を導入する.この変数は浅い層の情報を深い層に伝える役割があり、Memory cellと呼ばれる.これを用いることで勾配消失の問題を解決することが出来る.
- 新しい入力のたびに以下の式に基づいてを更新する.
-
- 入力の記憶した方が良い部分を考慮したの候補値(ex. 主語が単数形から複数形になった.)
-
- [tex: \tilde{c}^{\lt t>}をどの程度考慮して更新(Update)するかを表す更新ゲートを意味し、0から1の値をとる.
-
- 実際に行う更新.はelement-wiseな掛け算.
-
- はすべて同じ次元である.そのため、ベクトルの各要素ごとに記憶の維持or更新をすることができる.
- 実際にはこれに加えて関連ゲート(Relevance gate)と呼ばれるを計算する必要があり、上記の式は以下のように修正される.
- 多くの研究者が様々なバージョンのunitやその組み合わせを設計し、より良いRNNを模索してきた.LSTM (Long Short Term Memory)もその1つである.
Long Short Term Memory (LSTM)
- LSTMはGRUを一般化したもので、より強力である.GRUとの相違点は以下の通り.
- 関連ゲートが存在しない.
- 忘却ゲート(Forget gate)と出力ゲート(Output gate)が存在する.
- LSTMの更新式は次のように書ける.
- この他にも、例えばゲートの計算にも用いるのぞき穴接続(Peephole connection)と呼ばれるバリエーションもある.
- 歴史的にはLSTMの方が早く、GRUはLSTMを簡略化したものとして登場した.一般的にどちらが良いかの結論はない.
- GRUはシンプルなモデルなので複雑で大きなモデルを構築するのに適しており、計算も少し早い.
- LSTMはゲートが3つあるので複雑な処理が可能.
Bidirectional RNN
- これまで議論したRNNは初めのタイムステップから前方向にのみ計算を行っていたため、それよりも後ろのタイムステップからの寄与は考えられていなかった.そこで、前方向からの計算の次に後ろ方向の計算も行い、両方の寄与を用いて出力を計算する.
- Bidirectional RNN(BRNN)の式は以下のように書ける.
- RNNのBlockはGRUやLSTMを用いても良い.自然言語処理ではLSTMを用いたBRNNが一般的である.
- ただしデータ全体が入力として必要になるため、音声認識のようなリアルタイムで処理が必要な場合にBRNNが適するかどうかは考える必要がある.
Deep RNNs
- より複雑な処理をするためにRNNを積み重ねるDeep RNNという方法もある.
- 時間軸方向の同じ層ではパラメータは共有される.
- 時間軸方向で既に層が深いので、ふつうはRNNを2, 3層積み重ねる程度である.
- もちろん、ブロックはGRUやLSTMを使っても良い.
- 各タイムステップの出力を一般的なDNNの入力にする方法もある.