TensorFlowチュートリアルMNIST(初心者向け)をTensorBoardで見える化

#TensorFlowの初心者向けチュートリアルをTensorBoardで出力
TensorFlowの初心者向けチュートリアル[MNIST For ML Beginners](https://www.tensorflow.org/get_started/mnist/beginners)をTensorBoardに出力して見える化しました。ですが、TensorBoardの見方(特にGraph以外)をほとんど理解していないのでコードと簡単な解説のみです。Deep Learningを実践していくと、非常に有用そうですが、そこまでのレベルに達していないので・・・
環境:python3.5 tensorflow1.1

######参考リンク
> - [TensorFlowをWindowsにインストール Python初心者でも簡単だった件](http://qiita.com/FukuharaYohei/items/d8f82c827e0bae70096a)
> - [【入門者向け解説】TensorFlow基本構文とコンセプト](http://qiita.com/FukuharaYohei/items/0825c3518d8596c09396)
> - [【入門者向け解説】TensorFlowチュートリアルMNIST(初心者向け)](http://qiita.com/FukuharaYohei/items/10b89275efda2a22e9c5)
> - [TensorFlow APIメモ](http://qiita.com/FukuharaYohei/items/f9bb9a0afd47be9ecef8)
> - [【TensorBoard入門】TensorFlow処理を見える化して理解を深める](http://qiita.com/FukuharaYohei/items/7ea120005f73cf882146)
> - [【TensorBoard入門:image編】TensorFlow画像処理を見える化して理解を深める](http://qiita.com/FukuharaYohei/items/fae6896e041235033454)
> - [【TensorBoard入門:Projector編】TensorFlow処理をかっこよく見える化](https://qiita.com/FukuharaYohei/items/70f702ee85e23b5b1e26)
> - [【入門者向け解説】TensorFlowチュートリアルDeep MNIST](http://qiita.com/FukuharaYohei/items/0aef74a0411273705512)
> - [TensorFlow理解のために柏木由紀さん顔特徴を調べてみた【前編】](http://qiita.com/FukuharaYohei/items/c3fb29fc8b42e0dfad0f)

#コード
書いたコードは↓です。公式サイトの[「TensorBoard: Visualizing Learning」](https://www.tensorflow.org/get_started/summaries_and_tensorboard)を参考にしています。

```py3
import tensorflow as tf
sess = tf.InteractiveSession()

# MNISTデータ読込
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets('MNIST_data', one_hot=True)

# TensorBoard情報出力ディレクトリ
log_dir = '/tmp/tensorflow/mnist/logs/mnist_beginner'

# 指定したディレクトリがあれば削除し、再作成
if tf.gfile.Exists(log_dir):
    tf.gfile.DeleteRecursively(log_dir)
tf.gfile.MakeDirs(log_dir)

# 変数を加工してTensorBoard出力する関数
def variable_summaries(var):

    # 変数Summaries
    with tf.name_scope('summaries'):
        mean = tf.reduce_mean(var)                      #Scalar出力(平均)
        tf.summary.scalar('mean', mean)
        with tf.name_scope('stddev'):
            stddev = tf.sqrt(tf.reduce_mean(tf.square(var - mean)))
        tf.summary.scalar('stddev', stddev)             #Scalar出力(標準偏差)
        tf.summary.scalar('max', tf.reduce_max(var))    #Scalar出力(最大値)
        tf.summary.scalar('min', tf.reduce_min(var))    #Scalar出力(最小値)
        tf.summary.histogram('histogram', var)          #ヒストグラム出力

# 回帰の計算
with tf.name_scope('layer'):
    with tf.name_scope('weights'):
        W = tf.Variable(tf.zeros([784,10]))
        variable_summaries(W)
    with tf.name_scope('biases'):
        b = tf.Variable(tf.zeros([10]))
        variable_summaries(b)
    with tf.name_scope('y'):
        y = tf.nn.softmax(tf.matmul(x, W) + b)
        tf.summary.histogram('y', y)

# クロスエントロピー
with tf.name_scope('cross_entropy'):
    with tf.name_scope('total'):
        cross_entropy = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(labels=y_, logits=y))
        tf.summary.scalar('cross_entropy', cross_entropy)

# 訓練
with tf.name_scope('train'):
    train_step = tf.train.GradientDescentOptimizer(0.5).minimize(cross_entropy)

# 正解
with tf.name_scope('accuracy'):
    with tf.name_scope('correct_prediction'):
        correct_prediction = tf.equal(tf.argmax(y,1),tf.argmax(y_,1))
    with tf.name_scope('accuracy'):
        accuracy = tf.reduce_mean(tf.cast(correct_prediction, tf.float32))
    tf.summary.scalar('accuracy', accuracy)

# 全Summariesを出力
merged = tf.summary.merge_all()
train_writer = tf.summary.FileWriter(log_dir + '/train', sess.graph) #訓練データ
test_writer  = tf.summary.FileWriter(log_dir + '/test')              #テストデータ

# 初期化
tf.global_variables_initializer().run()

for i in range(1000):
    batch_xs, batch_ys = mnist.train.next_batch(100)

#   10回ごとにテストし、正解率を出力    
    if i % 10 == 0:  # Record summaries and test-set accuracy
        summary, acc = sess.run([merged, accuracy], feed_dict={x: mnist.test.images, y_:mnist.test.labels})
        test_writer.add_summary(summary, i)
        print('Accuracy at step %s: %s' % (i, acc))

#   訓練
    else:  # Record train set summaries, and train

#       訓練のうち1回/100回は、詳細訓練データを出力        
        if i % 100 == 99:  # Record execution stats
            run_options  = tf.RunOptions(trace_level=tf.RunOptions.FULL_TRACE)
            run_metadata = tf.RunMetadata()
            summary, _   = sess.run([merged, train_step],
                              feed_dict={x: batch_xs, y_:batch_ys},
                              options=run_options,
                              run_metadata=run_metadata)
            train_writer.add_run_metadata(run_metadata, 'step%03d' % i)
            train_writer.add_summary(summary, i)
            print('Adding run metadata for', i)

        #通常の訓練
        else:
            summary, _ = sess.run([merged, train_step], feed_dict={x: batch_xs, y_:batch_ys})
            train_writer.add_summary(summary, i)

# Writerクローズ
train_writer.close()
test_writer.close()
```

# TensorBoard起動
その後にTensorboardを起動します。筆者の環境はAnacondaで構築しているので、まずAnaconda NavigatorからTerminalを起動しています。
![30.TensorFlow_Install01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/f9d2c32d-708c-1878-e6c7-fe6b0b74cfa7.jpeg)

で、TerminalからTensorbaordをディレクトリを指定して起動します(Pythonプログラム内変数log_dirにディレクトリを格納しています)。

```none
tensorboard --logdir=/tmp/tensorflow/mnist/logs/mnist_beginner
```

起動後にブラウザで http://localhost:6006/ を開くとTensorBoard画面が表示されます。

##Graph
Computational Graphは下図の形で出力されます。[入門記事](http://qiita.com/FukuharaYohei/items/7ea120005f73cf882146)では、シンプルな計算式だったのでグラフ化の必要性がなかったですが、このくらいの複雑さになると見やすいです。
![40.TensorBoard01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/286f8a0d-22e2-e06e-0c7b-c1f25b973eb3.jpeg)
##Scalar(折れ線グラフ)
Scalar(折れ線グラフ)で正答率(accuracy)と交差エントロピー(クロスエントロピー)のステップごとの遷移が見られます。
青線が訓練データで、オレンジ線がテストデータです。
![10.Scalar01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/13225b14-dd93-7453-b868-7193f19768da.jpeg)
同様にバイアス(切片)や重み付けの値の標準偏差等の値の遷移も出力しています。
![10.Scalar02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/f6c8f741-35af-00b4-4989-b142e218f792.jpeg)

##Distribution(分布)
バイアスのDistribution(分布)を見てみましょう。0で初期化しているので0からスタートして、学習していくにつれ、バイアスのテンソルの値が変化していることがわかります。
![20.Distribution01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/c550e779-8699-351c-0d82-c1077e9c1856.jpeg)

##Histogram(ヒストグラム)
同じくバイアスのHistogram(ヒストグラム)を見てみます。3次元の度数分布です。Distribution(分布)で見たように0からスタートして、学習していくにつれ、バイアスのテンソルの値が変化しています。
![30.Histgram01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/529635bf-0cf2-019f-74fb-9316e6da8126.jpeg)