【TensorBoard入門】TensorFlow処理を見える化して理解を深める

#TensorBoardでTensorFlowの理解を早める
文系卒で**Deep LearningどころかPythonも初めて**だと、TensorFlowを理解するのが遅くてなかなか苦しいです。少しでも**理解を早めるために**もTensorBoardを学習しました。複雑なディープラーニングの理解促進はもちろん、デバッグや処理最適化・再設計などいろんなことに使えます。いろいろな見える化ができるのですが、**当記事は入門者に向けたGraph出力方法に絞って**解説します(もっと広く深くできればいいのですが、そこまで筆者の理解が追いついていません:sweat:)。
[公式ガイド「TensorBoard: Visualizing Learning」](https://www.tensorflow.org/get_started/summaries_and_tensorboard)がわかりにくかったので、かなり簡素化しています。
[TensorBoardで処理を可視化する](http://www.mwsoft.jp/programming/tensor/tutorial_tensorboad.html)のサイトが素晴らしく、かなり参考にさせて頂きました。
環境:python3.5 tensorflow1.1とtensorflow1.21の両方で確認済

######参考リンク
> - [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チュートリアルMNIST(初心者向け)をTensorBoardで見える化]
(http://qiita.com/FukuharaYohei/items/2834cc054a8b8884e150)
> - [【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 APIメモ](http://qiita.com/FukuharaYohei/items/f9bb9a0afd47be9ecef8)
> - [TensorFlow理解のために柏木由紀さん顔特徴を調べてみた【前編】](http://qiita.com/FukuharaYohei/items/c3fb29fc8b42e0dfad0f)


#TensorBoard(Graph)の簡単なロジック
##  1+2 の式をGraphで見える化
こんな感じで定数の1+2を計算して、見える化します。正直、非常に簡単です。

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

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

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

# 定数で1 + 2
x = tf.constant(1, name='x')
y = tf.constant(2, name='y')
z = x + y

# このコマンドでzをグラフ上に出力
_ = tf.summary.scalar('z', z)

# SummaryWriterでグラフを書く(これより後のコマンドはグラフに出力されない)
summary_writer = tf.summary.FileWriter(log_dir , sess.graph)

# 実行
print(sess.run(z))

# SummaryWriterクローズ
summary_writer.close()
```

その後に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/simple01
```

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

![TensorBoardBasic00.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/ce162beb-3bed-6cd5-6f98-35cc94fc43f3.jpeg)

「No scalar data was found(データがないぞ)」と怒られますが、今回はscalarは出力しておらず、Graph出力のみとしているので問題ありません。画面上にあるメニューで「Graphs」を選ぶことで下図のGraphが出力されます。ここで1+2の計算式を見ることができました。

![TensorBoardBasic01.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/c623863c-6140-7b81-e40f-194458641d87.jpeg)

## [tf.name_scope](https://www.tensorflow.org/api_docs/python/tf/name_scope)を使ってグルーピング
先程のソースコードにtf.name_scopeを加えるとグルーピングができます。

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

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

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

# add_scopeという名称でグルーピング
with tf.name_scope('add_scope'):
    
    # 定数で1 + 2
    x = tf.constant(1, name='x')
    y = tf.constant(2, name='y')
    z = x + y
    
    # このコマンドでzをグラフ上に出力
    _ = tf.summary.scalar('z', z)


# SummaryWriterでグラフを書く(これより後のコマンドはグラフに出力されない)
summary_writer = tf.summary.FileWriter(log_dir , sess.graph)

# 実行
print(sess.run(z))

# SummaryWriterクローズ
summary_writer.close()
```

結果
add_scopeという名称でグループ化(枠)ができています。計算が複雑な場合に、グループ化できないと見にく過ぎて厳しいです。
> ![TensorBoardBasic02.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/65c81cf1-487a-365d-0738-622944dec225.jpeg)

##式の階層化
先程のソースコードにtf.name_scopeをさらに入れ子で追加して複数式の階層化をします。

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

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

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

#add_scopeという名称でグルーピング
with tf.name_scope('add_scope'):

    # 定数で1 + 2
    x = tf.constant(1, name='x')
    y = tf.constant(2, name='y')
    z = x + y
    
    # このコマンドでzをグラフ上に出力
    _ = tf.summary.scalar('z', z)
    
    # 上の結果に掛け算
    with tf.name_scope('multiply_scope'):
        zz = y * z

# SummaryWriterでグラフを書く(これより後のコマンドはグラフに出力されない)
summary_writer = tf.summary.FileWriter(log_dir , sess.graph)

# 実行
print(sess.run(z))

# SummaryWriterクローズ
summary_writer.close()
```

結果
階層化してすっきりしました。
> ![TensorBoardBasic03.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/9513ee95-2e9a-9cd3-c1a9-668d78ba8bbf.jpeg)

参考
ちなみに階層化ではなく、同列にするとこんな形で出力されます。
> ![TensorBoardBasic04.JPG](https://qiita-image-store.s3.amazonaws.com/0/134273/81e68406-b94b-b7f8-ccd0-3d22d7af3954.jpeg)