TensorFlow 2.0でのMINSTの実行とTensorBoardでの可視化まで(2019年版)

# はじめに
* TensorFlow公式チュートリアルの[Beginner quickstart](https://www.tensorflow.org/tutorials/quickstart/beginner?hl=ja)では、MNISTデータセットを使用した学習と評価のサンプルが載っています。
* 本記事ではMINSTの学習、評価を実際にやってみるのと、TensorBoardで学習過程やデータフローを可視化するとこまでを書こうと思います。

# 環境
* Windows10 Pro 64bit
* Python 3.7.4
* Visual Studio Code 1.40
* 外部接続にプロキシ認証が必要

# TensorFlowの導入
* コマンドプロンプトからpipでインストール、実施環境はプロキシ配下のためプロキシ設定も事前に実施

```python
set HTTP_PROXY=プロキシ設定
set HTTPS_PROXY=プロキシ設定

pip install tensorflow
```

# MINSTの実行
* 公式チュートリアルの内容をそのままコピペする

```python
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf

# データロード
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 層を積み重ねてtf.keras.Sequentialモデルを構築
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),  # 28×28サイズの2次元データを784の1次元データに平滑化
  tf.keras.layers.Dense(128, activation='relu'),  # 活性化関数にランプ関数を指定
  tf.keras.layers.Dropout(0.2),                   # 過学習を防ぐためのドロップアウト率の指定
  tf.keras.layers.Dense(10, activation='softmax') # 活性化関数にソフトプラスを指定
])

# 訓練のためにオプティマイザと損失関数を選ぶ
model.compile(optimizer='adam',  #どうやって学習を最適化するかを決定
              loss='sparse_categorical_crossentropy',  #どうやって損失を定義するかを決定
              metrics=['accuracy'])

# モデルを訓練する
model.fit(x_train, y_train, epochs=5)

# モデルの損失値と評価値を返却する
model.evaluate(x_test,  y_test, verbose=2)
```

* このまま実行するとデータロード部分でプロキシ認証エラーになる
* プロキシ設定がめんどくさいので、ブラウザを使用して直接データをダウンロードする[(ダウンロードURLはこちら)](https://storage.googleapis.com/tensorflow/tf-keras-datasets/mnist.npz)
* ダウンロードしたデータファイル(mnist.npz)を以下に配置すればローカル読み込みが行われる

```bat:データ配置先
C:\Users\ユーザ名\.keras\datasets
```

* データファイルをローカル配置した状態で、上記スクリプトを実行すると以下結果が出力される

```bat:実行結果
Train on 60000 samples
Epoch 1/5
2019-11-13 14:08:58.762382: I tensorflow/core/profiler/lib/profiler_session.cc:184] Profiler session started.
60000/60000 [==============================] - 5s 82us/sample - loss: 0.2946 - accuracy: 0.9146 - val_loss: 0.1343 - val_accuracy: 0.9589
Epoch 2/5
60000/60000 [==============================] - 4s 66us/sample - loss: 0.1435 - accuracy: 0.9578 - val_loss: 0.1014 - val_accuracy: 0.9698
Epoch 3/5
60000/60000 [==============================] - 4s 67us/sample - loss: 0.1082 - accuracy: 0.9675 - val_loss: 0.0840 - val_accuracy: 0.9737
Epoch 4/5
60000/60000 [==============================] - 4s 67us/sample - loss: 0.0852 - accuracy: 0.9743 - val_loss: 0.0780 - val_accuracy: 0.9758
Epoch 5/5
60000/60000 [==============================] - 4s 66us/sample - loss: 0.0742 - accuracy: 0.9767 - val_loss: 0.0686 - val_accuracy: 0.9780
10000/1 - 0s - loss: 0.0365 - accuracy: 0.9780
```

* **accuracy: 0.9780**がテストデータを使用しての正解率

# TensorBoardを使用した学習過程とかの可視化
* TensorBoard用のログを出力するようスクリプトを変更

```python
from __future__ import absolute_import, division, print_function, unicode_literals
import tensorflow as tf

# データロード
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train, x_test = x_train / 255.0, x_test / 255.0

# 層を積み重ねてtf.keras.Sequentialモデルを構築
model = tf.keras.models.Sequential([
  tf.keras.layers.Flatten(input_shape=(28, 28)),  # 28×28サイズの2次元データを784の1次元データに平滑化
  tf.keras.layers.Dense(128, activation='relu'),  # 活性化関数にランプ関数を指定
  tf.keras.layers.Dropout(0.2),                   # 過学習を防ぐためのドロップアウト率の指定
  tf.keras.layers.Dense(10, activation='softmax') # 活性化関数にソフトプラスを指定
])

# 訓練のためにオプティマイザと損失関数を選ぶ
model.compile(optimizer='adam',  #どうやって学習を最適化するかを決定
              loss='sparse_categorical_crossentropy',  #どうやって損失を定義するかを決定
              metrics=['accuracy'])

# tensorboard用ログ出力コールバック関数
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="log_dir", histogram_freq=1)

# モデルを訓練する
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test), callbacks=[tensorboard_callback])

# モデルの損失値と評価値を返却する
model.evaluate(x_test,  y_test, verbose=2)
```

* 変更箇所だけ抜粋。

```python
# tensorboard用ログ出力コールバック関数
tensorboard_callback = tf.keras.callbacks.TensorBoard(log_dir="log_dir", histogram_freq=1)

# モデルを訓練する
model.fit(x_train, y_train, epochs=5, validation_data=(x_test, y_test), callbacks=[tensorboard_callback])
```

* 変更したスクリプトを実行すると、スクリプトの格納されたフォルダに「log_dir」フォルダが生成される。
* 「log_dir」フォルダが存在する状態で、以下をコマンドプロンプトから実行

```python
tensorboard --logdir='./log_dir'
```

* 以下にブラウザでアクセスするとTensorBoard画面が表示できる
  * http://localhost:6006/
* Main Graph部分が学習過程を可視化したもの
<img src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/310068/b575d15b-0f15-a1c3-cac3-dd5ec984b1d1.png" width="800">

# まとめ
* 公式チュートリアルの内容をやっただけですが、何となく機械学習やってる系のエンジニアの気分を味わえました
* 細かい部分は全然わかっていないのでこれからちょっとずつ勉強していきます