DeepLerningまとめ（後半）

# 再帰型ニューラルネットワーク（RNN)の概念
時系列データを扱えるニューラルネットワーク
時系列データとは、月ごとの売上、音声データなど

## RNNの構造と式
![20161006221744.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/08b1d7e2-0599-f48a-2c24-4b6a0076a65c.png)

RNNは通常のNNと同じように、入力層から中間層に掛けられる重み$W_{(in)}$、中間層から出力層にかけられる重み$W_{(out)}$に加えて、前の時系列から現在の時系列へかけられる重み$W$を使用する。

各出力値は以下のように算出する。

```math
中間層の総入力：u^{t}=w_{(in)}x^{t}+wz^{t-1}+b \\
中間層の出力 : z^t = f(u^t)\\
出力層の総入力 : v^t=W_{(out)}z^t+c \\
出力層の出力 : y^t=g(v^t) 
```

## BPTT(RNNの誤差逆伝搬法)
RNNの誤差逆伝搬法のパラメーターの更新式は以下のようになる。
前の時系列の勾配が伝搬していく形になっている

```math
\dfrac {\partial E}{\partial u^{t}}
=\dfrac {\partial E}{\partial v^{t}}\dfrac {\partial v^{t}}{\partial u^{t}}
=\dfrac {\partial E}{\partial v^{t}}\dfrac {\partial \left\{ W_{\left( out\right) } f\left( u^{t}\right) +c\right\} }{\partial u^{t}}
=f'\left( u^t\right) W^{T}_\left( out\right) \delta ^{out,t}
=\delta ^{t}\\

\delta ^{out,t}=g'\left( v^{t}\right) \left( y^{t}-t^{t}\right) \\

\delta ^{t-1}=\delta ^{t}\left\{ Wf'\left( u^{t-1}\right) \right\} \\

\delta ^{t-a-1}=\delta ^{t}\left\{ Wf'\left( u^{t-a-1}\right) \right\}

　\\
\\
W^{t+1}_{\left( in\right) }
=W^{t}_{\left( in\right) }-\varepsilon \dfrac{\partial E}{\partial W_{(in)} }
=W^{\left( t\right) }_{\left( in\right) }-\varepsilon{ \sum ^{\pi }_{a=0}\delta ^{t-a}\left[ x^{t-a}\right] ^{T}} \\

W^{t+1}_{\left( out\right) }
=W^{t}_{\left( out\right) }-\varepsilon \dfrac{\partial E}{\partial W_{(out)} }
=W^{\left( t\right) }_{\left( in\right) }-\varepsilon { \delta ^{out,t}\left[ z^{t}\right] ^{T}}
\\
W^{t+1}
=W^{t}-\varepsilon \dfrac {\partial E}{\partial W}
=W^{\left( t\right) }_{\left( in\right) }-\varepsilon { \sum ^{T_t }_{a=0}\delta ^{t-a}\left[ x^{t-a-1}\right] ^{T}} \\


b^{t+1}=b^{t}- \dfrac {\partial E}{\partial b}=b^{t}-\varepsilon \sum ^{T_t}_{a=0}\delta ^{t-a}　\\

c^{t+1}=c^{t}-\varepsilon \dfrac {\partial E}{\partial c}=c^{t}-\varepsilon \delta^{out,t} \\

ただし、　T_t:RNNの時系列の最大値 ,a: {0～(T_t - 1)}の任意の時系列
```

## RNNの課題
時系列の最大値$T_t$が大きいほど、時系列を経るごとの勾配が小さければ、勾配消失が起こる。
または、時系列を経るごとの勾配が大きければ、勾配爆発（発散）が起こる。
上記問題により、長い時系列の学習が困難になっている。

# LSTM（Long short-term memory)
RNNでは、長期の予測が長期であるほどに困難になるという問題があった。
しかし、LSTMは短期の記憶を長い期間で活用するという特徴により、その問題を解決する。

## CEC (Constant Error Carousel)
時系列ごとの勾配を１にする機構。長期であっても、勾配が１なので、消失や爆発といった問題が起こらない。

具体的には、以下のようになるよう調整する

```math
\delta ^{t-a-1}=\delta ^{t-a}\left\{ Wf'\left( u^{t-a-1}\right) \right\} =1
```

## 入力ゲート
従来のRNNで起こっていた入力の重み衝突問題を解決する。

### 入力の重み衝突
1. 入力値を活性化したい（次の入力へ伝えたい）場合、重みを大きくする方に学習する。
2. 入力値の中で不要な値を排除したい（次の入力へ伝えたくない）場合、重みが小さくする方に学習する。
従来のRNNの入力層⇒中間層では、1,2が繰り返されて、学習が遅くなる問題があった。

### 入力ゲートの効果
入力の重み衝突の問題を解決するために、追加の重みをもたせて、１つ前の時間のユニットの入力を受け取るか否かを判断させる入力ゲートを導入して解決。必要な誤差信号のみ伝達する。

## 出力ゲート
従来のRNNで起こっていた出力の重み衝突問題を解決する。

### 出力の重み衝突
入力の重み衝突と同じように、従来のRNNの中間層⇒出力層では、学習が遅くなる問題があった。

### 出力ゲート
入力ゲート同様、必要な誤差信号のみ伝達する仕組みを導入し出力の重み衝突問題を解決する。

## 忘却ゲート
過去の情報がいらなくなる時に、過去の情報を削除する機能を持つために忘却ゲートを使用する。

## のぞき穴結合（Peephole connection)
ゲートにより遮断された情報を再度活用するためにメモリセルから各ゲートへ情報を流し込むために使用する。

参考：
https://qiita.com/t_Signull/items/21b82be280b46f467d1b

# GRU (Gated Reccurent Unit)
LSTMよりゲートの数（重み）が少なく、LSTMより計算量が少なく学習可能。
ただし、LSTMと比べて、音声モデリングなどの限定的な用途でのみ同等またはそれ以上の性能を発揮する。
LSTMはGRUより厳密に強力なため、GRUで学習できることは全てLSTMで学習可能。

参考: https://ja.wikipedia.org/wiki/%E3%82%B2%E3%83%BC%E3%83%88%E4%BB%98%E3%81%8D%E5%9B%9E%E5%B8%B0%E5%9E%8B%E3%83%A6%E3%83%8B%E3%83%83%E3%83%88

# BRNN (Bidirectional Recurrent Neural Networks, 双方向RNN)
2つの正反対の方向の隠れ層を使用する。１方向は過去に向かって、もう一方は未来に向かって学習する。例えば、手書き文字の認識などに効果を発揮する。過去の手書き文字と未来の手書き文字の双方向から現在の文字を予想することができる。

参考：https://en.wikipedia.org/wiki/Bidirectional_recurrent_neural_networks


# Seq2Seq
EncoderRNNという入力部とDecoderRNNという出力部を持つRNN。
文章をトークン（単語などの単位）に区切って、EncoderRNNで最初のトークンから順に次のトークンへ時系列的に重みを伝搬させていく。
EncoderRNNの最後の重みの出力（final state)をDecoderRNNに学習結果として反映させる。同じく時系列ごとにDecoderRNNの前の時系列の出力（トークン単位）が、DecoderRNNの次の時系列の入力となって、次々とトークンを出力し、文章を完成させる。

## Seq2Seqの課題
一問一答しかできない。（文脈を学習することができない）

# HRED
Seq2SeqにContext RNNという層を導入し、１つ前までの文脈を反映できるようにしたもの。

## HREDの課題
会話の「流れ・展開」に多様性がなく一様になってしまう。
短く情報量に乏しい回答をしがち。

## VHRED
HREDのContext RNNにランダムなノイズを加えて、会話の流れを試行ごとに変える方法

## VAE(Variational Autoencoder)
AutoencoderはEncoder(入力のNN)で潜在変数z変換し、潜在変数zからDecoder(出力のNN）へ復元することで、入力と同じものを出力として得るニューラルネットワーク。
zの次元が入力より小さければ、圧縮（次元削減）となる。

この潜在変数zを確率分布と仮定したものが、VAEと呼ばれる。



参考：
https://qiita.com/kenmatsu4/items/b029d697e9995d93aa24


# Word2vec

OneHotベクトルで重み１行分を単語１つと対応させたニューラルネットワーク。
単語の長さ毎に重みがある。

# Attention Mechanism
Seq2Seqでは、長い文章への対応が難しい。固定次元の入力値を持つという課題があった
これを解決するために、入力と出力のどの単語が関連しているかを学ぶAttention Mechanismという仕組みを導入した。

参考：
https://qiita.com/halhorn/items/614f8fe1ec7663e04bea

# Tensorflowの実装演習

## 定数
単一の数値や行列などを定義できる。
```
tensorflow.constant()
```

## プレースホルダー
任意の変数の箱を保持できる。
```
tensorflow.placeholder(dtype, shape)
```

## 変数
定数と同様、単一の数値や行列を定義できる。

```
// 定義
tensorflow.Variable()

//　代入
tensorflow.assign()
```

## 線形回帰演習
ノイズを大きくするほど、重みやバイアスは実際の値と予測値の乖離が大きくなる。
重みやバイアスの値の変化は予測精度に影響しないとみられる。

ノイズ 0
実際の重み,バイアス：3.00, 2.00
予測の重み,バイアス：2.96, 2.01

![noise0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/5f5ee864-cfbb-e85a-783a-9e9f002f9697.png)


ノイズ 1
実際の重み,バイアス：3.00, 2.00
予測の重み,バイアス：2.85, 1.90
![noise1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/8079777b-a624-ce29-61a6-d963010db5ab.png)

ノイズ 3
実際の重み,バイアス：3.00, 2.00
予測の重み,バイアス：3.76, 1.79

![noise3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/02b00224-d0b9-f023-1fbf-79342e4e0d5d.png)


## 非線形回帰演習

・次の式をモデルとして回帰を行おう $y=30x^2+0.5x+0.2
実際のモデルと誤差が大きいことから、未学習であることが分かった。
![nonlinear1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/ab359964-16a9-e112-aeae-3337212d65d8.png)


⇒ 学習率が0.001と小さいので、0.1と大きくして再度学習させた

![nolinear2.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/a63faa35-7ffd-37f3-21c9-668fe945461a.png)


⇒ 実際の値とほぼ同じ曲線を得ることができた

## Mnist演習
![3layerMnist normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/36e4b18b-b091-49f1-e9e2-a0eb00de633e.png)


・隠れ層のサイズを変更してみよう
隠れ層を600,300⇒60,30に変更した。

![3layerMnist hiden60-30.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/68b2e307-e304-99c0-eff2-27bc9ca93d2f.png)


⇒　層を減らすと、学習率が下がった

・optimizerを変更しよう
Adam→GradientDescentOptimizerに変更

![3layerMnist gradientdecent.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/740ba7f8-275b-5674-c511-9a503729bb78.png)


⇒　optimizerでは、大きく精度が異なることがなかった。

## Keras演習

### 単純パーセプトロン
![Keras perceptron normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/f3c9cc7b-0ad3-77af-b039-4c88a688f85f.png)

・np.random.seed(0)をnp.random.seed(1)に変更
誤差が大きくなり、テストに1/4失敗
![perseptron seed1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/383eed63-4694-4057-c309-31244d59a650.png)

・エポック数を100に変更
１００世代でも、誤差の縮小が進んでいる
![perseptron epoch100.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/676780a6-f077-b93c-57c2-502d651f11bb.png)


・AND回路, XOR回路に変更
それぞれ、誤差が大きくなった。バイアスの影響か
OR < AND < XOR

AND
![perseptron and circit.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/e6da686c-fa1c-0b12-f050-ba83d521c30c.png)

XOR
![perseptron xor.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/2d0ffdb4-d19a-110c-cf1c-4742a4ca5ac0.png)



・OR回路にしてバッチサイズを10に変更
学習できていない

![perceptron or batch10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/3233d217-471e-27fb-c7ff-f4d5cf450874.png)


・エポック数を300に変更しよう
エポックに関係なくOR回路は学習できず

![perceptron epoch300.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/0934b3de-9dd8-dcf5-3567-60897d0dcf52.png)

## Irisデータの分類
![iris normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/5bf130f6-41ef-c24e-ce1d-198c96006e32.png)


・中間層の活性関数をsigmoidに変更しよう
勾配消失が起きて、学習が進まなくなった
![iris sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/f298a953-b7c6-85cd-6d3e-e95b37c2c88c.png)


・SGDをimportしoptimizerをSGD(lr=0.1)に変更しよう
学習の進みが早くなったが、正解率が安定していない

![iris sgd0.1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/b1367b1b-21ed-a968-8c13-d9e4f4bd94bc.png)

## Mnist
![mnist normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/b3bc0ede-bb3c-2f8d-cece-ae39a3500cbe.png)


・load_mnistのone_hot_labelをFalseに変更しよう (error)
![mnist onehot false.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/8f1ee246-d97b-9cdb-326f-00a84c2af206.png)


・誤差関数をsparse_categorical_crossentropyに変更しよう
ラベルが通常の状態で学習できた
![mnist sparce categorycal crossentropy.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/05ac665c-50dd-4b5a-ff60-cbdb47adef01.png)


・Adamの引数の値を変更しよう
LearningRate=0.1に大きくした。学習できなくなった

![mnist sdg param.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/7201aa44-4f44-581a-0a28-a93e979c8718.png)

## RNN
![rnn normal.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/d5306728-e286-71dd-ec0e-96bf58cc0d2d.png)


・RNNの出力ノード数を128に変更
表現力が高くなり、初期のepochから精度が高くなった
![rnn unit128.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/a53aa472-6826-72c7-b55b-5864f5e94f8b.png)


・RNNの出力活性化関数を sigmoid に変更
reluに比べ、精度が下がった

![rnn sigmoid.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/5e58085b-0f65-ed0a-4b01-075bd517b528.png)

・RNNの出力活性化関数を tanh に変更
２世代目から急激に精度が良くなった
![rnn tanh.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/fa4cbc26-67e2-efd5-155b-c486602f8258.png)


・最適化方法をadamに変更
早いepochから精度が上がる

![rnn adam.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/527161aa-e577-5746-3cea-2a2f5d33c138.png)


・RNNの入力 Dropout を0.5に設定
精度が出ない

![rnn dropout.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/b9594a2d-cc88-0811-d329-66b12d943fb7.png)


・RNNの再帰 Dropout を0.3に設定
学習は早くなったが、さらに精度が出なくなった
![rnn reccurent drop.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/904d10ac-15a3-0305-7d6e-ea753b9d2d2a.png)


・RNNのunrollをTrueに設定
実行速度が速くなった

![rnn unroll.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/408015/3f00e7c9-7d61-22b3-c858-cb4fc8b50aee.png)


# 強化学習

## 機械学習の分類
大別し、次の３つに分けられる。
・教師あり学習 : 正解ありのデータの「入力と出力の関係」を学習し、正解が未知の問題の正解を予測する
・教師なし学習 : 正解なしのデータの「データの構造」を学習し、クラスタリングや次元削減を行う
・強化学習 : 行動の結果、連続的に起こる事象から「報酬を最大化する行動」を学習し、未来の行動を決定する

→　強化学習は、テトリスなどのゲームや、株取引など未来の行動を選択するAIのために使用される

## 強化学習の３要素
状態：環境がどのようになっているかを表す。株取引では、現在の株価や株の保有数など。
行動：エージェントが環境に対してどのような行動を起こすかを表す。株取引では、株の売買、その数など。
報酬：ある状態においてエージェントが行動した時の結果を表す。株取引では、売買後の損益など。

## 代表的なアルゴリズム
Q学習では、現在の行動の価値を一つ先の行動の価値を用いて表現する。
アルゴリズムにより、以下のような特徴がある。

Q学習 : 次の行動の価値を現在の価値の最大値として、学習を進める方法
Sarsa : 実際に行動してみて、どうなったかを使って、学習を進める方法
モンテカルロ法 : 実際に報酬が得られてから(実際に良い結果を得られてから）、その値を使用して、学習を進める方法

## 探索と利用のトレードオフ
未知の行動（探索）と既知の良い報酬が得られる行動（利用）にはトレードオフの関係がある。
学習しながら行動を決定する場合、
未知の行動を選択すると、既知の行動より良い報酬が得られる可能性があるが、これまで学習した結果を活かせない。
既知の行動を選択すると、これまでの学習が活かせるが、新たな行動で学習することができない。

## 価値関数
強化学習の価値を決める関数は２種類存在する。

状態価値関数 : 状態sにいることの価値
（状態)行動価値関数 :状態sで行動aをとることの価値

## 方策関数
強化学習で次にどの行動をとるかを方策という。
次にとる行動の確率を表す関数を方策関数という。

## 方策勾配法
学習完了までの行動の価値を高めて、それ以外の行動の確率を下げるということを繰り返し学習する方法

方策の関数は次のように表される。

```math
\pi_{\theta}(a|s) = \frac{exp(Q(s,a)/Tx)}{\sum_{b \in A} exp(Q(s,b)/T)}
```

方策の更新式は次のようにあらわされる。

```math
\theta^{t+1}=\eta \nabla_{\theta}J(\theta)
```

方策の勾配は次のように表される。

```math
\nabla_{\theta}J(\theta)=E_{\pi_{\theta}}[\nabla_{\theta}log_{\pi_{\theta}}(a|s)Q^{\pi}(s,a)]
```


参考1 : https://qiita.com/tkmaroon/items/ee45c3a2913ffd152627
参考2 : https://qiita.com/triwave33/items/5e13e03d4d76b71bc802