TensorFlowのチュートリアルをコメント付けながら実行してみた（初心者のための_TensorFlow_2_0_入門）

参考URL：https://www.tensorflow.org/tutorials/quickstart/beginner?hl=ja



# 目標
以下のことを行う
- 画像を分類するニューラルネットワークを構築する
- ニューラルネットワークを訓練する
- モデルの性能を評価する

## パッケージの用意


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


```python
# tensorflowのver確認
print(tf.__version__)
```

    2.3.0


## データセットを用意
今回はMNISTを使用する

他のデータセット：https://www.tensorflow.org/api_docs/python/tf/keras/datasets?hl=JA


```python
mnist = tf.keras.datasets.mnist

(x_train, y_train), (x_test, y_test) = mnist.load_data()

# サンプルを整数から浮動小数点数に変換（0から255を0から1の範囲に変換） 
x_train, x_test = x_train / 255.0, x_test / 255.0
```

    Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz
    11493376/11490434 [==============================] - 0s 0us/step



```python
# データの形を確認
print(x_train.shape)
print(x_test.shape)
```

    (60000, 28, 28)
    (10000, 28, 28)


- 訓練データ：60000枚
- テストデータ：10000枚

## モデルの構築

### 処理の流れ


1.   28✖️28の２次元データを１次元に平滑（へいかつ）化
    > tf.keras.layers.Flatten  
    > input_shape=(28, 28)で入力されるデータの形を指定している
2.   隠れ層の定義
    > tf.keras.layers.Dense  
    > 128はユニットの数（ニューロンの数）
    > activation='relu'は活性化関数　ReLUを指定している  
    > 他の活性化関数：https://www.tensorflow.org/api_docs/python/tf/keras/activations?hl=ja
3.   ドロップアウトの定義
    > 過学習を防ぐためにランダムにいくつかのニューロンを無効にする
    > 0.2で2割を無効にする
4.   全結合層の定義
    > 最終的に10個クラスに分類するので10を指定する


```python
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),
  tf.keras.layers.Dense(128, activation='relu'),
  tf.keras.layers.Dropout(0.2),
  tf.keras.layers.Dense(10)
])
```

### 学習前の予測

クラスごとに"ロジット"や"対数オッズ比"と呼ばれるスコアを算出する

#### 予測するデータを可視化

数字の5かな？？


```python
plt.figure()
plt.imshow(x_train[0] * 255, cmap="gray")
plt.grid(False)
plt.show()
```

![output_14_0.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/534121cb-5f17-d7f1-a327-026d27f856cc.png)



#### 学習前のモデルで予測


```python
predictions = model(x_train[:1]).numpy()
predictions
```




    array([[-0.68039566,  0.24756509,  0.03884459,  0.13278663, -0.09757528,
            -0.41739488, -0.07566899, -0.00817996,  0.17783645,  0.13316259]],
          dtype=float32)



#### 予測時の投入するデータの形
`x_train[0]`だと形が合わないので注意  
モデルは、サンプルの中のバッチ（batch）あるいは「集まり」について予測を行うように作られている


```python
print(x_train[0].shape)
print(x_train[:1].shape)
```

    (28, 28)
    (1, 28, 28)


#### スコアを確率に変換


```python
predictions_probability = tf.nn.softmax(predictions).numpy()
print(predictions_probability)
# 予測された確率から最大要素のインデックスを取得
np.argmax(predictions_probability)
```

    [[0.05172387 0.13082756 0.10618253 0.1166411  0.09264173 0.06728384
      0.09469356 0.10130493 0.12201592 0.11668495]]





    1



## 損失関数の定義

#### 損失関数

交差エントロピーを採用している

他の損失関数：https://www.tensorflow.org/api_docs/python/tf/keras/losses?hl=ja


```python
loss_fn = tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True)
```


```python
loss_fn(y_train[:1], predictions).numpy()
```




    2.6988351



#### モデルのコンパイル
学習のためのモデルを定義している

- optimizer：最適化アルゴリズム
    - 今回は`Adam`を指定
    - その他の最適化アルゴリズム：https://www.tensorflow.org/api_docs/python/tf/keras/optimizers
- loss：損失関数
    - 今回は`交差エントロピー`を指定
- metrics：学習及びテスト中に定量化される項目
    - 今回は`accuracy（正確性）`を指定


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

#### モデルの学習
エポックを5にして学習を行う  
エポック：１つの訓練データを何回繰り返して学習させるか」の数のこと


```python
model.fit(x_train, y_train, epochs=5)
```

    Epoch 1/5
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.2981 - accuracy: 0.9127
    Epoch 2/5
    1875/1875 [==============================] - 4s 2ms/step - loss: 0.1435 - accuracy: 0.9572
    Epoch 3/5
    1875/1875 [==============================] - 3s 2ms/step - loss: 0.1079 - accuracy: 0.9671
    Epoch 4/5
    1875/1875 [==============================] - 3s 2ms/step - loss: 0.0875 - accuracy: 0.9728
    Epoch 5/5
    1875/1875 [==============================] - 3s 2ms/step - loss: 0.0750 - accuracy: 0.9768





    <tensorflow.python.keras.callbacks.History at 0x7f12f819d5c0>



#### モデルの性能評価

テストデータを使用してモデルの損失値と正確性を算出する  
`verbose`はプログレスバーを表示するかどうかのオプション  
今回のモデルはテストデータにおいて97%の正解率を示している


```python
model.evaluate(x_test,  y_test, verbose=1)
```

    313/313 [==============================] - 0s 1ms/step - loss: 0.0742 - accuracy: 0.9772





    [0.07416515052318573, 0.9771999716758728]



#### モデルの出力を変更
数値ではなく確率を出力する場合


```python
probability_model = tf.keras.Sequential([
  model,
  tf.keras.layers.Softmax()
])
```


```python
predictions = probability_model(x_test[:5])

# 予測と正解を可視化して比べてみる
for index, prediction in enumerate(predictions):
    print(f'予測：{np.argmax(prediction)} 正解：{y_test[index]}')
    ax = plt.subplot(3, 3, index + 1)
    plt.imshow(x_test[index] * 255, cmap="gray")
    plt.show()
```

    予測：7 正解：7


![output_33_1.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/f467b144-8cdd-5855-4e4a-8fe5fe16ecf2.png)


    予測：2 正解：2



![output_33_3.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/6aa6dd2a-eeee-8282-05ca-8d73807ace56.png)



    予測：1 正解：1


![output_33_5.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/a149185f-b25c-4b2a-4639-3754b237950b.png)



    予測：0 正解：0


![output_33_7.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/dd7bcbe4-5953-1951-e6d8-069d20bb325f.png)


    予測：4 正解：4


![output_33_9.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/190554/b080b3e1-a439-eb75-3971-05558df6b89b.png)