2017年1月26日木曜日

TensorFlowの可視化機能を使ってみる

まずは、可視化用のソースコードを準備しました。Tutrialで用いられているソースコードを少々いじり、
扱いやすいコードにしました。
https://tensorflow.googlesource.com/tensorflow/+/master/tensorflow/g3doc/tutorials/mnist/fully_connected_feed.py

可視化用ソースコード

import tensorflow as tf
import time
import input_data
import math
 
BATCH_SIZE = 150
LOGDIR = '/tmp/mnist_data_log'
 
def placeholder_inputs(batch_size):
         input_placeholder = tf.placeholder(tf.float32, shape=[BATCH_SIZE,784])
         label_placeholder = tf.placeholder(tf.float32,shape=[BATCH_SIZE,10])
 
         return input_placeholder,label_placeholder
 
def fill_feed_dict(data_set, images_pl, labels_pl):
         images_feed, labels_feed = data_set.next_batch(BATCH_SIZE)
         feed_dict = {
         images_pl: images_feed,
         labels_pl: labels_feed
         }
         return feed_dict
 
def loss_function(y_,y):
         return -tf.reduce_sum(y_*tf.log(y))
 
def full_connect_model(images):
         # hidden1
         with tf.name_scope("hidden_layer1") as scope:
                 weights = tf.Variable(tf.truncated_normal([784, 500],
                            stddev=1.0 / math.sqrt(float(784))),name='weights')
                 biases = tf.Variable(tf.zeros([500]),name='biases')
 
                 hidden1 = tf.nn.sigmoid(tf.matmul(images, weights) + biases)
         # hidden2
         with tf.name_scope("hidden_layer2") as scope:
                 weights = tf.Variable(tf.truncated_normal([500, 300],
                            stddev=1.0 / math.sqrt(float(500))),name='weights')
                 biases = tf.Variable(tf.zeros([300]),name='biases')
 
                 hidden2 = tf.nn.sigmoid(tf.matmul(hidden1, weights) + biases)
         # softmax layer
         with tf.name_scope("softmax_layer") as scope:
                 weights = tf.Variable(tf.truncated_normal([300, 10],
                            stddev=1.0 / math.sqrt(float(300))),name='weights')
                 biases = tf.Variable(tf.zeros([10]),name='biases')
 
                 logits = tf.nn.softmax((tf.matmul(hidden2, weights) + biases))
         return logits
 
def training(loss):
         tf.scalar_summary(loss.op.name, loss)
 
         optimizer = tf.train.GradientDescentOptimizer(0.01)
         #global_step = tf.Variable(0, name='global_step', trainable=False)
         train_op = optimizer.minimize(loss)
 
         return train_op
 
def run_training():
         data_sets = input_data.read_data_sets('MNIST_data',one_hot=True)
 
         with tf.Graph().as_default():
                 images_placeholder, labels_placeholder = placeholder_inputs(BATCH_SIZE)
                 logits = full_connect_model(images_placeholder)
 
                 loss = loss_function(labels_placeholder,logits)
 
                 sess = tf.Session()
                 train_step = training(loss)
 
                  # get the summary data.
                 summary_op = tf.merge_all_summaries()
 
                 sess.run(tf.initialize_all_variables())
 
                 summary_writer = tf.train.SummaryWriter(LOGDIR,
                                                             graph_def=sess.graph_def)
                  for step in xrange(20000):
                          start_time = time.time()
                          feed_dict = fill_feed_dict(data_sets.train,
                                                           images_placeholder,
                                                           labels_placeholder)
                          duration = time.time() - start_time
 
                          _, loss_value = sess.run([train_step, loss],
                                                         feed_dict=feed_dict)
 
                          duration = time.time() - start_time
 
                          if step % 100 == 0:
                                   print('Step %d: loss = %.2f (%.3f sec)' % (step, loss_value, duration))
                                   # Update the events file.
                                   summary_str = sess.run(summary_op, feed_dict=feed_dict)
                                   summary_writer.add_summary(summary_str, step)
 
if __name__ == '__main__':
         run_training()

ソースコード解説

前回と似ている箇所はすっ飛ばし(前回の記事を御覧ください)、今回の必要な部分について解説します。

グラフの定義です。

§  with tf.Graph().as_default():の内部にモデルを記述し、セッションにinputすることによりグラフのデータを保存することができます。

§  full_connect_modelで構築するモデルの中でname_scopeを使用しています。これはGRAPHで表示するのに使用します。

§  tf.merge_all_summaries()にて、単一のオペレーションを合体し、サマリデータを取得するのだそうです。

§  SummaryWriterを使って、情報をディレクトリに書き留めています。この宣言時に現在のグラフを記録しています。

§  100stepごとに、結果を記録する作業を行っています。

可視化

さて、上記の内容を可視化する場合にはTensorBoardと呼ばれる可視化機能を
使うことができます。
実際に使ってみましょう。いくらか方法があるそうです。以下は、https://github.com/tensorflow/tensorflow/tree/master/tensorflow/tensorboard:title:公式より抜粋。

python tensorflow/tensorboard/tensorboard.py --logdir=path/to/logs
# if installed via pip
tensorboard --logdir=path/to/logs
 
# if building from source
bazel build tensorflow/tensorboard:tensorboard
./bazel-bin/tensorflow/tensorboard/tensorboard --logdir=path/to/logs

私はPyEnvを使っているせいなのかわからず、うまくいきませんでした。find
検索をかけて探してそのコマンドを使っています。
今回の方法では2つの機能を扱えます。一つは、EVENT機能、もうひとつはGRAPH機能です

EVENT


時系列ごとのイベントの表示も可能です。実際にこのイベントの解析をするのにはよいでしょうか
x
軸を変更することができます。STEPRELATIVEWALLです。yは誤差ですね。

STEP:回数
RELATIVE:

WALL:
時間推移

学習時間どれくらいかかるのか、何回のステップで計算は十分だったのかのようなことを知ることができるでしょう。
Validation
EVENTも同時に記述できると、便利ですね。(多分できると思いますが・・)

GRAPH

自分が作成したネットワーク構造を可視化することができます。
ニューラルネットワークの層に名前をつけましたが、その名前の表示もされています。
中を展開することができます。試しに隠れ層(hidden_layer1)を展開してみました。

この中を見ると、計算のフローが書いてあります。
hidden_layer1
の中のforward部分を解読すると次のように計算していることが見て取れると思います。

1.    weightsMatMulを行う。

2.    上記のに、biasを足す。

3.    sigmoidの計算をする。

これを見ると全体がどんな感じで流れているのか、その内部で何を計算しているのかをひと目で確認することができます。

 

0 件のコメント:

コメントを投稿