29. Tensor Board로 딥네트웍 들여다보기 (lab 09-2)


Tensorboard를 활용한 TensorFlow 시각화를 공부할 차례다. 어찌 된게 뭐 하나 쉬운게 없고.. 계속해서 벽에다 머리 들이박는 상상만 하고..


TensorBoard는 TensorFlow에서 발생한 로그를 표시하거나 디버깅(debugging)을 하기 위한 도구이다. 그래프를 그려서 통계를 시각화하는 것이 주요 기능이다.


예전에는 이렇게 텍스트로 출력을 해서 결과를 보았다. 여전히 그런 사람이 있다. TensorBoard를 사용하기 위해서는 분명 별도의 코드를 넣어야 하니까. 그래도 위와 같은 방식으로 100개 정도만 출력되도 데이터의 변화를 눈으로 추적하기는 어려워진다.


이제는 그래프를 사용해서 결과를 보고 잘못된 부분을 찾아야 할 때이다. 그래프로 검증하는 새로운 방법인 TensorBoard를 사용해 보자.


교수님께서 말씀하셨다. 순서대로 5가지만 하면 된다. 주석(annotate, not comment)으로 처리하고 싶은 노드를 선택하고, 한 군데로 모아서, 특정 파일에 기록한다. 즉, 로그를 예약한다. run 함수로 구동한 결과를 add_summary로 추가하고, tensorboard 명령으로 결과를 확인한다.

쉬워보일 수 있지만, 생각보다 어렵다. 아마도 tensorflow 자체에 익숙하지 않기 때문인 것 같다. 텍스트로 결과 보기도 어려운데, 어떻게 시각화까지 할 수 있겠는가? 잘 보려면 그래프가 좋지만, 쉽게 보려면 텍스트가 낫다는 사실은 바뀌지 않는다. 앞에 언급했던 "여전히 그런 사람"에 나 또한 포함된다.

Create writer 항목에서 sess.graph_def는 sess.graph로 바뀌었다. Launch Tensorboard 항목에서 /tmp/mnist_logs는 루트(/) 폴더 밑의 tmp 폴더 밑의 mnist_logs 폴더를 가리킨다.


tensorboard는 터미널(콘솔)에서 실행시킨다. 소스 코드가 있는 폴더로 이동해서 작업을 하면 더 쉽다. tmp 폴더는 리눅스나 맥에서 임시 데이터를 저장하는 폴더이다. 삭제해도 되는 데이터를 보관한다.

현재 폴더에 로그를 기록하려면 "./logs/mnist_logs"라고 한다. 현재 폴더(.) 밑의 logs 폴더 밑의 mnist_logs 폴더라는 뜻이다.

tensorboard를 실행한 후에 웹 브라우저를 열고 주소창에 "0.0.0.0:6006"이라고 입력한다. 마지막에 실행한 tensorboard 명령에 맞는 결과를 보여준다. 폴더를 잘못 지정하는 등의 오타가 있으면 결과가 표시되지 않는다. 이 부분에서 많이 실수했다. 잘못되면 문제가 발생해야 하는데, 내 생각에는 문제로 보이지 않아서 문제였다.


히스토그램을 보여주는 tensorboard. 다른 코드를 사용해서 돌려보니까, 이 모양이 나오지 않았다. 문제는 그 모양이 맞는지 틀리는지 모르는 상황. 그냥 저 그림을 봤을 때 올바르게 나왔다,라는 생각이 들까?


1개짜리 벡터인 스칼라를 추가한 그림이다. accuracy와 cost 두 가지를 보여준다. cost가 줄어드는 방식이 확실히 보인다.



여기 있는 3장의 그림은 교수님께서 따로 배포하신 코드를 실행했을 때의 모습이다. 동영상에서 사용한 코드와는 조금 다르긴 하지만, 모양은 잘 나오는 것 같다. mnist를 구현한 코드이고, 정확도는 100회 반복에 98.64% 나왔다.


import tensorflow as tf
import input_data

def init_weights(shape, name):
return tf.Variable(tf.random_normal(shape, stddev=0.01), name=name)

# This network is the same as the previous one except with an extra hidden layer + dropout
def model(X, w_h, w_h2, w_o, p_keep_input, p_keep_hidden):
# Add layer name scopes for better graph visualization
with tf.name_scope("layer1"):
X = tf.nn.dropout(X, p_keep_input)
h = tf.nn.relu(tf.matmul(X, w_h))
with tf.name_scope("layer2"):
h = tf.nn.dropout(h, p_keep_hidden)
h2 = tf.nn.relu(tf.matmul(h, w_h2))
with tf.name_scope("layer3"):
h2 = tf.nn.dropout(h2, p_keep_hidden)
return tf.matmul(h2, w_o)

mnist = input_data.read_data_sets("MNIST_data/", one_hot=True)
trX, trY, teX, teY = mnist.train.images, mnist.train.labels, mnist.test.images, mnist.test.labels

X = tf.placeholder("float", [None, 784], name="X")
Y = tf.placeholder("float", [None, 10], name="Y")

w_h = init_weights([784, 625], "w_h")
w_h2 = init_weights([625, 625], "w_h2")
w_o = init_weights([625, 10], "w_o")

# Add histogram summaries for weights
tf.histogram_summary("w_h_summ", w_h)
tf.histogram_summary("w_h2_summ", w_h2)
tf.histogram_summary("w_o_summ", w_o)

p_keep_input = tf.placeholder("float", name="p_keep_input")
p_keep_hidden = tf.placeholder("float", name="p_keep_hidden")
py_x = model(X, w_h, w_h2, w_o, p_keep_input, p_keep_hidden)

with tf.name_scope("cost"):
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(py_x, Y))
train_op = tf.train.RMSPropOptimizer(0.001, 0.9).minimize(cost)
# Add scalar summary for cost
tf.scalar_summary("cost", cost)

with tf.name_scope("accuracy"):
correct_pred = tf.equal(tf.argmax(Y, 1), tf.argmax(py_x, 1)) # Count correct predictions
acc_op = tf.reduce_mean(tf.cast(correct_pred, "float")) # Cast boolean to float to average
# Add scalar summary for accuracy
tf.scalar_summary("accuracy", acc_op)

with tf.Session() as sess:
# create a log writer. run 'tensorboard --logdir=./logs/nn_logs'
writer = tf.train.SummaryWriter("./logs/nn_logs", sess.graph) # for 0.8
merged = tf.merge_all_summaries()

# you need to initialize all variables
tf.initialize_all_variables().run()

for i in range(100):
for start, end in zip(range(0, len(trX), 128), range(128, len(trX), 128)):
sess.run(train_op, feed_dict={X: trX[start:end], Y: trY[start:end],
p_keep_input: 0.8, p_keep_hidden: 0.5})
summary, acc = sess.run([merged, acc_op], feed_dict={X: teX, Y: teY,
p_keep_input: 1.0, p_keep_hidden: 1.0})
writer.add_summary(summary, i) # Write summary
print(i, acc) # Report the accuracy

이 코드를 돌리기 위해서는 input_data.py 파일이 필요하다. 구글에서 배포한 파일로 처음 배포하신 코드에 포함되어 있다. 아니면 텐서플로우 샘플 폴더에서도 찾을 수 있다.

여기서는 tensorboard에 결과를 보여주는 것이 목표이므로, 설명은 생략한다. 이 코드에는 drop out, relu 등의 다양한 기법들을 사용하고 있기 때문에 분석하면 많은 도움이 될 것이다.