[TensorFlow] IRISを３行の変更でTensorBoardに対応させる

# はじめに
TensorFlowのサンプルプログラムIRISを３行変更してTensorBoard対応してみました。

### 目次

+ TensorFlowのインストール
+ サンプルプログラム（IRIS）にTensorBoard用コードを３行追加
+ TensorBoardの実行

# TensorFlowのインストール
AWS EC2 のUbuntu 14.04に TensorFlowをインストールしました。

### AWS EC2
Ubuntu Server 14.04 LTS (HVM), SSD Volume Type
### Anaconda
※ AnacondaにはIRISを実行するのに必要なsklearnが含まれています。

・ダウンロード
> $ curl https://repo.continuum.io/archive/Anaconda3-4.2.0-Linux-x86_64.sh -o Anaconda3-4.2.0-Linux-x86_64.sh

・インストール
> $ bash Anaconda3-4.2.0-Linux-x86_64.sh

・PATHの反映
> $ source ~/.bashrc

### Tensorflow
・インストール
> $ conda install -c conda-forge tensorflow

・動作確認
> $ python -m tensorflow.models.image.mnist.convolutional --self_test

・インストールディレクトリの確認
> $ python -c 'import os; import inspect; import tensorflow; print(os.path.dirname(inspect.getfile(tensorflow)))'
> /home/ubuntu/anaconda3/lib/python3.5/site-packages/tensorflow

# サンプルプログラム（IRIS）にTensorBoard用コードを追加
プログラムが簡単なIRIS（[リンク](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/learn/iris.py)）を使ってTensorBord用のコードを追加します。

まず、iris.pyを[ダウンロード](https://github.com/tensorflow/tensorflow/blob/master/tensorflow/examples/learn/iris.py)して実行させてみます。

```
$ python iris.py
WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.
WARNING:tensorflow:Change warning: default value of `enable_centered_bias` will change after 2016-10-09. It will be disabled by default.Instructions for keeping existing behaviour:
Explicitly set `enable_centered_bias` to 'True' if you want to keep existing behaviour.
WARNING:tensorflow:Using default config.
WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.
WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.
Accuracy: 0.966667
```

多少、WARNINGがでますが、最後に「Accuracy: 0.966667」が表示されます。
続いて、TensorBord用に主に３か所のコードを追加します。

### **(1) モニターを定義**
10ステップごとにモニターすることにします。

```
    validation_monitor = tf.contrib.learn.monitors.ValidationMonitor(
                             iris.data,
                             iris.target,
                             every_n_steps=10)
```

### **(2) モデルのパス、保存間隔を指定**
model_dir と config のパラメータを追加します。

```
    classifier = tf.contrib.learn.DNNClassifier(
                         feature_columns=feature_columns,
                         hidden_units=[10, 20, 10],
                         n_classes=3,
                         model_dir="tmp/iris_model",
                         config=tf.contrib.learn.RunConfig(
                             save_checkpoints_secs=1))
```

### **(3) 学習をモニタする指定**
monitors のパラメータを追加します。
グラフとしての見栄えをよくするために、200ステップだったところを501ステップに増やしてあげます。

```
    classifier.fit(x_train, y_train,
                   steps=501,
                   monitors=[validation_monitor])
```

実行してみます。

> $ python iris_tensor_board.py

元々でていたWARNINGに追加で下記のWARNINGが出ますが、最後に「Accuracy」が表示されます。

```
WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.
WARNING:tensorflow:Given features: Tensor("input:0", shape=(?, 4), dtype=float64), required signatures: TensorSignature(dtype=tf.float64, shape=TensorShape([Dimension(None), Dimension(4)]), is_sparse=False).
WARNING:tensorflow:Given targets: Tensor("output:0", shape=(?,), dtype=int64), required signatures: TensorSignature(dtype=tf.int64, shape=TensorShape([Dimension(None)]), is_sparse=False).
WARNING:tensorflow:float64 is not supported by many models, consider casting to float32.
Accuracy: 0.966667
```

モデル出力ディレクトリを確認してみると、チェックポイントごとにデータが出力されています。

```
$ ls tmp/iris_model/
checkpoint                                       model.ckpt-441.meta            model.ckpt-491-00000-of-00001
eval                                             model.ckpt-463-00000-of-00001  model.ckpt-491.meta
events.out.tfevents.1477847211.ip-172-31-18-181  model.ckpt-463.meta            model.ckpt-501-00000-of-00001
graph.pbtxt                                      model.ckpt-484-00000-of-00001  model.ckpt-501.meta
model.ckpt-441-00000-of-00001                    model.ckpt-484.meta
```

# TensorBoardの実行
モデル出力ディレクトリを指定してTensorBoardを実行させてみます。
最初、ひとしきり、リソースが見つからずにエラーが発生しますが、その後、200でOKな状態になります。

```
$ tensorboard --logdir=tmp/iris_model/
Starting TensorBoard b'29' on port 6006
(You can navigate to http://172.31.18.181:6006)
WARNING:tensorflow:Found more than one graph event per run. Overwriting the graph with the newest event.
122.135.65.50 - - [30/Oct/2016 15:12:37] "GET / HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:12:37] "GET /lib/css/global.css HTTP/1.1" 200 -
WARNING:tensorflow:IOError [Errno 2] No such file or directory: '/home/ubuntu/anaconda3/lib/python3.5/site-packages/tensorflow/tensorboard/webcomponentsjs/webcomponents-lite.min.js' on path /home/ubuntu/anaconda3/lib/python3.5/site-packages/tensorflow/tensorboard/webcomponentsjs/webcomponents-lite.min.js
122.135.65.50 - - [30/Oct/2016 15:12:37] "GET /webcomponentsjs/webcomponents-lite.min.js HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:12:37] "GET /dist/tf-tensorboard.html HTTP/1.1" 200 -
WARNING:tensorflow:IOError [Errno 2] No such file or directory: '/home/ubuntu/anaconda3/lib/python3.5/site-packages/tensorflow/tensorboard/dist/bazel-html-imports.html' on path /home/ubuntu/anaconda3/lib/python3.5/site-packages/tensorflow/tensorboard/dist/bazel-html-imports.html
WARNING:tensorflow:IOError [Errno 2] No such file or directory: '/home/ubuntu/anaconda3/lib/python3.5/site-packages/external/dist/bazel-html-imports.html' on path /home/ubuntu/anaconda3/lib/python3.5/site-packages/external/dist/bazel-html-imports.html
122.135.65.50 - - [30/Oct/2016 15:12:37] code 404, message Not Found

．．．

122.135.65.50 - - [30/Oct/2016 15:16:09] "GET /data/runs HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:16:10] "GET /data/runs HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:16:19] "GET /data/scalars?run=eval&tag=accuracy HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:16:25] "GET /data/scalars?run=eval&tag=loss HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:16:25] "GET /data/scalars?run=.&tag=loss HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:29] "GET /data/scalars?run=.&tag=centered_bias%200 HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:33] "GET /data/scalars?run=.&tag=centered_bias%201 HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:36] "GET /data/scalars?run=.&tag=centered_bias%202 HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:39] "GET /data/scalars?run=.&tag=dnn%2Fhiddenlayer_0%3Afraction_of_zero_values HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:39] "GET /data/scalars?run=.&tag=dnn%2Fhiddenlayer_1%3Afraction_of_zero_values HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:39] "GET /data/scalars?run=.&tag=dnn%2Fhiddenlayer_2%3Afraction_of_zero_values HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:39] "GET /data/scalars?run=.&tag=dnn%2Flogits%3Afraction_of_zero_values HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:47] "GET /data/scalars?run=.&tag=global_step%2Fsec HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:55] "GET /data/scalars?run=.&tag=loss HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:17:55] "GET /data/scalars?run=eval&tag=loss HTTP/1.1" 200 -
122.135.65.50 - - [30/Oct/2016 15:18:10] "GET /data/runs HTTP/1.1" 200 -
```

200でOKな状態になってから、ブラウザで6006ポートにアクセスします。
無事に表示されました。

![tensorboard1.png](https://qiita-image-store.s3.amazonaws.com/0/107056/b01b1665-ae1d-9b64-b083-1420faeba648.png)

![tensorboard2.png](https://qiita-image-store.s3.amazonaws.com/0/107056/e47bb31f-d8d1-c784-4b8c-7c2930a96c14.png)

# プログラム
プログラム全体はこのようになっています。

```iris_tensor_board.py
#  Copyright 2016 The TensorFlow Authors. All Rights Reserved.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#   http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

"""Example of DNNClassifier for Iris plant dataset."""

from __future__ import absolute_import
from __future__ import division
from __future__ import print_function
from sklearn import cross_validation
from sklearn import metrics
import tensorflow as tf
from tensorflow.contrib import learn


def main(unused_argv):
    # Load dataset.
    iris = learn.datasets.load_dataset('iris')
    x_train, x_test, y_train, y_test = cross_validation.train_test_split(
        iris.data, iris.target, test_size=0.2, random_state=42)

    validation_monitor = tf.contrib.learn.monitors.ValidationMonitor(
                             iris.data,
                             iris.target,
                             every_n_steps=10)

    # Build 3 layer DNN with 10, 20, 10 units respectively.
    feature_columns = learn.infer_real_valued_columns_from_input(x_train)
    classifier = tf.contrib.learn.DNNClassifier(
                         feature_columns=feature_columns,
                         hidden_units=[10, 20, 10],
                         n_classes=3,
                         model_dir="tmp/iris_model",
                         config=tf.contrib.learn.RunConfig(
                             save_checkpoints_secs=1))

    # Fit and predict.
    classifier.fit(x_train, y_train,
                   steps=501,
                   monitors=[validation_monitor])

    predictions = list(classifier.predict(x_test, as_iterable=True))
    score = metrics.accuracy_score(y_test, predictions)
    print('Accuracy: {0:f}'.format(score))


if __name__ == '__main__':
    tf.app.run()
```

# tf.contrib.learn.monitors.ValidationMonitorクラス
Ｎステップごとに与えた推定量を評価します。
評価は保存されたチェックポイントに対して行われます。通常、チェックポイントは、現在のステップよりも古いです。
`early_stopping_rounds` を指定すると検証を早目に停止させることができます。

|パラメータ|デフォルト|意味  |
|:--      |:--      |:--   |
|x|None|─|
|y|None|─|
|input_fn|None|─|
|batch_size|None|─|
|eval_steps|None|─|
|every_n_steps|100|nステップごとにチェックします|
|metrics|None|─|
|early_stopping_rounds|None|数ステップにわたって変化が小さければ停止させるための値|
|early_stopping_metric|'loss'|停止メトリクスの名前|
|early_stopping_metric_minimize|True|True：メトリクスは減っていって停止（例：平均事情誤差）、False：メトリクスは増えていって停止（例：正解率）|
|name|None|─|

# tf.contrib.learn.DNNClassifierクラス
|パラメータ|デフォルト|意味|
|:--|:--|:--|:--|
|hidden_units||隠れ層|
|feature_columns||特徴カラム|
|model_dir|None|モデルパラメータ、グラフを保存するディレクトリ|
|n_classes|2|ターゲットクラス数|
|weight_column_name|None|重み、カラム名|
|optimizer|None|最適化．Noneの場合はAdagard．|
|activation_fn|relu|活性関数|
|dropout|None|ドロップアウト|
|gradient_clip_norm|None|float > 0 : 勾配のノルムが閾値以下になるように補正|
|enable_centered_bias|None|True:各クラスの中心閾値を学習|
|config|None|RunConfig:実行用の設定値|

# tf.contrib.learn.RunConfigクラス
|パラメータ|デフォルト|隠れ層|
|:--|:--|:--|
|master|None(local)|TensorFlowマスター|
|task|None(0)|訓練実行中のレプリカ数|
|num_ps_replicas|None(0)|パラメータサーバタスク数|
|num_cores|0|使用するコア数．０の場合は自動判定．|
|log_device_placement|False|ログデバイスを配置|
|gpu_memory_fraction|1|GPUメモリの配分|
|cluster_spec|None|ClusterSpec クラスター仕様|
|tf_random_seed|None|初期化用の乱数シード|
|save_summary_steps|100|サマリーをセーブするステップ間隔|
|save_checkpoints_secs|600|チェックポイントをセーブする時間間隔（秒）|
|keep_checkpoint_max|5|チェックポイントファイルを保持する最大数．None, 0を指定した場合はすべて保存|
|keep_checkpoint_every_n_hours|10000|チェックポイントを保持する最大時間|
|job_name|None|ジョブ名|
|is_chief|None|チーフタスクかどうか|
|evaluation_master|''|評価マスター|