<科目> 深層学習 Day4 強化学習・Tensor Flow


*****
#<科目> 深層学習　


目次
[深層学習: Day1 NN ]
(https://qiita.com/matsukura04583/items/6317c57bc21de646da8e)
[深層学習: Day2 CNN ]
(https://qiita.com/matsukura04583/items/29f0dcc3ddeca4bf69a2)
[深層学習: Day3 RNN]
(https://qiita.com/matsukura04583/items/9b77a238da4441e0f973)
[深層学習: Day4 強化学習・Tensor Flow]
(https://qiita.com/matsukura04583/items/50806b750c8d77f2305d)


##深層学習: Day4 強化学習・Tensor Flow (講義の要約)
+ Tensor FlowはGoogleが提供。レイブラリとしての利用では最も多い。そのため講義ではTensor Flow中心にで学んでゆく。

### Section1) TensorFlowの実装演習

####線形回帰(DN65)
+ データ個数　300個<br>
d＝３x＋２（ノイズ0.3）
+ 誤差関数 平均2乗誤差
+ Optimizer 勾配降下法
+ 学習率0.1

[try]

noiseの値を変更しよう
dの数値を変更しよう

<img width="823" alt="スクリーンショット 2020-01-04 12.11.10.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/8cc4eb36-1c3e-0aec-4d84-ab2c66f1abf0.png">


$\Rightarrow$【考察】

+ Tensor Flowはセッションを明示的に実施しないと動かない。
+ [(参考)TensorFlowで-１でreshapeがどのように変形するのか調べた件ー『-1は「他の要素から計算して適切な数字にする」の意味になります』](https://teratail.com/questions/104809)
+ (参考:調べた事)Optimizerについて<br>
  TensorFlowでは現在，次のものがサポートされている。

|Optimizer name|Description|
|:--|:--|
|GradientDescentOptimizer|勾配降下法によるオプティマイザー|
|AdagradOptimizer|AdaGrad法によるオプティマイザー|
|MomentumOptimizer|モメンタム法によるオプティマイザー|
|AdamOptimize|Adam法|
|FtrlOptimizer|Follow the Regularized Leader アルゴリズム(これは習ってないですね)|
|RMSPropOptimizer|学習率の調整を自動化したアルゴリズム|
[(参考)tensorflowのOptimizer](http://www.tensorflow.org/api_docs/python/train.html#optimizers)

####非線形回帰(DN66)

+ データ個数　100個<br>
$d = - 0.4 x^3 + 1.6x^2 - 2.8x + 1$（ノイズ0.05）<br>
この時、W（重み）は、-0.4,1,6,-2,8,1（xの０乗）の４つでb(バイアス)は使っていないことに注意。
+ 誤差関数 平均2乗誤差
+ Optimizer 勾配降下法
+ 学習率0.01
+ <br>

[try]
noiseの値を変更しよう
dの数値を変更しよう

<img width="887" alt="スクリーンショット 2020-01-04 12.43.50.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/bd1e8325-d050-2afa-0664-9b6302fe39e8.png">

+ W = tf.Variable(tf.random_normal([4, 1], stddev=0.01))
  stddev=0.01は、標準偏差0.01のランダムな初期値として、tf.random_normalで定義。

####演習問題(DN67)

[try]
+ 次の式をモデルとして回帰を行おう<br>
  $d = 30x^2 +0.5x + 0.2$（ノイズ0.05）
+ 誤差が収束するようiters_numやlearning_rateを調整しよう

<img width="924" alt="スクリーンショット 2020-01-04 14.36.20.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/8295aba0-dfc2-1a30-4fb1-53bc94d8a09e.png">
$\Rightarrow$【考察】
iters_num(イテレーションナンバー：反復学習回数)を調整するよりも、learning_rate(学習率)を調整した方が効果が高いという結果になった。
【変更ソース】

```python:python
import numpy as np
import tensorflow as tf
import matplotlib.pyplot as plt

# イテレーションの変更はこちらで行う
iters_num = 10000
plot_interval = 100

# データを生成
n=100
#random.rand(): 0.0以上、1.0未満で乱数生成
x = np.random.rand(n).astype(np.float32) * 4 - 2
d =  30 * x ** 2 +0.5 * x + 0.2

#  ノイズを加える
noise = 0.05
d = d + noise * np.random.randn(n) 

# モデル
# bを使っていないことに注意.
# 追加　Wの数が４から３になっているので変更
#xt = tf.placeholder(tf.float32, [None, 4])
xt = tf.placeholder(tf.float32, [None, 3])
dt = tf.placeholder(tf.float32, [None, 1])
# 追加　Wの数が４から３になっているので変更
#W = tf.Variable(tf.random_normal([4, 1], stddev=0.01))
W = tf.Variable(tf.random_normal([3, 1], stddev=0.01))
y = tf.matmul(xt,W)

# 誤差関数 平均２乗誤差
loss = tf.reduce_mean(tf.square(y - dt))
# 学習率の変更はこちらで行う
optimizer = tf.train.AdamOptimizer(0.001)
train = optimizer.minimize(loss)

# 初期化
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

# 作成したデータをトレーニングデータとして準備
d_train = d.reshape(-1,1)
#x_train = np.zeros([n, 4])
x_train = np.zeros([n, 3])
for i in range(n):
# 追加　Wの数が４から３になっているので変更
#    for j in range(4):
    for j in range(3):
        x_train[i, j] = x[i]**j

#  トレーニング
for i in range(iters_num):
    if (i+1) % plot_interval == 0:
        loss_val = sess.run(loss, feed_dict={xt:x_train, dt:d_train}) 
        W_val = sess.run(W)
        print('Generation: ' + str(i+1) + '. 誤差 = ' + str(loss_val))
    sess.run(train, feed_dict={xt:x_train,dt:d_train})

print(W_val[::-1])
    
# 予測関数
def predict(x):
    result = 0.
# 追加　Wの数が４から３になっているので変更
#   for i in range(0,4):
    for i in range(0,3):
        result += W_val[i,0] * x ** i
    return result

fig = plt.figure()
subplot = fig.add_subplot(1,1,1)
plt.scatter(x ,d)
linex = np.linspace(-2,2,100)
liney = predict(linex)
subplot.plot(linex,liney)
plt.show()
```

####MNIST1(DN68)
+ MNISTとは、手書き文字のデータセットで、28✖️28✖️白黒もの１1チャンネルの画像が入っている。
+ 0から9のどの数字かを予測するようなものになっている。

##### 分類3層 (mnist)(DN69)
[try]
隠れ層のサイズを変更してみよう
optimizerを変更しよう
$\Rightarrow$【考察】
<img width="942" alt="スクリーンショット 2020-01-04 19.33.05.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/4f3f0d29-656e-e1a9-08df-a5c4c8716eca.png">
隠れ層のサイズを半分にしたところ正答率が大幅に下がった。一方、optimizerをAdamからMomentumに変更したところ正答率は90から94パーセントまで上がった。他にも実施したが、RMSPropが96パーセントと最も良かった。
隠れ層のサイズを倍にもしてみたが、正答率の向上は１パーセント程度だったことから、隠れ層のサイズが十分深かったら、その後はoptimizerで調整する事が望ましいと感じた。

##### 分類CNN (mnist)(DN70)
conv - relu - pool - conv - relu - pool - 
affin - relu - dropout - affin - softmax
[try]

ドロップアウト率を0に変更しよう
$\Rightarrow$【考察】
(変更前)dropout_rate = 0.5
<img width="416" alt="スクリーンショット 2020-01-04 19.54.24.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/63d99456-c96d-991d-7b64-89b5483d3a9c.png">

(変更後)dropout_rate = 0
<img width="401" alt="スクリーンショット 2020-01-04 20.02.13.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/baec0cf7-7087-a997-99b4-0bafac4777a8.png">
もっと下がるかと思ったが、あまり変わらなかった。

### 例題解説
<img width="830" alt="スクリーンショット 2020-01-04 20.37.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/2fda9071-e3ef-c935-a8a8-a0999cf97982.png">

$\Rightarrow$【考察】
回答は（a）
１.googlenetはInceptionモジュールの積み重ねで構成されたネットワークである。
2.Inceptinモジュール
　上記表で示しているように小さいネットワークを一つのモジュールに定義する。よって（D）は正解です。
　Inceptinモジュールは通常は、フィルターサイズを定義してあげてConvolutionで行う部分を複数のフィルターサイズを使う事でConvolutionで行う特徴となっている。
１×１の畳み込みによって次元削減を行うCは正解になります。複数の畳み込みによってパラメーター数を減らしながら表現力を改善してゆくBも正解。


回答は（a）が誤り
まずlossについては、途中のネットワークから分岐させた部分でクラス分類を行っている事がこのlossの特徴になります。

あとの例題解説は省略。

【DN73】例題解説中の確認テスト
VGG・GoogleNet・ResNetの特徴をそれぞれ簡潔に述べよ。

VGGについては、最も古く2014年のモデルになります。特徴としては、Convolution,Convolution,max_poolというような単純なネットワークの積み重ねでシンプルなものとなっている。一方他の二つと比べパラメーター数が多いのが特徴。
GoogleNetはinceptionモジュールを使っているのがと特徴。１✖️１サイズを使った次元削減や様々なフィルターサイズを使うことによるスパースなものというのが特徴的になっている。
ResNetについては＜スキップコネクションアイデンティティモジュールを使うことによって残渣接続を行い、それによって深い学習が行えるという事が特徴になっている。

#####Keras2 (DN69)
######単純パーセプトロン
OR回路
[try]
np.random.seed(0)をnp.random.seed(1)に変更
エポック数を100に変更
AND回路, XOR回路に変更
OR回路にしてバッチサイズを10に変更
エポック数を300に変更しよう
⇒ 【考察】
(変更前)np.random.seed(0)
<img width="573" alt="スクリーンショット 2020-01-04 22.40.41.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/c5506b3f-6e84-01e2-709c-b0b3168c65ab.png">
(変更後)np.random.seed(1)に変更
<img width="573" alt="スクリーンショット 2020-01-04 22.49.46.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/056a8430-f5fe-d738-9919-c9d24abb1a13.png">
(変更後)エポック30回→100回に変更
<img width="574" alt="スクリーンショット 2020-01-04 22.58.35.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/cc4c070a-48d9-c34c-9649-23b38eebdab7.png">
(変更後)AND回路に変更
 OR, ANDは線形分離可能だが, XORは線形分離不可能なので学習できない
(変更後)OR回路にしてバッチサイズを10に変更
<img width="571" alt="スクリーンショット 2020-01-04 23.22.23.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/ef372b4a-8392-7450-cc84-117e812b594f.png">
(変更後)エポック数を300に変更しよう
<img width="566" alt="スクリーンショット 2020-01-04 23.24.53.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/c3546081-ca86-26d1-fee5-0f2c269d2e67.png">

######分類 (iris)
[try]

+ 中間層の活性関数をsigmoidに変更しよう
+ SGDをimportしoptimizerをSGD(lr=0.1)に変更しよう

(変更前・ReLU)
<img width="1043" alt="スクリーンショット 2020-01-04 23.38.52.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/7c767b32-935c-0bc7-45f0-adcfdef6bf67.png">
(活性化関数をSygmoidに変更)
<img width="1055" alt="スクリーンショット 2020-01-05 0.40.44.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/a27aba1b-daa1-7aee-b53f-4fea39aecbb5.png">
やはりグラフからはReRUの方が精度が良いと言える。
（最適化をoptimizer=SGD(lr=0.1)に変更）
<img width="1047" alt="スクリーンショット 2020-01-05 0.53.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/8c1694f5-8ed4-f521-c213-ff056a840ece.png">

optimizer=SGD(lr=0.1)にして、時折１.０が出るように精度が上がってきた部分もあるが、ばらつきも多くなったように見受けられる。

######分類 (mnist)
[try]

+ load_mnistのone_hot_labelをFalseに変更しよう (error)
+ 誤差関数をsparse_categorical_crossentropyに変更しよう
+ Adamの引数の値を変更しよう

（変更前）
<img width="1069" alt="スクリーンショット 2020-01-05 1.17.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/4d3ee4c9-6deb-90e6-6461-2526b8abc345.png">
（変更後）one_hot_labelをFalseに変更
<img width="1087" alt="スクリーンショット 2020-01-05 4.51.25.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/9a7811b4-5d8a-e298-ae79-de0465e3ff5a.png">

（変更後）誤差関数をsparse_categorical_crossentropy変更
　　　　　且つone_hot_labelをFalseに変更
<img width="419" alt="スクリーンショット 2020-01-05 5.04.45.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/c15d13df-01a0-ef4a-58e7-28b1f7a20622.png">

categorical_crossentropy→ one_hot_label をTrue
sparse_categorical_crossentropy→ one_hot_label をFales
にしなければならない。しない場合エラーとなる。

（変更後）Adamのlr引数の値を変更しよう（学習率0.01 -> 0.1）
<img width="409" alt="スクリーンショット 2020-01-05 5.10.06.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/52b363fb-6bf2-c837-4b74-3f2d1b2e77b0.png">

######RNN 
(二進数足算の予測)
[Keras RNNのドキュメント] (https://keras.io/ja/layers/recurrent/#simplernn)

+ RNNの出力ノード数を128に変更
+ RNNの出力活性化関数を sigmoid に変更
+ RNNの出力活性化関数を tanh に変更
+ 最適化方法をadamに変更
+ RNNの入力 Dropout を0.5に設定
+ RNNの再帰 Dropout を0.3に設定
+ RNNのunrollをTrueに設定

[try]
(変更前)
<img width="803" alt="スクリーンショット 2020-01-07 15.54.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/ed58b712-a4f2-850f-7361-fa74bb23ecec.png">
(変更後)出力ノード数を128に変更
SimpleRNN のunits=16 $\Rightarrow$ units=128に変更。
<img width="798" alt="スクリーンショット 2020-01-07 16.07.28.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/b007d065-2abc-1da2-2a14-917a0bd1b066.png">
EPOCH1の段階からAcc0.9299まで上がっている。
(変更後)出力活性化関数を ReLU$\Rightarrow$ sigmoid に変更
<img width="759" alt="スクリーンショット 2020-01-07 16.21.14.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/3593be60-54b3-703d-cd74-11d21cc19e72.png">
SygmoidはLeRUほどAccが上がらない結果になりました。
(変更後)出力活性化関数を tanh に変更
<img width="789" alt="スクリーンショット 2020-01-07 16.33.54.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/d8d896ee-6acd-3e10-637d-cdc0ecebd075.png">
Accが100%まであがるのにEpoch3までかかっている。

(変更後)最適化方法をadamに変更
ソース変更

```python:pyton
#model.compile(loss='mean_squared_error', optimizer=SGD(lr=0.1), metrics=['accuracy'])
model.compile(loss='mse', optimizer='adam', metrics=['accuracy'])

```
<img width="810" alt="スクリーンショット 2020-01-07 17.09.49.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/dd1374b5-2dab-43bb-a9e7-7faa73266c0f.png">
Accがほぼ良い結果である。

(変更後)入力 Dropout を0.5に設定
<img width="773" alt="スクリーンショット 2020-01-07 16.41.19.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/bd27f11b-71f6-139f-c899-cb704d6ab05a.png">
Accが思うほど上がらない結果。

(変更後)再帰 Dropout を0.3に設定
<img width="762" alt="スクリーンショット 2020-01-07 16.53.33.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/a9bb9754-0eff-6667-724f-2bb36715aaf3.png">
こちらもAcc98%どまりとなっている。

(変更後)unrollをTrueに設定
<img width="783" alt="スクリーンショット 2020-01-07 17.15.36.png" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/3ec4e0d7-c8fb-3a67-e8be-064a40dc23c1.png">
こちらも良い結果である。


### Section2) 強化学習
####2-1強化学習とは
　長期的に報酬を最大化できるように環境のなかで行動を選択できるエージェントを作ることを目標とする機械学習の一分野
$\Rightarrow$行動の結果として与えられる利益(報酬)をもとに、行動を決定する原理を改善していく仕組みです。

【D81】強化学習1　確認テスト
強化学習に応用できそうな事例を考え、環境エージェント・行動・報酬を具大的に挙げよ。

⇒【考察】
株の投資のロボット
　　環境⇒株式市場
　　エージェント⇒投資家
　　行動　⇒儲かりそうな株を選んで投資する投資する
　　報酬　⇒　株式に売買による利益・損失

####2-2強化学習の応用例
マーケティングの場合
環境        :会社の販売促進部
エージェント:プロフィールと購入履歴に基づいて、キャンペーンメールを
             送る顧客を決めるソフトウェアである。
行動        :顧客ごとに送信、非送信のふたつの行動を選ぶことになる。
報酬        :キャンペーンのコストという負の報酬とキャンペーンで生み
             出されると推測される売上という正の報酬を受ける

####2-3探索と利用のトレードオフ
環境について事前に完璧な知識があれば、最適な行動を予測し決定することは可能。<br>
⇒どのような顧客にキャンペーンメールを送信すると、どのような行動を行うのかが既知である状況。<br>
⇒強化学習の場合、上記仮定は成り立たないとする。不完全な知識を元に行動しながら、データを収集。最適な行動を見つけていく。

過去のデータで、ベストとされる行動のみを常に取り続ければ他にもっとベストな行動を見つけることはできない。
⇒探索が足りない状態
(上と下はトレードオフの関係性)
未知の行動のみを常に取り続ければ、過去の経験が活かせない。利用が足りない状態トレードオフの関係性
⇒未知の高度のみを



####2-4強化学習のイメージ
![Day4.jpg](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/357717/20fa7fa9-cf5c-3078-c1bb-d14aa9b74b2f.jpeg)

####2-5強化学習の差分
強化学習と通常の教師あり、教師なし学習との違い

結論:目標が違う

+ 教師なし、あり学習では、データに含まれるパターンを見つけ出すおよびそのデータから予測することが目標
+ 強化学習では、優れた方策を見つけることが目標

強化学習の歴史
強化学習について
・冬の時代があったが、計算速度の進展により大規模な状態をもつ場合の、強化学習を可能としつつある。
・関数近似法と、Q学習を組み合わせる手法の登場

Q学習
・行動価値関数を、行動する毎に更新することにより学習を進める方法
関数近似法
・価値関数や方策関数を関数近似する手法のこと



####2-6行動価値関数
行動価値関数とは

+ 価値を表す関数としては、状態価値関数と行動価値関数の2種類がある
+ ある状態の価値に注目する場合は、状態価値関数状態と価値を組み合わせた価値に注目する場合は、行動価値関数



####2-7方策関数
方策関数とは方策ベースの強化学習手法において、ある状態でどのような行動を採るのかの確率を与える関数のことです。

####2-8方策勾配法
方策反復法
方策をモデル化して最適化する手法
⇒方策勾配法

```math
\theta^{(t+1)}=\theta^{(t)}\epsilon\nabla j(\theta)
```
ｊとは⇒方策の良さ・・・定義しなければならない

定義方法
・平均報酬
・割引報酬和
上記の定義に対応して、行動価値関数:Q(s,a)の定義を行い。
方策勾配定理が成り立つ。

```math
\nabla _{\theta} j(\theta)=E_{\pi_\theta} [\nabla_{\theta} log\pi_\theta(a|s)Q^\pi(s,a))]
```