머신러닝

4-7 TensorBoard에 의한 TensorFlow 코드 NN의 내부 Graph 분석

coding art 2021. 7. 5. 16:28
728x90

아래의 과정은 윈도우즈 아나콘다가 아닌 리눅스 OS를 사용하는 라즈베리 파이 보드에서 TensorBoard 사용법임에 유의하자. 아울러 TensorBoard 데모에 사용하는 NN 코드에 관해서는 4-3절의 내용을 읽어보고 참조하도록 하자. TensorFlow 코드가 간단할수록 그라프 구조를 검토하기가 쉬워진다.

 

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)이 아닌 Adam optimizer를 사용하기로 한다. 아울러 learning rate0.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)