아래의 과정은 윈도우즈 아나콘다가 아닌 리눅스 OS를 사용하는 라즈베리 파이 보드에서 TensorBoard 사용법임에 유의하자. 아울러 TensorBoard 데모에 사용하는 NN 코드에 관해서는 최근에 포스팅한 블로그 내용을 읽어보고 참조하도록 하자.
4-3 XOR 로직 신경망 모델링, Backpropagation 계산, Hypothesis 3D Graphic Visualization
https://steemit.com/kr/@codingart/4-3-xor-backpropagation-hypothesis-3d-graphic-visualization
이 TensorBoard 기법을 몰라도 머신 러닝을 배우는데 큰 지장은 없다고 생각하지만 어느정도 머신 러닝 학습이 되어 XOR 문제에 대한 NN을 다루게 되면 한번쯤 다루어 보아 그 내막을 알게 되면 당신의 머신 러닝 학습에 탄력이 붙어 가속이 될 수 있을지도 모르겠다.
TensorFlow 코드에서 특정 파라메터 값들을 추적하기 위해서 sess.run() 명령을 사용하여 계산 결과를 일일이 프린팅 출력했으나 TensorFlow에서 지원하는 TensorBoard에 의해 효율적으로 모니터링 해 보자. TF 코드 내부의 Computational Graph는 연산단위인 노드(Node)들과 이들의 흐름을 연결하는 선(edge)들로 구성되어 일반 그래프처럼 시각적으로 보여준다. 이는 전기회로에서 배선에 따라 전류가 흐르듯 코드의 배선도로 보면 될 것이다.
TensorFlow 코드에서 TensorBoard를 사용하기 위한 5단계 스텝을 알아보자.
XOR 논리 처리를 위한 신경망 계산 예제를 TensorBoard로 체크해 보자.
입력 데이터 x_data와 출력 데이터 y_data 가 리스트 형태로 주어지며 이들을 numpy array 형태로 두고 session에서 참고할 수 있도록 각각 placeholder X, Y 로 선언한다.
TensorBoard에서 단위별로 알기 쉽게 Graph 구조를 볼 수 있도록 tf.name.scope() 명령을 사용하여 “layer1”으로 정의하자. 마찬가지로 그 다음 레이어도 name.scope 명령을 사용해“layer2”로 명칭을 부여해 둔다. 아울러 cost 함수와 train 단계도 각각 namescope 로 정의한다. 참고로 현재 분석하는 코드에서는 최소제곱법을 쓰지 않기 때문에 경사하강법(GradDecent)이 아닌 Adamsoptimizer를 사용하기로 한다.
아울러 learning rate는 0.01을 사용하도록 하여 학습을 시키도록 하며, 학습 횟수 epoch 는 10000회로 설정한다.
마지막 단계에서 summary.merge_all() 명령을 실행하여 TensorBoard 에서 사용할 정보를 모은 후 결과를 저장할 디렉토리 경로를 ./logs/xor_logs_r0_01로 설정한다.
./logs/는 리눅스 OS를 사용하는 라즈베리 파이 상의 디렉토리 경로를 뜻하며 실제로는 터미날 창에서 tensorboard 명령을 실행함에 있어 정확한 경로를 지정해야 한다.
파이선 코드를 실행한 후에 터미널 창에서 디렉토리 경로를 cd /home/pi/⚫⚫⚫/logs/xor _logs_r0_01로 변경한 후에 다음의 tensorboard 명령을 실행한다.
Starting TensorBoard ⚫⚫⚫
(You can navigate to http://127.0.1.1:6006) 이 출력되면 인터넷을 열고 해당 request 주소를 입력하고 enter 처리하면 TensorBoard 화면이 나타난다. 여기에서 빨간 색 박스 친 부분을 확인 할 필요가 있다.
cost를 클릭하면 epoch에서 설정한 10000회에 걸친 cost 함수 값의 변화를 볼 수 있다. 이 기능은 learning rate α 값 설정과 관련하여 대단히 중요한 역할을 한다. 마찬가지로 스칼라로 설정했던 accuracy 도 비즁얼 하게 관찰이 가능하다.
그밖에도 sess.graph도 추가하여 코드의 세밀한 GRAPH 구조를 살펴보기로 한다.
코드의 GRAPH 정보는 TensorBoard에서 GRAPHS 버튼을 클릭하여 나타나는 정보를 살펴보기로 하자.
name.scope에서 선언한대로 “layer1” 이 나타났으며 “layer2” 로 연결이 되고 있다.
빨간 박스친 layer1을 클릭하면 다음과 같이 layer1 의 Graph 구조를 볼 수 있다.
웨이트 값과 바이아스 초기 값은 균일 분포 난수(random_normal())에 의해 생성된다.
cost 와 train 도 세부적으로 Graph 구조를 볼 수 있다. 다음은 Adam 의 train 세부 Graph 인데 내부에 경사하강법이 들어 있음을 알 수 있다.
첨부된 파이선 코드를 다운로딩 후 명령이 끝나는 부분에 콜론 “:” 다음에 그 다음 줄을 당겨 붙인 후 다시 엔터 작업을 하면 정확한 indentation 위치를 파악할 수 있다. indentation을 정확히 복구하여 실행해 보도록 하자.
#xor_tensorboard.py
import tensorflow as tf
import numpy as np
tf.set_random_seed(777) # for reproducibility
learning_rate = 0.01
x_data = [[0, 0],[0, 1],[1, 0],[1, 1]]
y_data = [[0],[1],[1],[0]]
x_data = np.array(x_data, dtype=np.float32)
y_data = np.array(y_data, dtype=np.float32)
X = tf.placeholder(tf.float32, [None, 2], name='x-input')
Y = tf.placeholder(tf.float32, [None, 1], name='y-input')
with tf.name_scope("layer1") as scope:
W1 = tf.Variable(tf.random_normal([2, 2]), name='weight1')
b1 = tf.Variable(tf.random_normal([2]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)
w1_hist = tf.summary.histogram("weights1", W1)
b1_hist = tf.summary.histogram("biases1", b1)
layer1_hist = tf.summary.histogram("layer1", layer1)
with tf.name_scope("layer2") as scope:
W2 = tf.Variable(tf.random_normal([2, 1]), name='weight2')
b2 = tf.Variable(tf.random_normal([1]), name='bias2')
hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)
w2_hist = tf.summary.histogram("weights2", W2)
b2_hist = tf.summary.histogram("biases2", b2)
hypothesis_hist = tf.summary.histogram("hypothesis", hypothesis)
#cost/loss function
with tf.name_scope("cost") as scope:
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) *
tf.log(1 - hypothesis))
cost_summ = tf.summary.scalar("cost", cost)
with tf.name_scope("train") as scope:
train = tf.train.AdamOptimizer(learning_rate=learning_rate).minimize(cost)
#Accuracy computation
#True if hypothesis>0.5 else False
predicted = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicted, Y), dtype=tf.float32))
accuracy_summ = tf.summary.scalar("accuracy", accuracy)
#Launch graph
with tf.Session() as sess:
# tensorboard --logdir=./logs/xor_logs
merged_summary = tf.summary.merge_all()
writer = tf.summary.FileWriter("./logs/xor_logs_r0_01")
writer.add_graph(sess.graph) # Show the graph
# Initialize TensorFlow variables
sess.run(tf.global_variables_initializer())
for step in range(10001):
summary, _ = sess.run([merged_summary, train], feed_dict={X: x_data, Y: y_data})
writer.add_summary(summary, global_step=step)
if step % 100 == 0:
print(step, sess.run(cost, feed_dict={
X: x_data, Y: y_data}), sess.run([W1, W2]))
#Accuracy report
h, c, a = sess.run([hypothesis, predicted, accuracy],
feed_dict={X: x_data, Y: y_data})
print("\nHypothesis: ", h, "\nCorrect: ", c, "\nAccuracy: ", a)