のんびりしているエンジニアの日記

ソフトウェアなどのエンジニア的な何かを書きます。

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

Sponsored Links

本日はTensorFlowの可視化機能を使ってみる。

皆さんこんにちは
お元気ですか。私は元気です。

今日はTensorFlowの可視化機能を使ってみました。
TensorFlowって何ぞ?といった方はこちらの記事を御覧ください。

nonbiri-tereka.hatenablog.com

まずは、可視化用のソースコードを準備しました。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

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

STEP:回数
RELATIVE:?
WALL:時間推移

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

GRAPH

f:id:tereka:20151114090906p:plain

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

f:id:tereka:20151114232301p:plain

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

  1. weightsとMatMulを行う。
  2. 上記のに、biasを足す。
  3. sigmoidの計算をする。

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

感想

計算とデータの流れを一目見てわかるのが凄い。応用すればたいていのことはできます。
誤差の経過を見せる仕組みはこれまでなかったと思う。(時間もあるのがよい)