【ラビットチャレンジ】 stage4 - 深層学習後編 (day4)

#ラビットチャレンジ

ラビットチャレンジはE資格の受験に必要な協会認定講座のプログラムです。
ラビットチャレンジでは認定プログラムを修了してE資格の受験資格を習得するために、指定のレポートとテストで合格点を取得しなければなりません。

https://ai999.careers/rabbit/

今回はStage4深層学習後編(day4)についてまとめます。

- [ ] Stage1 応用数学
- [ ] Stage2 機械学習
- [ ] stage3 深層学習前編(day1, day2)
- [x] stage4 深層学習後編(day3, day4)

---

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

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/b23dac02-a2bf-bf69-6532-6dd8ae09e452.png)


環境について事前に完璧な知識があれば、最適な行動を予測し決定することは可能。
強化学習の場合は不完全な知識を元に行動しながらデータを収集し最適な行動を見つけていく。
また、過去のデータでベストとされる行動のみをとり続けると他にもっとベストな行動を見つけることができない。
このよう場合に未知の行動のみをとり続ければ、過去の経験が生かせない。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/d388da03-4c31-6645-da8f-1b5eb74a054b.png)


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

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

###Ｑ学習
・行動価値関数を、行動するごとに更新することにより学習を進める

###関数近似法
・価値関数や、方策関数を関数近似する方法。

###価値関数
・価値を表す関数で以下の2種類がある。
　- 状態価値関数：ある状態の価値に注目する
　- 行動価値関数：状態と価値を組み合わせた価値に注目する ⇒ 状態価値関数は状態のみを見る

###方策関数
・ある状態でどのような行動を採るのかの確率を与える関数

```math
\pi (s)=a
```

・$\pi (s, a)$ VやQ基にどういう行動をとるか ※その瞬間の行動
・$V^{\pi}(s)$ 状態関数
・$Q^{\pi}(s, a)$ 状態や行動関数

###方策勾配法

```math
\theta^{(t+1)}=\theta^t+\epsilon\nabla J(\theta)
```

・$\epsilon$：学習率
・$\theta$：重み
・$t$：時刻
・$J$：方策の良さで定義しなければならない

###方策勾配定理

```math
\nabla_{\theta} J(\theta) = \mathbb{E}_{\pi_{\theta}}[(\nabla_{\theta}log{\pi}_{\theta}(a|s)Q^{\pi}(s, a))]
```

・$s$：状態
・$a$：行動
・$Q$：Q値
・$\theta$：重み

#Section2 Alpha Go
AlpahGoは強化学習で作られた囲碁プログラムである。

###AlphaGo
AlphaGoの学習は次の手順で行われる
1. 教師あり学習によるRollOutPolicyとPolicyNetの学習
2. 強化学習によるPolicyNetの学習
3. 強化学習によるValueNetの学習

※RollOutPolicy：線形の方策関数
※PolicyNet：方策関数
※ValueNet：価値関数

PolicyNetの教師あり学習
KGS Go Server (ネット囲碁対局サイト)の棋譜データから3,000万局面分の教師を用意し、教師と同じ着手を予測できるよう学習を行った。
具体的には、教師が着手した手を1として残りを0とした19x19次元の配列を教師とし、それを分類問題として学習。

PolicyNetの強化学習
現状のPolicyNetとPolicyPoolからランダムに選択されたランダムに選択されたPolicyNetと対局シミュレーションを行い、その結果を用いて方策勾配法で学習を行った。
PolicyPoolとは、PolicyNetの強化学習の過程を500イテレーションごとに記録し保存しておいたものである。
ランダムにPolicyNetを選択することで、対局に幅を持たせて過学習を防ごうというのが主である。
この学習をmini batch size 128で1万回行った。

ValueNetの学習
PolicyNetを使用して対局シュミレーションを行い、その結果の勝敗を教師として学習した。
教師データの手順は、
1. SLPolicyNet(教師あり学習で学習した作成したPolicyNet)でN手まで打つ。
2. N+1手目の手をランダムに選択し、その手で進めた局面をS(N+1)とする
3. S (N+1)からRL PolicyNet(強化学習で作成したPolicyNet)で終局まで打ち、その勝敗報酬をRとする
S(N+1)とRを教師データ、損失関数を平均二乗誤差とし回帰問題として学習した。
この学習をmini batch size 32で5,000万回行った
N手までとN+1手からのPolicyNetを別々にしてある理由は過学習を防ぐためと論文には書かれている

モンテカルロ木探索
コンピュータ囲碁で最も有効とされている探索法
盤面評価値に頼らずに末端評価値(勝敗のみ)を使って探索を行うことができないかという発想で生まれた探索法である。
囲碁の最大手数はマスの数でほぼ限定されるため末端局面に到達しやすい。

現局面から末端局面までランダムシュミレーションを多数行い、その勝敗から着手の優劣を決定し、シミュレーション回数が一定数を超えたら、その手を着手したあとの局面をシミュレーション開始局面とするように探索木を成長させる。

AlphaGoのモンテカルロ木探索は選択、評価、バックアップ、成長という4ステップで構成されている。

|||
|:-|:-|
|選択|着手選択方策に従って手を選択|
|評価|局面をValueNetで評価|
|バックアップ|評価した値を積算|
|成長|選択~バックアップでの結果から探索木の成長|


###AlphaGoZero
1. 教師学習を行わなず、強化学習のみで作成
2. 特徴入力からヒューリスティックな要素を廃止し、石の配置のみを行う
3. PolicyNetとValueNetを一つのネットワークに統合した
4. ResidualNetを導入
5. モンテカルロ木探索から、RollOutシミュレーションをなくした

学習方法
・自己対局による教師データの作成
・自己対局で作成した教師データを使い学習
・学習後に現状のネットワークと学習後のネットワークで対局し勝率の高い方を採用

AlphaGoZeroのモンテカルロ木探索は選択、評価および成長、バックアップの3ステップで構成されている。

|||
|:-|:-|
|選択|着手選択方策に従って手を選択|
|評価および成長|局面をPolicyValueNetで評価し木を成長させる|
|バックアップ|評価した値を積算|

#Section3 軽量化・高速化技術

###分散深層学習
深層学習は非常に多くのデータを使用したり、パラメータの調整のために多くの時間を使用したりするため、高速な計算が求められる。
そこで複数の計算資源(ワーカー)を使用し、並列的にニューラルネットを構成することで効率のよい学習を行えるようにしたい。
**データ並列化**、**モデル並列化**、**GPU**による高速技術は必要不可欠である

###データ並列化
親モデルを各ワーカーに子モデルとしてコピーし、データを分割して各ワーカーごとに計算させる

・データ並列化：同期型
データ並列化は各モデルのパラメータの合わせ方で、同期型か、非同期型か決まる
同期型では各ワーカーの結果が終わるのを待ち、全ワーカーの勾配が出たところで勾配の平均を計算し、親モデルのパラメータ―を更新する。

・データ並列化：非同期型
各ワーカーはお互いの計算を待たず、各子モデルごとに更新を行う。
学習が終わった子モデルはパラメータサーバーにPushされる。
新たに学習を始める時は、パラメータサーバーからPopしたモデルに従って学習していく。

・同期型と非同期型の比較
処理スピードは非同期型の方が待たない分早い。
非同期型は最新モデルのパラメータを使用できないため、不安定になりやすい。
同期型の方が性能が良いことが多いので、主流になっている。

###モデル並列化
親モデルを各ワーカーに分割しそれぞれのモデルを学習させ全てのデータで学習が終わった後で、一つのモデルに復元する。
※モデルが大きいときはモデル並列化、データが大きい時はデータ並列化を行うのが効率が良い

モデルのパラメータ数が多いほど、スピードアップの効率も向上する。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/357db05c-086b-f2f2-56b3-8c5cebcc6917.png)



###GPU

|CPU|GPU|
|:-|:-|
|高性能なコアが少数|比較的低性能なコアが多数|
|複雑で連続的な処理が得意|簡単な並列処理が得意|

ニューラルネットの学習は単純な行列演算が多いので高速化が可能

GPGPU:General-purpose on GPU
元々の使用目的であるグラフィック以外の用途で使用されるGPUの総称

GPGPUの開発環境

|CUDA|OpenCL|
|:-|:-|
|GPU上で並列コンピューティングを行うためのプラットフォーム|オープンな並列コンピューティングのプラットフォーム|
|NVIDIA社製のGPUのみ|NVIDIA社以外の会社(Intel,AMD,ARMなど)のGPUからでも使用可能|
|DeepLearning用に提供されているので使いやすい|DeepLearning用の計算に特化していない|

DeepLerningフレームワークでないで実装されているため、使用するときには指定するだけで良い
※対応可能な環境かどうかも確認できる

###モデルの軽量化
モデルの精度を維持しつつパラメータや演算回数を低減する手法の総称
特にモバイル端末やIoT端末などではパソコンに比べて性能が大きく劣るため、モデルの軽量化が必須となっている。

軽量化の手法としては以下の3つがある
・量子化(Quantization)
・蒸留
・プルーニング

**量子化(Quantization)**
通常の64bit浮動小数点を32bitに落とすことでメモリと演算処理の削減を行う
しかし、デメリットとして精度は落ちる

ニューロンの重みを浮動小数点のbit数を少なくし有効桁数を下げることでニューロンのメモリサイズを小さくする
倍精度から単精度にしても実際問題として精度はあまり変わらない

**蒸留**
学習済みの精度の高いモデルの知識を使い軽量なモデルの作成を行う
学習済みのモデルを教師モデル、学習するモデルを生徒モデルとする
教師モデルはパラメータを固定し、生徒モデルの重みを更新していく。
誤差は教師モデルと生徒モデルのそれぞれの誤差を使い重みを更新していく。
蒸留することで少ない学習回数で精度のよいモデルを作成できる

**プルーニング**
モデルの精度に寄与が少ないニューロンを削減することでモデルの軽量化、高速化が見込まれる
ニューロンの削減として重みがしきい値以下の場合にニューロンを削減し再学習を行う。



#Section4 応用技術

##MobileNet
MobileNetはDeepLearningモデルの軽量化・高速化・高精度化を実現した

一般的な畳み込みレイヤーでは以下の計算量が必要となる
・入力特徴マップ(チャンネル数)：$H(幅) \times W(高さ) \times C(チャンネル数)$
・畳込みカーネルのサイズ：$K(カーネルサイズ) \times K \times C(チャンネル数)$
・出力チャンネル数(フィルタサイズ)：$M$
・出力マップ：$H(幅) \times W(高さ) \times M(マップ数)$
ストライド1，パティングを使用した場合の畳み込み計算量は・・・
$H \times W \times K \times K \times C \times M$

これを基に軽減する

###Depthwise Convolution
入力マップのチャンネルごとに畳み込みを実施し、出力マップをそれらと結合する
⇒ 通常の畳み込みは全てのフィルタを適用していたので計算量を大幅に削減

・畳込みカーネルのサイズ：$K(カーネルサイズ) \times K \times 1(チ
ャンネル数)$

となり総計算量は
$H \times W \times C \times K \times K$
となる

###PointWise Convolution
1x1convとも呼ばれ、入力マップのポイントごとに畳込みを実施

・畳込みカーネルのサイズ：$1 \times 1 \times C(チャンネル数)$

となり総計算量は
$H \times W \times C \times M$
となる


##DenseNet
ニューラルネットワークでは層が深いほど表現力が増すが学習が難しくなる。
これを解決するためにDenthBlockと呼ばれるモジュールを用いたのがDenseNet。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/6efa95ac-146e-4533-58f7-2c593aa7e541.png)


DenthBlockでは前方の各層からの出力全てが後方の層への入力へとも位置られる。※ResNetのResidualBlockでは前1層の入力のみ後方へ伝えられる

いくつかのレイヤーがあり、通過するごとにチャンネルが増える
特徴マップの入力に対し、下の処理で出力を計算する
- Batch正規化
- ReLU関数による返還
- 3x3畳込み層による処理
前の結果を付け加えることでチャンネル数が増加する

DepthBlockとDepthBlockの間にはTransisionLayerと呼ばれる層があり特徴マップのサイズを変更してダウンサンプリングを行う。
ここでサイズ変更を行うためDenthBlockで増加したチャンネルを戻すことができる

DenthBlock内には成長率(Growth Rate)と呼ばれるハイパーパラメータkが存在し、各ブロック毎に増加する特徴マップのチャンネル数を表す。
kが大きくなるほど、ネットワークが大きくなるため小さな整数に設定するのがよい

##正規化
**Batch Norm Layer**
レイヤー間を流れるデータの分布をミニバッチ単位で平均が0、分散が1になるように正規化することで学習時間の短縮や初期値への依存低減、過学習の抑制などの効果がある

ただしBatch Sizeが小さい条件下では学習が収束しないことがあり、代わりにLayer Normalizationなどの正規化手法が使われることが多い

**Batch Norm**
ミニバッチに含まれるsampleの同一チャネルが同一分布に従うよう正規化

**Layer Norm**
それぞれのsampleの全てのpixelsが同一分布に従うよう正規化
Layer Normは入力データや重み行列に対して、以下の操作を行っても出力が変わらないことが知られている。
・入力データのスケールに関してロバスト
・重み行列のスケールやシフトに関してロバスト

**Instance Norm**
さらにchannelも同一分布に従うよう正規化
コントラストの正規化に寄与し画像のスタイル転送やテクスチャ合成タスクなどで使用される。

##Wavenet
生の音声波形を生成する深層学習モデル
Pixel CNNを音声に応用している

時系列データに対して畳込みを適用している。
Dilated convolutionでは層が深くなるにつれて畳み込むリンクを離す。

#Section5 Transformer
ニューラル機械翻訳の問題点としては、長さに弱い。
翻訳元の分の内容を一つのベクトルで表現しようとするため、文長が長くなると表現力が足りなくなってしまう。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/e89e7887-d659-77f9-c6b6-8fa9ee5ee0d5.png)


この問題に対してAttention(注意機構)が作られた。
Attention機構では翻訳先の各単語を選択する際に、翻訳元の文中の各単語の隠れ状態を利用する。

このの隠れ状態をQueryとした場合にkeyとvalueが1対1で対応する辞書オブジェクトで、queryとkeyの内積が類似度を表す。


```math
Attention(Q, K, V) = softmax(QK^T)V
```

$Q$：Query(辞書クエリ)
$K$：Key(辞書キー)
$V$：Value(辞書の値)

Attentionは辞書オブジェクトでquery(検索クエリ)に一致するkeyを牽引し、対応するvalueを取り出す操作である


この機構により文長が長くなっても翻訳精度が落ちないことが確認された。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/24c5adfc-cea5-b07b-ecad-a50997eb455c.png)


また、AttentionはRNNを使わずに当時のSOTAをはるかに少ない計算量で実現した

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/b3392b2f-331b-ec86-3712-4c99ad23fe57.png)


###Attention
注意機構には以下の2種類がある
・Source Target Attention (ソース・ターゲット注意機構)
・Slef Attention (自己注意機構)

自己注意機構では入力が自己であるため全ての情報をフラットにして楽手的に注意個所を決めていく

###Position-Wise Feed-Forword Network
位置情報を保持したまま順伝播させる


###Scaled Dot-Product Attention
全単語に関するAttentionをまとめて計算する

```math
Attention(Q, K, V) = softmax(\frac{QK^T}{\sqrt{d_k}})V
```

###Multi-Head attenion
重みの異なる8個のヘッドを使用している
8個のScaled Dot-Product Attention の出力をConcatする
それぞれのヘッドが異なる種類の情報を収集する

###Decoder
6層で構成される


###Add&Norm
Add(Residual Connection)
- 入出力の差分を学習させる
- 実装上は出力に入力をそのまま加算する
⇒ 学習・テストエラーの低減

Norm(LayerNormalization)
- 各層においてバイアスを除く活性化関数への入力を平均0分散1に正規化
⇒ 学習の高速化

###Position Encoding
RNNを使用しないので単語列の語順情報を追加する必要がある
そこで単語の位置情報もエンコードする

```math
PE_{(pos,2i)}=sin(\frac{pos}{10000^{2i/512}})\\
PE_{(pos,2i+1)}=cos(\frac{pos}{10000^{2i/512}})

```

$pos$：時刻
$i$：Embeddingの次元番号

このようにすることで$x,y$の二次元平面のように線形関数で表現しやすくしている。




#Section6 物体検知・セグメンテーション (124)

###データ

||出力|
|:-|:-|
|分類|画像全体に対して単一、または複数のクラスラベル|
|物体検知|Bounting Box (bbox/BB) 矩形|
|意味領域分割|各ピクセルに対して単一のクラスラベル|
|個体領域分割|各ピクセルに対して単一のクラスラベル|

代表的なデータセット

||クラス数|データ数|BOX数/画像|
|:-:|:-:|:-:|:-:|
|VOC12|20|11,540|2.4|
|ILSVRC17|200|476,668|1.1|
|MS COCO18|80|123,287|7.3|
|OICOS18|500|1,743,042|7.0|

BOX数/画像が小さいほどアイコン的で大きいほど現実に近い
クラス数だけでなく目的に応じたデータセットを選ぶ必要あり

###評価指標

混合行列(Confusion Matrix)

|真値\予測|Positive|Negative|
|:-:|:-:|:-:|
|Positive|TP(True Positive)|FN (False Negative)|
|Negative|FP (False Positive)| TN (True Negative)|

TP:実際に写っているものを正解予測した
FN:実際に写っているものを予測しなかった・・・未検出
FP:実際に写っていないものを間違って予測した・・・誤検出
TN:実際に写っていないものを予測しなかった

正解予測を縦に見て予測した場合の正解率を出すことができる

```math
Precision=\frac{TP}{TP+FP}
```

実際に正解を横に見て真値が予測される確率がわかる

```math
Recall=\frac{TP}{TP+FN}
```

confidenceのしきい値を変化させることでPrecision-Recall curveを描くことができる

###IoU (intersection over Union)
物体位置の予測精度を評価するために使用

```math
Iou = \frac{Area\ of\ Overlap}{Area\ of\ Union}
```
予測した矩形と真の矩形の重なり領域を、予測した矩形と真の矩形を足した領域で割っている
全て重なっている場合に1となり、まったく重なっていない場合に0となる

ConfusionMatrixの要素を用いて表現すると

```math
IoU = \frac{TP}{TP+FP+FN}
```

別名でJaccarrd係数とも呼ばれる

###Average Precision (平均適合率)
IoUのしきい値はそのままで、物体のConf値(一定以上を物体とする)を変えていった時のPrecision, Recallを求める
conf値のしきい値をβとするとき

```math
Recall=R(\beta), Precision = P(\beta)\\
AP=\int_{0}^{1}P(R)dR
```

横軸をRecall,縦軸をPrecisionとして表にしたときにAPはprecision-recall曲線の下の部分の面積を表す。
値は常に0から1の値となる

###mean Average Precision
クラス数がCの場合

```math
mAP=\frac{1}{C}\sum_{i=1}^{C}AP_i
```

とすることで全てのクラスについて平均している

###FPS(Flames per Second)
検出速度の指標
1秒あたりに処理できる枚数

###物体検知のフレームワーク
物体検知には2つのタイプがある

||2段階検出器(Two stage detector)|1段階検出器(one-stage detector)|
|:-|:-|:-|
|精度|高い|低い|
|推論速度|遅い|速い|

###SSD (Single Shot Detector)
SSDは1段階検出器で物体の領域検出とクラス分類を同時に行う
VGG16をベースに作成されている
予測時にはそれぞれのレイヤーから特徴マップを取得しクラス分類に使用する


#確認テスト
###MobileNet (86P)
Depthwise Separable Convolutionという手法を用いて計算量を削減している。通常の畳込みが空間方向とチャネル方向の計算を同時に行うことに対して、Depthwise Separable ConvolutionではそれらをDepthwise ConvolutionとPointwise Convolutionと呼ばれる演算によって個別に行う。

Depthwise Convolutionはチャネルごとに空間方向へ畳込む。すなわち、チャネル毎に$D_k \times D_k \times 1$のサイズのフィルターをそれぞれ用いて計算を行うため、その計算量は(い)となる。

次にDepthwise Convolutionの出力をPointwise Convolutionによってチャネル方向に畳み込む。すなわち、出力チャネルごとに$1 \times 1 \times M$サイズのフィルターをそれぞれ用いて計算を行うため、その計算量は(う)となる

回答
い：$H \times W \times C \times K \times K$
う：$H \times W \times C \times M$

###Wavenet (106P)
問：深層学習を用いて結合確立を学習する際に、効率的に学習が行えるアーキテクチャを提案したことがWaveNetの大きな貢献の一つである。
提案された新しいConvokution型アーキテクチャは(あ)と呼ばれ、結合確立を効率的に学習できるようにする。

回答：Dilated causal convolution
・Depthwise separable convolutionはMobileNetで用いられる畳み込み手法
・Pointwise convolutionもMobileNetで用いられている手法
・DeconvolutionはGANなどで元画像を復元することに使用

問(あ)を用いた際の大きな利点は、単純なConvolution layerと比べて(い)ことである。

回答：パラメータ数に対する受容野が広い

#実装
###4_1_tensorflow_codes.pyの実行
まずはtensorflowを動くようにインストール

```Python
pip install tensorflow
```

しかしエラーが出てインストールできない。
原因はLongPathに未対応とのことで以下で対応
https://docs.microsoft.com/en-us/windows/win32/fileio/maximum-file-path-limitation?tabs=cmd#enable-long-paths-in-windows-10-version-1607-and-later
Windows 10バージョン1607以降で削除されたらしいので復活させる
レジストリの以下を1にComputer\HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem\LongPathsEnabled (Type: REG_DWORD)

インストール完了し実行したところ

```
module 'tensorflow' has no attribute 'Session'
```

とのこと・・・
どうやらV2では不要ならしく「.compat.v1」を挟むといいらしい

```Python
sess = tf.compat.v1.Session()
```

しかしここは通過しても

```
The Session graph is empty. Add operations to the graph before calling run().
```

のエラーが発生
Session()を呼び出す前にdisable_eager_execution()を呼び出すとよいらしい

```Python
tf.compat.v1.disable_eager_execution()
sess = tf.compat.v1.Session()
```

一応これで問題の個所は通過したのだが、もっと楽にできないかと探していたところ
https://www.tensorflow.org/guide/migrate

```Python
import tensorflow.compat.v1 as tf
tf.disable_v2_behavior()
```

これでV1コードが動作するらしい
実際試したところ問題なく動作している
途中までは・・・

###tf.session

TensorflowはDefien-and-Run形式で、先に計算グラフを作成してから実行する。
tf.sessionに値を設定し、tf.runを実行することで値が出力される。

```Python
import tensorflow.compat.v1 as tf
import numpy as np

tf.disable_v2_behavior()

#tf.compat.v1.disable_eager_execution()
sess = tf.compat.v1.Session()

# それぞれ定数を定義
a = tf.constant(1)
b = tf.constant(2, dtype=tf.float32, shape=[3,2])
c = tf.constant(np.arange(4), dtype=tf.float32, shape=[2,2])

print('a:', a)
print('b:', b)
print('c:', c)

sess = tf.Session()

print('a:', sess.run(a))
print('b:', sess.run(b))
print('c:', sess.run(c))
```

実行結果

```Python
a: Tensor("Const:0", shape=(), dtype=int32)
b: Tensor("Const_1:0", shape=(3, 2), dtype=float32)
c: Tensor("Const_2:0", shape=(2, 2), dtype=float32)
a: 1
b: [[2. 2.] [2. 2.] [2. 2.]]
c: [[0. 1.] [2. 3.]]
```

tf.constant()で定数を定義する
sees = tf.Session()でセッションを作成
sess.run()で実行される
定義した時点では型を定義しただけでrunすることで値が入る

###tf.placeholder

```Python
import tensorflow.compat.v1 as tf
import numpy as np
tf.disable_v2_behavior()

# プレースホルダーを定義
x = tf.placeholder(dtype=tf.float32, shape=[None,3])

print('x:', x)

sess = tf.Session()

X = np.random.rand(2,3)
print('X:', X)

# プレースホルダにX[0]を入力
# shapeを(3,)から(1,3)にするためreshape
print('x:', sess.run(x, feed_dict={x:X[0].reshape(1,-1)}))
# プレースホルダにX[1]を入力
print('x:', sess.run(x, feed_dict={x:X[1].reshape(1,-1)}))
```

実行結果

```Python
x: Tensor("Placeholder:0", shape=(?, 3), dtype=float32)
X: [[0.64251042 0.3131871  0.52888782]
 [0.77237512 0.31842441 0.64704635]]
x: [[0.6425104 0.3131871 0.5288878]]
x: [[0.7723751 0.3184244 0.6470463]]
```

placeholderを使うことで置き場を確保することができます
placeholderの値はセッション実行時にfeed_dictに指定することで使用できます。

###tf.variables

```Python
# 定数を定義
a = tf.constant(10)
print('a:', a)
# 変数を定義
x = tf.Variable(1)
print('x:', x)

calc_op = x * a

# xの値を更新
update_x = tf.assign(x, calc_op)

sess = tf.Session()

# 変数の初期化
init = tf.global_variables_initializer()
sess.run(init)

print(sess.run(x))

sess.run(update_x)
print(sess.run(x))

sess.run(update_x)
print(sess.run(x))
```

実行結果

```Python
a: Tensor("Const_3:0", shape=(), dtype=int32)
x: <tf.Variable 'Variable:0' shape=() dtype=int32_ref>
1
10
100
```

Variableは変数を作成します
tf.initialize_all_variables()で変数は初期化されます
変数の値を変更するにはtf.assignで変更する変数、変更後の値を設定します
calc_opにはx*a(10)が入っているため、runを呼び出すたびにxは10倍されます。


###線形回帰

noise/dの値を変えて実行する

```Python
# データを生成
n = 100
x = np.random.rand(n)
d = 6 * x + 2

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

実行結果

|noise\d|3*x+2|6*x+2|9*x+2|
|:-:|:-:|:-:|:-:|
|0.3|![img1_0.3-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/a0ece540-5cd2-a2cf-02f5-7d3d85a3d474.png)|![img1_0.3-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/24c31203-8b7f-f252-6ecf-727449b8381b.png)|![img1_0.3-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/13f3c22f-f0ee-0eed-9d4d-2a9e99fa470c.png)|
|0.5|![img1_0.5-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/86c14f76-a1f3-c091-aef6-ed405d74e6a3.png)|![img1_0.5-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/c212c38a-a9b9-53bc-877f-72022e00e7a2.png)|![img1_0.5-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/3b068c3b-e6d8-21d1-2938-16fb2af8c63a.png)|
|0.7|![img1_0.7-3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/f17c8210-4ad5-9842-a888-7fdeb35270fc.png)|![img1_0.7-6.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/2e53ba35-7620-44d1-f6ca-65dd535c01c0.png)|![img1_0.7-9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/093cd81a-d4a3-4a53-0bcb-dcd0f1d854a3.png)|

dを大きくするほど線形なまま縦への広がりが大きくなり、noiseが大きいほどデータが分散する

###非線形回帰

noise/dの値を変えて実行する

```Python
# データを生成
n=100
x = np.random.rand(n).astype(np.float32) * 4 - 2
d =  - 0.4 * x ** 3 + 1.6 * x ** 2 - 2.8 * x + 1

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

|noise\d|+1|+20|+50|
|:-:|:-:|:-:|:-:|
|0.05|![img2_0.05-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/f3672124-0793-2fda-f1cf-c168f45988ce.png)|![img2_0.05-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/0007c6d9-bd46-59ba-8a6f-c48f6746591f.png)|![img2_0.05-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/030d0e81-89e1-a1d5-021a-736021e89081.png)|
|0.50|![img2_0.50-1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/72551f0c-8254-bdda-cb73-b99fdb4c0ab0.png)|![img2_0.50-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/895662f8-d809-592a-b0ba-a0edcab9ea44.png)|![img2_0.50-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/6012c45b-f058-aa1c-5c64-d8a0967c7aad.png)|
|0.80|![img2_0.80-10.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/f8ac2ae0-6b70-d17d-c0f4-b58fea5d5cf2.png)|![img2_0.80-20.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/53efe329-03bc-643c-243a-dfa65aba02ca.png)|![img2_0.80-50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/1883771/b8437609-5e0a-b0be-ff32-3da1cd323ea8.png)|

###tensorflowチュートリアルの実行
https://www.tensorflow.org/tutorials/images/cnn

MNISTの数の分類をCNNで行います

```Pyhton
import tensorflow as tf
from tensorflow.keras import datasets, layers, models

(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images, test_images = train_images / 255.0, test_images / 255.0

model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

model.summary()

model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

model.fit(train_images, train_labels, epochs=5)

test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print(test_acc)
```

実行結果

```Python
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #
=================================================================
 conv2d (Conv2D)                 (None, 26, 26, 32)       320
 max_pooling2d (MaxPooling2D)    (None, 13, 13, 32)       0
 conv2d_1 (Conv2D)               (None, 11, 11, 64)       18496
 max_pooling2d_1 (MaxPooling2D)  (None, 5, 5, 64)         0
 conv2d_2 (Conv2D)               (None, 3, 3, 64)         36928
 flatten (Flatten)               (None, 576)              0
 dense (Dense)                   (None, 64)               36928
 dense_1 (Dense)                 (None, 10)               650
=================================================================
Total params: 93,322
Trainable params: 93,322
Non-trainable params: 0
_________________________________________________________________
Epoch 1/5
1875/1875 [==============================] - 29s 15ms/step - loss: 0.1434 - accuracy: 0.9550
Epoch 2/5
1875/1875 [==============================] - 29s 16ms/step - loss: 0.0451 - accuracy: 0.9865
Epoch 3/5
1875/1875 [==============================] - 30s 16ms/step - loss: 0.0340 - accuracy: 0.9895
Epoch 4/5
1875/1875 [==============================] - 30s 16ms/step - loss: 0.0260 - accuracy: 0.9919
Epoch 5/5
1875/1875 [==============================] - 29s 16ms/step - loss: 0.0203 - accuracy: 0.9933
313/313 - 2s - loss: 0.0305 - accuracy: 0.9905 - 2s/epoch - 6ms/step
0.9904999732971191
```

内容

MNISTデータの準備を行います

```Python
(train_images, train_labels), (test_images, test_labels) = datasets.mnist.load_data()

train_images = train_images.reshape((60000, 28, 28, 1))
test_images = test_images.reshape((10000, 28, 28, 1))

train_images, test_images = train_images / 255.0, test_images / 255.0
```

MNISTデータは標準セットに準備されているため簡単にロードできます
数値の画像(images)とその正解データ(labels)が学習用と評価用それぞれで取得できます
画像データは0~255の輝度データなので0~1.0のfloat型に変換します
```

次にCNNのモデルを作成します。

```Python
model = models.Sequential()
model.add(layers.Conv2D(32, (3, 3), activation='relu', input_shape=(28, 28, 1)))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.MaxPooling2D((2, 2)))
model.add(layers.Conv2D(64, (3, 3), activation='relu'))
model.add(layers.Flatten())
model.add(layers.Dense(64, activation='relu'))
model.add(layers.Dense(10, activation='softmax'))

model.summary()

```

最初にSequential型でモデルをインスタンス化し、addでレイヤーを追加していきます。
summaryを呼び出すことで現在のレイヤー構成が表示されます。

次に学習方法を設定します

```Python
model.compile(optimizer='adam',
              loss='sparse_categorical_crossentropy',
              metrics=['accuracy'])

```

compileで学習方法を決定します
optimizerに最適化方法を指定、lossに損失関数を指定、metricsに

次に学習を開始します。

```Python
model.fit(train_images, train_labels, epochs=5)
```

学習画像と正解ラベル、エポック数を指定して学習を実行します。

学習済みモデルの評価を行います

```Python
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)
print(test_acc)
```

他にmodel.predictで学習済みモデルを使った推論、model.saveでモデルの保存などが行えます。