TensorBoardのシンプルな解説

# 内容
TensorBoardの原文マニュアル
[TensorBoard: Visualizing Learning]
(https://www.tensorflow.org/get_started/summaries_and_tensorboard)
[TensorBoard: Graph Visualization]
(https://www.tensorflow.org/get_started/graph_viz)
[TensorBoard Histogram Dashboard]
(https://www.tensorflow.org/get_started/tensorboard_histograms)
をもっとシンプルな例で解説する.
目標はこれらの原文の理解に役立つような記事にすること.

この記事よりももっとシンプルなもの↓
[TensorBoardの最もシンプルなサンプル]
(https://qiita.com/yabeenico/items/b0fb24d65de988e59de2)


# 環境
```
$ cat /etc/lsb-release
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04 LTS"
$ python3 --version
Python 3.5.4
$ pip3 list|grep tensor
tensorboard (1.0.0a6)
tensorflow (1.4.0)
tensorflow-tensorboard (0.4.0rc3)
```

# サンプル
y = 2 * x のTensorFlowのグラフをTensorBoardで表示.
また，xを0から2まで変化させた時のyの変化を折れ線グラフで表示.

``` tensorboard_summary.py
import tensorflow as tf

a = tf.constant(2, name='A') # 定数a = 2を宣言
x = tf.Variable(0, name='X') # 変数xを初期値0で宣言
y = tf.multiply(a, x, name='Y') # y = a * x

x_incrementer = tf.assign(x, x + 1, name='X_INCREMENTER') # x++

sess = tf.InteractiveSession()

tf.summary.scalar('X_SCALAR', x) # xをスカラーとして記録
tf.summary.scalar('Y_SCALAR', y) # yをスカラーとして記録
merged = tf.summary.merge_all() # おまじない
if tf.gfile.Exists('./logdir'):
    tf.gfile.DeleteRecursively('./logdir') # ./logdirが存在する場合削除
writer = tf.summary.FileWriter('./logdir', sess.graph) # 保存先を./logdirに設定

tf.global_variables_initializer().run()

for i in range(3):
    summary, result = sess.run([merged, y])
    # sess.runの戻り値は第1引数(fetches)と同じ型
    # summaryにはxとyの値がスカラーとして保存される.
    # resultにはyの値が保存される.
    writer.add_summary(summary, i)
    # summaryをi番目のイテレーションとして./logdirに記録
    print(result) # 0, 2, 4
    sess.run(x_incrementer) # x++を実行
```

```
$ python3 tensorboard_summary.py
0
2
4
$ tensorboard --logdir='./logdir'
TensorBoard 0.4.0rc3 at http://localhost:6006 (Press CTRL+C to quit)

```

ブラウザで [http://localhost:6006](http://localhost:6006) にアクセスするとTensorBoardの画面が表示される.

上部のGRAPHSをクリックするとTensorFlowのグラフが表示される.
![summary_graphs.png](https://qiita-image-store.s3.amazonaws.com/0/101023/631ebc1a-6b04-7382-c3e7-f20dcb44c26a.png)

上部のSCALARSをクリックするとxとyの折れ線グラフが表示される.
Smoothingの値を0にすると意図した折れ線グラフになる.
横軸はiである.
![summary_scalars.png](https://qiita-image-store.s3.amazonaws.com/0/101023/e8e56787-1970-0381-73bd-ca6e79da93e2.png)

# SCALAR以外のsummary
tf.summary.scalar以外のsummaryも存在する.
[Module: tf.summary](https://www.tensorflow.org/api_docs/python/tf/summary)
- audio
- histogram
- image
- scalar
- text
など

# tf.name_scope
上のGRAPHSの画像の真ん中から右半分はX_INCREMENTERに関する部分のグラフとなっているが
``` x_incrementer = tf.assign(x, x + 1, name='X_INCREMENTER') # x++ ```
の
```x + 1```
の部分が内部実装のaddで展開されていて見づらい.
グラフのこの様な部分をまとめるのがtf.name_scopeである.
下記のようにx_incrementerをtf.name_scopeで囲むと

``` tensorboard_summary_name_scope.py

import tensorflow as tf

a = tf.constant(2, name='A') # 定数a = 2を宣言
x = tf.Variable(0, name='X') # 変数xを初期値0で宣言
y = tf.multiply(a, x, name='Y') # y = a * x

with tf.name_scope('NS_X_INCREMENTER'): # ここだけ追加
    x_incrementer = tf.assign(x, x + 1, name='X_INCREMENTER') # x++

sess = tf.InteractiveSession()

tf.summary.scalar('X_SCALAR', x) # xをスカラーとして記録
tf.summary.scalar('Y_SCALAR', y) # yをスカラーとして記録
merged = tf.summary.merge_all() # おまじない
if tf.gfile.Exists('./logdir'):
    tf.gfile.DeleteRecursively('./logdir') # ./logdirが存在する場合削除
writer = tf.summary.FileWriter('./logdir', sess.graph) # 保存先を./logdirに設定

tf.global_variables_initializer().run() # おまじない

for i in range(3):
    summary, result = sess.run([merged, y])
    # sess.runの戻り値は第1引数(fetches)と同じ型
    # summaryにはxとyの値がスカラーとして保存される.
    # resultにはyの値が保存される.
    writer.add_summary(summary, i)
    # summaryをi番目のイテレーションとして./logdirに記録
    print(result) # 0, 2, 4
    sess.run(x_incrementer) # x++を実行
```

グラフがすっきりして見やすくなる.
ノードの右上の+を押したりダブルクリックしたりするとノードを展開できる.
![summary_name_scope.png](https://qiita-image-store.s3.amazonaws.com/0/101023/22dbf25a-8c0c-f7d3-1574-e3acd263a095.png)