The Pitcher in the Rye

I'd just be the catcher in the rye and all. I know it's crazy, but that's the only thing I'd really like to be.

詳解ディープラーニング(第1版)の読書メモ

ずっと積ん読してた詳解ディープラーニング(第1版)を読みました

詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~

詳解 ディープラーニング ~TensorFlow・Kerasによる時系列データ処理~

  • 作者:巣籠 悠輔
  • 発売日: 2017/05/30
  • メディア: 単行本(ソフトカバー)

ずっと積んでるうちに第2版が出てしまっていました。。。

まあ、pytorchに対応したりtensorflowのバージョンが上がったりといった実装としての記述が変わっただけのようなので、時系列データを扱うディープラーニング(RNN系)の理解のためには第1版のままでも良いかなと思い一通り読んでみたので、自分のためのメモをここに残しておこうと思います。

ざっと読んだだけなので、あまり理解出来てなくて間違った解釈をしているところがあるかもしれませんので、詳しい人がこのブログを見ていたら優しく指摘してもらえると大変助かります。

また、以下のメモは自分が理解する為に書いたものなので、書籍に書いてない部分を想像して書いているところや、メモだけでは意味がよくわからない記述や、一部単なる感想を書いているところもありますので記述の統一感の無さ等に関してはご容赦いただければと思います。

以下にメモを書きます。

1〜2章は準備部分でそれほど面白い内容はなかったので、特にメモは無しです。

3章 ニューラルネットワーク

  • 単純パーセプトロン
    • 複数の入力、1つの出力でかつ活性化関数がステップ関数の1層のニューラルネット
    • 入力が二つだと単純で分かりやすい。
    • 2値分類になる。ある入力(x1, x2)が y=0, 1の2値分類する。
  • ロジスティック回帰(1出力)
    • 単純パーセプトロンの活性化関数をシグモイド関数にしたもの。
    • 尤度関数を最大化する最尤法で解いているので、最小二乗法になれた身としてはわかりづらかった。
    • 最尤法と最小二乗法で線形最適化問題を解く例は下記を参照。
    • 勾配降下法として確率的勾配降下法が説明されている。
      • 勾配降下法は損失関数をパラメーターwとbで偏微分して、学習率ηをかけた変化分をくわえながらwやbを更新していく。
        • 学習率ηは一般的に0.1などが使われる。
      • Δw = wk - w_k-1 の変化が閾値以下になったら収束と見なせる。
      • 学習率ηは実際に変化率に対してどれだけ大きく更新するかの更新量に影響する。
        • 大きすぎると収束しないし、小さすぎると収束に時間がかかる。
      • N個のデータx_n(n = 1〜N)に対して1つのバッチで勾配降下法を使うのが普通の勾配降下法。
      • N個のデータからランダムにいくつかのデータを選んでMグループを作ってこれらのグループ毎に勾配降下法を行って、値の平均値を採用するのが確率的勾配効果法。
        • これらのM個のグループをミニバッチと呼んだりする。
        • 更新量が閾値以下になって収束するのは稀なので、K回のイタレーションで止める。それでも平均すれば確率的には良い値になるはずという理屈。
    • 2値分類ではなく確率が出力されるが、線形の分類問題。
      • ある入力(x1, x2)が平面にプロットされて、それを分類する直線が存在し、そこから離れるほどその分類の正しさが確率が高い値になるようなイメージ。
  • 多クラスロジスティック回帰
    • 出力が複数出力(k個)になったロジスティック回帰。
    • 活性化関数がソフトマックス関数になる。シグモイド関数をk個足して確率が1になるように調整したような関数。
    • パーセプトロンからここまで全てが線形分類。
      • 平面にプロットされた点の分類の観点で見ると、複数の分類のために複数の直線が引かれるようなイメージ。
  • 多層パーセプトロン
    • ここで初めて中間層(隠れ層)が登場し3層以上になる。
    • 勾配計算のために、偏微分を計算するのだけど、複数層になると普通に順番に偏微分していくと煩雑になるので、誤差逆伝播法を使う。
      • 最終レイヤーの活性化前の出力による損失関数の偏微分は正解値と出力値との誤差(O-C)なので、それを入力として(チェインルールで偏微分を分解して)ニューラルネットを逆に辿っていけば、最初の入力レイヤーの値の偏微分まで辿り着いて、全レイヤーでのパラメータの偏微分が求まる。
        • これが誤差逆伝播法。逆伝搬で考えると行列式で解けるので並列化もできて一石二鳥。
          • 順方向にニューラルネットを辿っていくと、最終結果は様々な出力のコンボリューションになるけど、逆からだとパラメータの影響が単純に放射状に増えていくだけになることから定性的に理解できる。
    • 隠れ層があることで線形なパラメータのコンボリューションになるのでそれで非線形性が表現できる。
    • 平面プロットの分類の観点で見ると、分類の線は直線ではなく曲線になる。

4章 ディープニューラルネットワーク

  • ディープラーニング(3層以上のディープニューラルネットワークによる学習)
    • かつては、隠れ層を増やしたニューラルネットワークは使われていなかった。下記のような課題があったため。
      • 勾配消失問題
        • シグモイド関数は端っこの微分値がほぼゼロでまた最大でも傾きが0.25なので、隠れ層が多くあると、その微分値を掛け合わせることでどんどん誤差項が小さくなっていく。→勾配の消失。誤差逆伝播での勾配が小すぎるということは、どれだけ学習してもパラメータがほとんど更新されないことになってしまう。
        • 解決策としては中間層の活性化関数のみ以下のような活性化関数を採用する。(最終層は、ソフトマックス関数やシグモイド関数など)
          • tanh(ハイパボリックタンジェント
          • ReLU(Rectified Liner Unit)
            • ReLUは傾き1の部分(x > 0)では微分値が必ず1なので、誤差逆伝播でも勾配が小さくならないが、傾き0の部分(x =< 0)は常にゼロなので一度でもゼロになると、そのエッジは学習の間ずっとゼロのままになってしまう。
          • LReLU(Leaky ReLU)
            • ReLUを改良して(x =< 0)の部分にも微小な傾きをつけて勾配の消失を防ごうとした活性化関数。
          • PReLU(Parametric ReLU)
          • RReLU(Randomized ReLU)
      • オーバーフィッティング・オーバーラーニング(過適合・過学習
        • 解決策としては下記。
          • ドロップアウト
            • 学習の際にランダムにニューロンを除外する。(ネットワークをシンプル化して汎化性能を高める)
            • ドロップアウト確率としては一般的に0.5が使われる。
          • アンサンブル学習
            • 複数のモデルで学習してその平均値をとる。→ドロップアウトは擬似的なアンサンブル学習と呼べる。
    • その他の問題
      • 局所最適化への対処
        • モメンタム
          • 学習率を0.1などの固定にせずに、最初は大きく徐々に小さくする。
          • 学習率そのものをは変化させずに、モメンタム項という調整項を更新して行き、擬似的に学習率を調整する。
          • 物理現象との対応で言えば、落下運動に空気抵抗に相当する項(速度に応じて抵抗が生じる)を加えるようなもの。
        • Neserovモメンタム
          • 次のステップの更新量近似値がわかるようになり、どの方向にパラメータを更新すべきかをモメンタムの式に織り込んだもの。
        • Adagrad(Adaptive gradient algorithm)
          • モメンタムは学習率の値自体は一定で、モメンタム項を更新することでパラメタ更新していったが、Adagradでは学習率の値そのものをパラメータとして更新していく。
          • 勾配の2乗累積和のルートを取ったもので、学習率を割る。
            • 累積和であるため単調増加して行き、学習率はどんどん小さくなる。
              • ただし累積の変化については、勾配が大きい時は小さく、勾配が小さくなると大きくなる。
          • モメンタムと比べてハイパーパラメータが少なく、これまでの勾配に基づき自動で学習率ηを修正するのでより扱いやすい手法。
        • Adadelta
          • Adagradは勾配の累積和で学習率を割るため、学習のステップが進むと学習率が極端に小さくなって、学習が進まない場合がある。
          • そのため、ステップ0からの全ての2乗和を累積させるのではなく、定数w分だけ(wステップ分の和)に制限する。
          • ただし、定数w分の更新量を全部保持しておいてその都度、計算をするのはメモリを食うので、ステップ数を遡るほどその勾配の寄与を減衰させるような減衰平均の式を用いて計算を行っている。減衰を調整するパラメータはρでこれでどのくらい減衰させるかを調整する。
            • 一般的にρ=0.95を用いる。
        • RMSprop
          • Adadeltaと同じような制約を求めるが、Adadeltaの簡易版。
        • Adam(Adaptive moment estimation)
          • Adadeltaの減衰平均に加えて、単純な勾配の移動平均の項も加えたもの。
            • Adadeltaでやっているのが、勾配の2次モーメント(分散)による調整だが、Adamでは1次モーメント(平均)も加えて調整している。
      • オーバーフィッティングへの対処
        • Early Stopping
          • 学習率ではなく学習回数(イテレーション回数=Epoch数)に対する調整。
          • 処理は単純で前のEpochに比べて、誤差が増大していたらそこで学習を打ち切るだけ。
      • Batch Normalization
        • ミニバッチ毎にデータセットを正規化(白色化)し、重みの初期値を調整して学習をうまく行きやすくする。

5章 リカレントニューラルネットワーク(RNN)

  • RNN
    • RNNは系列データを扱うときに使われる。(音声、文字列など)
    • RNNは時刻tにおけるニューラルネットの隠れ層に対して、時刻t-1の隠れ層の入力を追加しただけ。
      • この時刻t-1の隠れ層の影響が逐次的に累積していくので系列データを扱うことができる。
    • 損失関数は時刻t=0〜Tの全ての出力と正解値との二乗誤差(O-C)2の和で、これを最小にする。
    • 誤差逆伝播時の注意
      • 時刻t=t1のときの出力値から誤差逆伝播するときには、隠れ層がt=0〜t1まで連なっているので、時刻を遡って逆伝搬する必要がある。
      • 全ての時間を遡る必要はなく、τ分遡ってそれを入力とするようなモデルで学習する。
      • Τを大きくして長期間遡ろうとすると勾配消失が発生する可能性が高くなる。
  • LSTM(long short-term memory)
    • RNNで活性化関数をシグモイド関数などにすると、長期間過去に遡ったときに勾配が消失してしまい、過去のデータによる重みを学習できなくなってしまう。
      • 上記を防ぐために、いくつかの手法がありそれを取り入れたのがLSTM。
    • CEC(constant error carousel)
      • 過去の隠れ層の活性化関数をLiner(線形関数)にしたのと基本的には同じと理解。
        • 過去の隠れ層の情報をそのまま保持しておく回路を隠れ層に付け加えたもの。
      • これによって勾配消失は生じなくなるが、微分値が1で一定なので過去の隠れ層の重みが全て同じになってしまう。
    • 入力ゲート・出力ゲート
      • 例えば周期性のある時系列データなどはその周期Tに該当する周期だけ遡ったデータの重みが大きくなって活性化されるべきだが、過去の隠れ層の重みが全て同じになってしまうと逆周期のデータも同じ主みで活性してしまうので、重みが打ち消しあってしまう。(入力重み衝突)
        • その活性化したニューロンからの出力に関しても同じ。(出力重み衝突)
      • 過去の隠れ層の重みが同じになってしまう問題を解決するために、必要になったときだけ逆伝搬するような回路を設けたもの。
        • ゲートという名前だが、微分可能な活性化関数で定式化することで通常のニューラルネットと同様に逆伝搬できるようにした。
        • 要するに、入力・出力ゲートを開くべきかどうかの重みも学習によって決められるということ。
    • 忘却ゲート
      • CECで全ての過去の層を保持していても意味がないので、適切に過去のデータを忘れるようなゲートを追加したもの。
        • 入力・出力ゲートだけでも過去のデータの重みが小さくなることによって、影響は取り除けると思われるがそもそも考慮しなくて良いぐらいに重みが小さくなる過去の隠れ層に関しては忘れてしまった方が計算量も減るためと思われる。
          • CECのデータを忘却しないと、時系列データが長ければ長いほど過去データを積み重ねていくため、後半の学習にいくほどメモリも食うし、計算コストがかかるようになってしまうためと思われる。
    • 覗き穴結合
      • CECの状態に応じて、入力・出力ゲートおよび、忘却ゲートを活性化するかどうかを制御するためにCECとそれぞれのゲートをつなげた。
      • これによってCECの状態を反映させることができる。
        • 例えば、CECに時間T分のデータが溜まったら入出力ゲートが開くように重みが学習されるとか、時間T1分溜まったら忘却するとかと考えられる。
    • 長期時間依存性を学習できているかを評価するためのtoy problem → Adding Probrem
      • 入力x(t)に対してs(t) シグナル、m(t) マスクの二つが出力される。
        • s(t)は0〜1の一様乱数に従う値。
        • m(t)は0か1をとるが全区間でランダムで選ばれた2点のみが1でそれ以外は0を取る。
      • これをRNNで学習すると、誤差関数は全く収束しないが、LSTMだとあるタイミングで誤差関数が一気に収束する。
  • GRU(gated recurrent unit)
    • LSTMは推定パラメータが多いため計算に時間がかかる。パラメータを減らしてもLSTMと同等の性能を得ようとしたモデルがGRU。
      • 多分ポイントは、CECのように過去の隠れ層を保持しない点と思われる。
        • これによってパラメータを削減している。
      • リセットゲートによって、そのtにおいて時刻t-1のデータをどのくらい考慮するのかの重みが調整されるため、これがLSTMで言うところの忘却ゲートのようなものとなっていると思われる。リセットされるとそれまでの過去データからの重みは考慮されなくなる。
      • 更新ゲートで時刻t-1のデータをどのくらい考慮するかの重みづけがなされるので、これで更新されていることでそれまでの過去データの重みが積み重なって更新されていく。リセットゲートの重みが高くなるまでは過去の重みによる影響がリカレントに更新されていくと考えられる。

6章 RNNの応用

  • Bidirectional RNN (BiRNN)
    • 未来を未知として、過去のデータで学習して未来を予測するように過去の隠れそうだけを使うのが通常のRNN。
    • ただし、過去も未来も両方のデータがある場合に、その時の現在を予測するのに過去・未来両方の隠れそうが使われるのがBiRNN。
    • MNISTの画像を時系列データと見立てて、BiRNNに入れるとよく予測できている。(本来系列データではないので、アプローチの一つとしての参考。普通はCNNを使うのが一般的)
  • RNN Encoder-Decoder
    • Sin波などの時系列データはt+1の繰り返しでありM、厳密にはシーケンス(系列)ではない。
    • 文章など単語データの組み合わせで一連の意味をなすものがシーケンスであり、英語→仏語の翻訳などは入力も出力もシーケンスであるため、これらを扱うようなモデルがsequence-to-sequence modelとなる。
    • RNNを利用した sequence-to-sequence model が RNN Encoder-Decoder。
    • RNN Encoder-Decoder は エンコーダとデコーダという2つのRNNを組み合わせたモデル。エンコーダが入力を処理し、デコーダが出力を処理する。
    • エンコーダは出力がない普通のRNN。
      • 隠れ層には単純な活性化関数を使うのでも良いが、LSTMやGRUのような回路を含んだ関数であるのが一般的。
    • デコーダは自身の出力を次のステップの入力として受け取っている。
      • ここで出力の活性化関数は確率を出力するので、ソフトマックス関数となる。
    • 簡単なQ&A → 足し算をエンコーダ・デコーダで解く
      • 文字列を扱う時は全て数値化する必要がある。
        • one-hotエンコーディング(one hot化)によって、文字列を数値化(1-of-Kベクトル化)する。
        • パディング(空白文字も含めて)数値化する。
  • Attention
    • 単純なRNNエンコーダ・デコーダだと、エンコーダの最後の出力ベクトルがデコーダに入ることになる。
    • しかし本来は、エンコーダの中の最後の出力よりも重要な部分があるはずなので、その入力のどれに重み付けするか(時間の重み)を考慮できるようにした仕組みがAttention。Attentionは元々はRNNエンコーダ・デコーダの改良のために考えられたが、他にも応用されている。
    • ネットワークとしては、エンコーダ部分はそのままだが、デコーダ部分の各ステップでエンコーダの全ての入力を受け取るようになっている。
      • 各エンコーダの出力のどれに重み付けてデコーダが出力するかが調整されるため、入力の全シーケンスを考慮した重み付けが可能となる。
      • これら各エンコーダからデコーダの各ステップへ入力についての活性化関数はソフトマックス関数となる。
    • LSTMによるAttention
      • LSTMブロックに対する、前回からの入力h(t-1)とCECの前回値からの入力c(t-1)が正にRNNエンコーダ・デコーダにおけるデコーダへの入力と同じなので、これをt-1だけでなく、時間重みを考慮したものに変えれば、Attentionを導入することができる。
  • Memory Networks
    • LSTMやGRUの問題点として、セルの内部に時系列の情報を保持するため非常に長期の情報を学習するには時間がかかる点や1つのベクトルの中にその情報が集約されるため、情報が適切に記憶できないという問題があった。
    • この過去の時間情報を外部記憶に切り出して保存しようとしたものがMemory Network。Memory Networkにはフィードフォーワードの単純なニューラルネットワークを用いる。
    • Q&A問題への適用例から理解する。
      • 学習データはbAbiタスクデータ(Facebook AI Researchが公開しているQ&Aを中心としたテキスト形式のデータ)
        • 最初にストーリーが読み上げられて、それに対するQとAが掲載されている。
      • ストーリーをもとに外部記憶を構築して、質問文とその外部記憶を照らし合わせて出力を行うというモデルとする。
        • 入力用と出力用の二つの記憶を用意する。
      • Word Embeddingによる記憶。
        • 単純にone-hotエンコーディングされた単語ベクトルでは、それぞれの単語間に相関がないことになるが意味を考慮して各成分が0, 1以外の浮動小数点数を与えるようなベクトルにする。
        • word2vecはWord Embeddingを応用した、単語のベクトルか手法。
        • 最も単純なWord Embeddingはonhotエンコーディングされたベクトルに対する重み行列を掛け合わせることであるので、ニューラルネットワークの層で表現できる。このニューラルネットに学習させることで、どのように重み付けしてストーリーを記憶すれば良いかがわかる。