Keras

※以下、個人的な勉強のためのレポートです。
※間違い多々あると存じますが、現在の理解レベルのスナップショットのようなものです。
※勉強のためWebサイトや書籍からとても参考になったものを引用させていただいております。
http://ai999.careers/rabbit/

#Keras
https://ja.wikipedia.org/wiki/Keras
https://qiita.com/iss-f/items/b12308b44376ba69ac6a
Kerasは、Pythonで書かれたオープンソースニューラルネットワークライブラリ。MXNet、Deeplearning4j(JavaのDNNライブラリ)、TensorFlow、CNTK(MicroSoftのDNNライブライ)、Theanoの上部で動作することができる。DNNを用いた迅速な実験を可能にするよう設計され、最小限、モジュール式、拡張可能であることに重点が置かれている。プロジェクトONEIROS (Open-ended Neuro-Electronic Intelligent Robot Operating System) の研究の一部として開発された。中心的な開発者、メンテナはGoogleのエンジニアのFrançois Chollet。Cholletは、Kerasはタスク全体を担う機械学習ライブラリよりむしろインターフェースとして着想された、と説明した。Kerasはバックエンドの科学計算ライブラリにかかわらず、ニューラルネットワークの設定を容易に行うことができる、より高いレベルでより直感的な一連の抽象化を提供している。MicrosoftはKerasにCNTKバックエンドを追加する作業を行っている。
⇒いわゆるラッパーなので、Kerasを使用するためには、TesorFlow等が必要になる。
⇒TensorFlowより、NNの実装が容易になる。
⇒https://keras.io/ja/　←公式

##モデル定義
「Sequentialモデル」「functional APIを用いたモデル」の二通りの方法がある。
https://qiita.com/Ishotihadus/items/c2f864c0cde3d17b7efb

〇Sequentialモデル
https://keras.io/ja/getting-started/sequential-model-guide/
1層前の出力をそのまま入力する、層を積み上げるモデル。

dense:通常の全結合ニューラルネットワークレイヤー
input_dim:入力層
output_dim:出力層
Activation:活性化関数
nb_epoch:学習回数
validation_split:検証に使うデータの割合
units:正の整数、出力空間の次元数

#Kerasによる線形回帰

```
#データの生成
#np.linspaceは等差数列を生成する関数、指定した区間をN等分した数列を生成
#https://deepage.net/features/numpy-linspace.html
x = np.linspace(-1, 1, 200)
#元のリストをランダムソート
np.random.shuffle(x)
#重み0.5、バイアス2、0-0.05までの正規分布に従うノイズを＋
d = 0.5 * x + 2 + np.random.normal(0, 0.05, (200,))

from keras.models import Sequential
from keras.layers import Dense

#TensorFlowを違い、x、y、Wやbのプレースホルダを作らなくても良い
#Variablesでの変数定義も不要

# モデルを作成
model = Sequential()
model.add(Dense(input_dim=1, output_dim=1))

# モデルを表示
model.summary()

# モデルのコンパイル
#TensorFlowと異なり、ここで最適化関数や学習方法を定義する
#mse:二乗誤差(mean square error)、sgd:勾配降下法
model.compile(loss='mse', optimizer='sgd')

# train
#for文を使わずに、epochを定義すればmode.trainで繰り返し実行してくれる
for i in range(iters_num):
    #学習
    loss = model.train_on_batch(x, d)
    if (i+1) % plot_interval == 0:
        print('Generation: ' + str(i+1) + '. 誤差 = ' + str(loss))

#layers[0] 0層目の重み、バイアスの取得
W, b = model.layers[0].get_weights()
print('W:', W)
print('b:', b)

```


#実行結果
##生成されたモデル

```
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_2 (Dense)              (None, 1)                 2         
=================================================================
Total params: 2
Trainable params: 2
Non-trainable params: 0
_________________________________________________________________
```
##グラフ
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/405299/27152cef-899c-88a0-3b18-4b51cd964235.png)

#kerasによる単純パーセプトロン
回路の動作、分類で有名
〇OR回路：二つの入力を受付け、01/10/11の場合、True。00の場合Falseを出力する論理回路

```
X = np.array( [[0,0], [0,1], [1,0], [1,1]] )
T = np.array( [[0], [1], [1], [1]] )
```

学習

```
#for文を使わずとも、epochsで定義した回数だけ学習してくれる
#natch1回の学習で、4回(Xの要素は4)学習が回るので、120回(X × epochs)の学習
model.fit(X, T, epochs=30, batch_size=1)
```

出力：分類

```
Y = model.predict_classes(X, batch_size=1)
```

##model.summary()の結果

```
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense_3 (Dense)              (None, 1)                 3         
_________________________________________________________________
activation_1 (Activation)    (None, 1)                 0         
=================================================================
```

###最終結果
TEST
 [ True]
 [ True]
 [ True]
 [ True]

##諸要素の変更
###random_seedの変更
システムが取ってくる初期値が変わるので、NN学習のされ方が変化する
⇒DNNでは初期値によって学習の様子が変わる。よって、初期値の与え方による学習進度/精度の違いについては、平均を取る等して考察する必要がある。
###epochsの変更
基本的に、学習回数を増やすことで、基本的に学習データのロスは減少していく。汎化性能を重視する必要があるため、頭打ちになるのはどこなのか見極める必要がある。
###AND回路への変更

```
X = np.array( [[0,0], [0,1], [1,0], [1,1]] )
T = np.array( [[0], [0], [0], [1]] )
```
正解データが変更されたことで、再度学習する。
結果、うまくいかなくなる。
⇒1層パーセプトロンは、線形分類にしか適用できない。

###バッチサイズの変更
バッチサイズを増やすことで、1エポックあたりの学習回数を減らすことができるので、学習速度の向上につなげることができる。
※GPUの性能を引き出す際には、バッチサイズは一般的には2の乗数にするのが良い
データ数が多いときにはバッチサイズを大きくし、データ数が少ないときにはバッチサイズを小さくする。