ラビットチャレンジ 深層学習day3

##本記事について
ラビットチャレンジの深層学習day3のレポートです。
ラビットチャレンジはStudy-AI開講のE資格受験資格を得られる認定プログラムとなっています。

## 再帰型ニューラルネットワークについて
### 再帰型ニューラルネットワークの概念
#### RNN
- 概要
 - 時系列データに対応可能なニューラルネットワーク

- 時系列データとは
  - 時間的順序を追って一定間隔ごとに観察され、相互に統計的依存関係が認められるようなデータ系列のこと
  - 例）音声データ、テキストデータなど 

- 全体像

![IMG_3819.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/93ca686b-ae8f-d1e3-dd0d-71ee3bb361c3.png)

![IMG_3821.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/ec419ee7-70b4-01db-90f5-a7f4155c35df.png)

- 数式とコード
$$ u^t = W_{(in)}x^t + Wz^{(t-1)}x^t + b  $$
$$ z^t = f( W_{(in)}x^t + Wz^{(t-1)}x^t + b) $$
$$ v^t = W_{(out)}z^t + c $$
$$ y^t = g(W_{(out)}z^t + c) $$

```python
# 入力層から中間層
u[:,t+1] = np.dot(X, W_in) + np.dot(z[:,t].reshape(1, -1), W)
z[:,t+1] = functions.sigmoid(u[:,t+1])

# 中間層から出力層
np.dot(z[:,t+1].reshape(1, -1), W_out)
y[:,t] = functions.sigmoid(np.dot(z[:,t+1].reshape(1, -1), W_out))
```

- 確認テスト
  - RNNのネットワークには大きくわけて3つの重みがある。1つは入力から現在の中間層を定義する際にかけられる重み、1つは中間層から出力を定義する際にかけられる重みである。残り1つの重みについて説明せよ。

- 確認テスト解答
  - 前回の中間層から今回の中間層への重み

- 特徴
  - 時系列モデルを扱うには、初期の状態と過去の時間(t-1)の状態を保持し、そこから次の時間でのtを再帰的に求める再帰構造が必要になる

### Section1 実装演習
- プログラムの実装
  - 二進数の繰り上がりの計算を実装する
  - 付属のソースコード「3_1_simple_RNN.ipynb」を利用する

- 実装結果
  - 横軸が学習回数、縦軸が損失
  - 学習回数が6000回目くらいから誤差が減る
  - 最終的(10000回目)には損失は約0.00029となった

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/d7775f93-9e85-c210-e5ab-7e1ee996f50a.png)

#### BPTT
- 概要
  - RNNにおける誤差逆伝播法の一種

- 数式とコード
  - $\delta$ は$E$を$u$で微分した値を示す
  - このTは行列の転置ではなく「時間的にさかのぼって全部微分する」の意味
$$ \frac{\delta E}{\delta W_{(in)}} = \frac{\delta E}{\delta u^t}[\frac{\delta u^t}{\delta W_{(in)}}]^T = \delta ^T [x^t]^T $$
$$ \frac{\delta E}{\delta W_{(out)}} = \frac{\delta E}{\delta v^t}[\frac{\delta v^t}{\delta W_{(out)}}]^T = \delta ^{out,T} [z^t]^T $$
$$ \frac{\delta E}{\delta W} = \frac{\delta E}{\delta u^t}[\frac{\delta u^t}{\delta W}]^T = \delta ^T [x^{(t-1)}]^T $$
$$ \frac{\delta E}{\delta b} = \frac{\delta E}{\delta u^t} \frac{\delta u^t}{\delta b} = \delta ^t$$
$$ \frac{\delta E}{\delta c} = \frac{\delta E}{\delta v^t} \frac{\delta v^t}{\delta c} = \delta ^{out,t} $$

```python
# 上から3つの式のみ記載
np.dot(X.T, delta[:,t].reshape(1,-1))
np.dot(z[:,t+1].reshape(-1,1),delta_out[:,t].reshape(-1,1))
np.dot(z[:,t].reshape(-1,1), delta[:,t].reshape(1,-1))
```

- 確認テスト
  - 下図のy1をx・z0・z1・win・w・woutを用いて数式で表せ。ただしバイアスは任意の文字で定義せよ。また中間層の出力にシグモイド関数g(x)を作用させよ。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/6a4f2a70-5230-826f-8c9c-b8a260f75a88.png)

- 確認テスト解答

![IMG_3822.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/54c5caa5-d6f5-ee3b-2dfc-d19b9b1ee1f8.png)

### LSTM
- RNNの課題
  - 時系列を遡れば遡るほど勾配が消失していくため、長い時系列の学習が困難

- LSTMの特徴
  - 数学的な解決法とは異なり、構造自体を変えて勾配消失を防ぐのがLSTM 

- LSTMの全体図

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/12588ab6-ff7d-9ccc-58a8-544b43b3a10d.png)

#### CEC
- 概要
  - 過去のデータを保存するユニット
  - RNNでは記憶するユニットと学習するユニットが同じだったがLSTMでは分離している

- 数式
  - 勾配消失および勾配爆発が起こらないためには勾配が1になる必要があるため、数式は下記のようになる
  - この場合、時間をさかのぼっても勾配は変化しない
  - CECは勾配を1にするため考案された

$$ \delta ^{t-z-1} = \delta ^{t-z} (Wf^{'}(u^{t-z-1})) = 1 $$

- 課題
  - 入力データについて時間依存度に関係なく重みが一律であるため、学習ができない

#### 入力ゲートと出力ゲート
- 概要
  - 入力ゲート：CECに記憶させる内容を学習するゲート
  - 出力ゲート：CECのデータをどう使えばよく出力できるか学習するゲート

- 役割
  - 入力・出力ゲートを追加することで、それぞれのゲートへの入力値の重みを、重み行列W,Uで可変可能とする
  - CECの課題である「記憶しかできないこと」を解決


#### 忘却ゲート
- LSTMの現状
  - CECは、過去の情報が全て保管されている

- 課題
  - 過去の情報が要らなくなった場合、削除することはできず保管され続ける

- 解決策
  - 過去の情報が要らなくなった場合、そのタイミングで情報を忘却する機能が必要
  - 忘却ゲートがその役割を担う

- 確認テスト
  - 以下の文章をLSTMに入力し空欄に当てはまる単語を予測したいとする。文中の「とても」という言葉は空欄の予測においてなくなっても影響を及ぼさないと考えられる。このような場合、どのゲートが作用すると考えられるか。
  - 「映画おもしろかったね。ところで、とてもお腹が空いたから何か____。」

- 確認テスト解答
  - 必要ない情報であるため、忘却ゲート

#### 覗き穴結合
- 課題
  - CECの保存されている過去の情報を任意のタイミングで他のノードに伝播させたり、あるいは任意のタイミングで忘却させたい
  - しかしCEC自身の値は、ゲート制御に影響を与えていない
  - 覗き穴結合で解決

- 概要
  - CEC自身の値に重み行列を介して伝播可能にした構造

#### 実装演習
- GRUの章で行う

### GRU
- LSTMの課題
  - パラメータ数が多く計算負荷が高くなる
  - GRUで解決

- GRUの特徴
  - LSTMのパラメータを大幅に削減しながら精度は同等になるような構造を取る

- 構造
  - 基本構造はLSTMと同じだが、CEC、入力ゲート、出力ゲート、忘却ゲートがなくなった
  - 新たにリセットゲートと更新ゲートが追加された

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/2287b99d-27f3-bc74-d932-946143847ca6.png)

- 確認テスト
  1. LSTMとCECが抱える課題について、それぞれ簡潔に述べよ。
  2. LSTMとGRUの違いを簡潔に述べよ。

- 確認テスト解答
  1. LSTMはパラメータが多く計算量が膨大、CECは記憶することしかできず学習能力がないという課題がある
  2. LSTMはCEC、入力ゲート、出力ゲート、忘却ゲートを持つがGRUはリセットゲートと更新ゲートを持つ。またLSTMはパラメータが多いがGRUはパラメータが少ない。

#### 実装演習
- 自然言語処理で何かの単語が来た際に次に来る単語を予測する
  - 今回予測するのは"some of them looks like"の次に来る単語
  - 付属のソースコード「predict_word.ipynb」を利用する

- 実装結果
  - 様々な単語の確率が学習されていることがわかる
  - 結果的に最も可能性が高かったのは"some of them looks like et"

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/b38eb498-9cd7-eddc-d8c3-8212659a4180.png)

### 双方向RNN
- 概要
  - 過去の情報だけでなく未来の情報を加味することで、精度を向上させるためのモデル
  - 例) 文章の推敲、機械翻訳等
 
#### 実装演習
- 講義内になかったため割愛

## RNNでの自然言語処理
### Seq2Seq
- 全体図
  - データから文脈を保存するエンコーダと文脈からデータを出力するデコーダからなる

![IMG_3824.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/e13b935a-b877-97e6-7379-4c2b4363951b.png)

- 概要
  - Encoder-Decoderモデルの一種
  - 機械対話や、機械翻訳などに使用されている

#### Encoder RNN
- 概要
  - ユーザーがインプットしたテキストデータを単語等のトークンに区切って渡す構造

- 処理詳細
  - Taking 
     - 文章を単語等のトークン毎に分割し、トークンごとのIDに分割
     - one-hotベクトルにする
  - Embedding 
     - IDから、そのトークンを表す分散表現ベクトルに変換
     - 似た単語の意味のembeddingベクトルが似たような値になるよう設定
  - Encoder RNN
      - ベクトルを順番にRNNに入力

- 処理手順
  1. vec1をRNNに入力し、hidden stateを出力する。このhidden stateと次の入力vec2をまたRNNに入力し、hidden stateを出力という流れを繰り返す。
  1. 最後のvecを入れたときのhidden stateをfinal stateとして保存する。このfinal stateはthought vectorと呼ばれ、入力した文の意味を表すベクトルとなる。

#### Decoder RNN
- 概要
  - システムがアウトプットデータを単語等のトークンごとに生成する構造

- 処理手順
  1.  Encoder RNN のfinal state (thought vector) から、各token の生成確率を出力していく。final state をDecoder RNN のinitial state として設定し、Embedding を入力する。
  1. Sampling:生成確率に基づいてtokenをランダムに選ぶ。
  1. Embedding:2で選ばれたtoken をEmbeddingしてDecoder RNN への次の入力とする。
  1. Detokenize:1~3を繰り返し、2で得られたtokenを文字列に直す。

- 確認テスト
  - 下記の選択肢から、seq2seqについて説明しているものを選べ。
  - （1）時刻に関して順方向と逆方向のRNNを構成し、それら2つの中間層表現を特徴量として利用するものである。
  - （2）RNNを用いたEncoder-Decoderモデルの一種であり、機械翻訳などのモデルに使われる。
  - （3）構文木などの木構造に対して、隣接単語から表現ベクトル（フレーズ）を作るという演算を再帰的に行い（重みは共通）、文全体の表現ベクトルを得るニューラルネットワークである。
  - （4）RNNの一種であり、単純なRNNにおいて問題となる勾配消失問題をCECとゲートの概念を導入することで解決したものである。

- 確認テスト解答
  - (2) seq2seqはRNNを用いたEncoder-Decoderモデルの一種である

#### HRED
- seq2seqの課題
  - 一問一答しかできないため、問に対して文脈も何もなくただ応答が行われ続ける
  - HREDで解決

- HREDの特徴
  - 過去n-1 個の発話から次の発話を生成する
  - Seq2seqでは会話の文脈無視で応答がなされたが、HREDでは前の単語の流れに即して応答されるため、より人間らしい文章が生成できる
  - 例）
     - システム:インコかわいいよね。
     - ユーザー:うん
     - システム:インコかわいいのわかる。

- 構造
  - HRED = Seq2Seq+ Context RNN
  - Context RNN
     - Encoderのまとめた各文章の系列をまとめて、これまでの会話コンテキスト全体を表すベクトルに変換する構造
     - 過去の発話の履歴を加味した返答をできる

#### VHRED
- HREDの課題
  - HRED は確率的な多様性が字面にしかなく、会話の「流れ」のような多様性が無い
  - 同じコンテキスト（発話リスト）を与えられても、答えの内容が毎回会話の流れとしては同じものしか出せない。
  - 短く情報量に乏しい答えをしがちである。
  - 短いよくある答えを学ぶ傾向がある
     - 例)「うん」「そうだね」「・・・」など

- VHREDの特徴
  - HREDに、VAEの潜在変数の概念を追加したもの
  - HREDの課題を、VAEの潜在変数の概念を追加することで解決した構造

#### VAE
##### オートエンコーダ
- 概要
  - 教師なし学習の一つ
  - 学習時の入力データは訓練データのみで教師データは利用しない

- 構造
  - 入力データから潜在変数zに変換するニューラルネットワークをEncoderと呼ぶ
  - 潜在変数zをインプットとして元画像を復元するニューラルネットワークをDecoderと呼ぶ

![IMG_3825.PNG](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2235425/434b80bb-b523-1d0b-312f-d2f13d3993ef.png)

##### VAE
- オートエンコーダの課題
  - 通常のオートエンコーダーの場合、何かしら潜在変数zにデータを押し込めているものの、その構造がどのような状態かわからない
  - VAEはこの潜在変数zに確率分布z-N(0,1)を仮定した
  - 似ている画像を近いものとして認識できる

- 確認テスト
  - VAEに関する下記の説明文中の空欄に当てはまる言葉を答えよ。自己符号化器の潜在変数に____を導入したもの。

- 確認テスト解答
  - 確率分布

#### 実装演習
- 講義内になかったため割愛

### Word2vec
- RNNの課題
  - 単語のような可変長の文字列をニューラルネットワークに与えることができず、固定長形式で単語を表す必要があった
  - Word2vecで解決

- Word2vecの概要
  - 単語をベクトルとして表現する手法 

- 手順
  1. 学習データから辞書を作成  
 例) "I want to eat apples. I like apples."の場合{apples, eat, I, like, to, want}
  2. 辞書の単語数分のone-hotベクトルを作成
  3. 変換表を作成し辞書の数×単語ベクトルの次元数の重み行列とする

### Attention Mechanism
- seq2seqの課題
  - 長い文章への対応が難しい
  - seq2seq では2単語でも100単語でも、同じ固定次元ベクトルの中に入力しなければならない
  - Attention Mechanismで解決

- 概要
  - 「入力と出力のどの単語が関連しているのか」の関連度を学習する仕組み

- 確認テスト
  - RNNとword2vec、seq2seqとAttentionの違いを簡潔に述べよ

- 確認テスト解答
  - RNN：時系列データを処理するのに適したネットワーク
  - word2vec：単語の分散表現ベクトルを得る手法
  - seq2seq：一つの時系列データから別の時系列データを得るネットワーク
  - Attention：時系列データの中身に対して関連性(重み)を付ける手法