ありまっくすのへっぽこ日記

アラフォーでへっぽこエンジニアをしております。へっぽこなりに頑張っています。

DeepLearning講座(第4回)を受けてきたよ

5/26にDeepLearning講座を受けてきました。今回のテーマは「時系列」でした。

 

最適な初期化

ResNetでパフォーマンスが上がらず、苦しんでいたのですが、理由を講師の方が説明してくださいました。

修正前

shortcut = Convolution2D(n_filters, (1,1), strides=(1,1),kernel_initializer='he_normal', padding='valid')(inputs)

修正後

shortcut = Convolution2D(n_filters, (1,1), strides=(1,1), padding='valid')(inputs)

※he_normalはheの正規分布

初期値の設定方法

今までは「適当に」初期値をとっていたのですが、SGD(確率的勾配降下法)は初期値に依存します。つまり、「良い初期値」で初期化すればより良い答えに到達するわけなのです。

初期化にはheまたはXavierを使うと良いです。

で、heとかXavierって何よ??となるわけですが

Sigmoidの場合
  • 0から1の一様乱数で初期化:0に近いか1に近い値しかとれなくなってしまい、勾配消失してしまう。
  • 0から1のガウス分布正規分布)で初期化:0付近の値しか取れなくなってしまう。
  • Xavierで初期化:いい感じにばらけてくれる。
ReLUの場合
  • 0から1の一様乱数で初期化:多層にするとほとんど0しか取れない
  • 0から1のガウス分布正規分布)で初期化:改善されるけど、まだ0に偏る
  • heで初期化:いい感じでばらけてくれる

(詳細はこちら)

http://murayama.hatenablog.com/entry/2017/11/25/231609

 

時系列処理

時系列とは株価、天気、言語など連続しているものです。以下の特徴が挙げられます。

  • 過去のデータが今の状態に影響している(株価が上昇トレンドなのが影響されるなど)
  • 過去のデータを保持しておく必要がある

画像分類など違って「過去のデータをどうするか」ということがポイントになってきます。つまり、過去のデータを持ってくるループが必要になってくるわけです。

f:id:ari_max:20180605122747p:plain

BPTT

時系列の学習方法として、Back Propagation Trough Time (BPTT)を使います。BPTTはループしている部分を展開し、中間層がたくさんある巨大なニューラルネットワークとして扱っています。

つまり、Back Propagationの概念が使えるということです。

ただし、最初の方の情報が消えてしまうということと、多層であることから勾配消失または勾配発散してしまうという特徴があります。

 

f:id:ari_max:20180606063251p:plain

ループ部分を展開したイメージ

LSTM

RNN(リカレントニューラルネットワーク)では前の情報を忘れてしまうという特徴があるので、時系列を扱うには限界があります。(前の情報でも重要なことは覚えておきたいし、逆に必要のないものは忘れたい)

そこで、出てきたのがLong-Short Term Memory(LSTM)です。

  • 登場は1995年
  • Forget Gateつきの1999年バージョンが有名

 

 RNNからLSTMへ

まずは、活性化関数にtanhを使うRNNを考えてみます。Xが入力、hが隠れ層、Yが出力です。

f:id:ari_max:20180606065130p:plain

 忘却ゲートの追加

Cというのがメモリセルです。このCに忘却ゲートを追加し、忘却ゲートでメモリセルの情報を制御します。0の場合は完全に忘れ、1の場合は完全に覚えています。

f:id:ari_max:20180606065338p:plain
忘却ゲート導入

 

忘却ゲートが導入されることにより、覚えていた情報を「一気に忘れること」ができるようになりました。

入力ゲートの導入

次に、入力ゲートを導入します。というのもRNNでは「忘れたい情報」がある一方で「上書きされたくない、覚えておきたい情報」もあるという相反する要請があるためです。入力ゲートが開いている時だけ、メモリセルに記憶ができるようにします。

 赤く囲んだところだけ見ると、普通のRNNと同じです。

f:id:ari_max:20180607215620p:plain

入力ゲート導入

σが0であれば、何も入力されないというところがポイントです。

重み衝突

覚えておきたい情報は重みを大きくして、活性化されるようにします。が、覚えなくてもいい情報も記憶されてしまい、情報が上書きされてしまいます。このことを重み衝突と言います。

入力ゲートがあることで重み衝突を避け、覚えておきたい情報を減衰しないようにできます。

 

出力ゲートの導入

今度は出力ゲートを導入します。入力ゲートの時と考え方は同じで、出力ゲートが開いている時だけメモリセルの情報を出力します。

f:id:ari_max:20180607225544p:plain

出力ゲート導入


ステップとしては以下のようになります。

  1. 忘却ゲートで、使わなくなった情報をメモリから消す
  2. 入力ゲートで、必要な情報だけメモリセルに入力する
  3. 出力ゲートで、必要な情報だけメモリセルから出力する

実際にうまくいくのかというと難しいです。というのも

  • 覚えなくてもいい情報をメモリセルに溜め込んでしまう
  • 複数のメモリセルに同じメモリセルに記憶してしまう

そのため、学習には色々な調整と長い学習時間が必要になります。そこで簡略化バージョンが取り入れられました。

  • Gated Recurrent Unit (GRU)
  • Minimum Recurrent Unit(MRU)

GRUはメモリセルを廃止して、忘却ゲートと入力ゲートを合わせて更新ゲートとしたもので、使用頻度も高いそうです。

 

Word2Vec

自然言語処理デファクトスタンダード。以下のように、単語をベクトル化し、分散表現で分かりやすくしています。

JapanーTokyo

FranceーParis

自分で実装するのは難しいので、Mechab とGensimを使うと楽です。

分布仮説

類似した文脈に出てくる単語は似た意味を持つという仮説の事です。

例えば「私は〇〇を食べる」という文章だと、〇〇には食べ物が入るはずです。〇〇に当てはまる言葉は「食べ物」という同じ方法のベクトルになります。

シンプルな仮説ですが強力です。例えばWikipediaのようにたくさん文章があるサイトからデータを取ってきたとすると、かなりの数の単語がベクトル化できるはずです。

 

seq2seq

Encoder-DecoderModelの一種です。Encoderでは入力を処理して最終的に一つのベクトルにし、DecoderではLSTMの内部状態を処理して単語を出力します。

f:id:ari_max:20180608000111p:plain

EncodingDecoding