본문 바로가기

Theory/DeepLearning

[Tensor Flow] XOR 문제를 해결하기 위해 은닉층(Hidden Layer)를 하나 추가해 보기

대부분의 딥러닝 혹은 신경망 책, 동영상 강의등을 보면 이렇게 진행해 오다가 XOR라는 단어가 나타납니다. 저도 전자회로 이후에 이렇게 AND, XOR 등의 단어를 많이 본 건 참 오랜만이네요. 처음 AND를 학습[바로가기]했던 예제는 입력 노드에 가중치가 붙고 출력 노드로 이어지는 아주 심플한 구조였습니다. 이번에는 단일 신경망으로는 풀 수 없는 유명한 문제 XOR를 은닉층 하나 추가해서 간단히 풀어내는 예제를 볼려고 합니다~~~~

오늘도 언제나 그렇듯~ 김성훈 교수님의 유명한 딥러닝과 텐서플로우 공개 강좌[바로가기], 그 외에 엣지있게 설명한 텐서플로우[바로가기], 딥러닝 첫걸음[바로가기], 처음 배우는 머신러닝[바로가기]을 정말 단순히 따라가는 수준입니다.

뭐 아무튼... 처음 AND 예제[바로가기]에서 AND를 입력하던 부분만

# XOR
x_data = np.array([[0, 0],
                  [0, 1],
                  [1, 0],
                  [1, 1]], dtype=np.float32)
y_data = np.array([[0],
                  [1],
                  [1],
                  [0]], dtype=np.float32)

위 코드로 표현되는 XOR로 바꿔서 실행해 보면... 

이런 결과가 나타납니다. Hypothesis가 모두 0.5가 되어서 사실 못 맞춘거죠.. 1 두개, 0 두개 있으니 Accuracy야 0.5가 잡혔겠지만 말이죠~

출처 : Learn to Build an App to Find Similar Images using Deep Learning- Piotr Teterwak

그것은 위의 AND나...

출처 : Learn to Build an App to Find Similar Images using Deep Learning- Piotr Teterwak

OR는 모두 하나의 선으로 분리 가능(linear separable)한데요...

출처 : Learn to Build an App to Find Similar Images using Deep Learning- Piotr Teterwak

XOR는 그렇지 않기 때문입니다. 그래서 어마어마한 역사적 사실들 - 이것도 굉장히 재미있는데요. 딥러닝의 역사를 따로 구글에서 찾아보시길 권합니다. 엄청~~~ 재미난 역사이니까요... 뭐 아무튼 이 XOR문제를 해결하는 방법은 많은 위대한 분들의 작업결과를 바로 가져오면 은닉층(Hidden Layer)을 하나 추가해 주면 됩니다. 먼저...

import tensorflow as tf
import numpy as np
from tqdm import tqdm_notebook
import matplotlib.pyplot as plt
%matplotlib inline

# XOR
x_data = np.array([[0, 0],
                  [0, 1],
                  [1, 0],
                  [1, 1]], dtype=np.float32)
y_data = np.array([[0],
                  [1],
                  [1],
                  [0]], 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)

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)

# 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.GradientDescentOptimizer(learning_rate=0.1).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)

이렇게 XOR까지 넣고 준비를 하구요. with tf.name_scope('NAME') as scope는 [바로가기]에서 이야기한 텐서보드를 사용할 때 이쁘게 보이게 그룹핑할 용도이구요. 나머지는 AND 때와 동일한 코드입니다. 이제

# Launch graph
with tf.Session() as sess:
    # tensorboard --logdir=./logs
    merged_summary = tf.summary.merge_all()
    writer = tf.summary.FileWriter("./logs/XOR/HiddenLayer")
    writer.add_graph(sess.graph)  # Show the graph
    
    # Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())

    for step in tqdm_notebook(range(10001)):
        summary, _ = sess.run([merged_summary, train], feed_dict={X: x_data, Y: y_data})
        writer.add_summary(summary, global_step=step)

    # 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)

이렇게 학습하고 결과를 보죠~

앗 ~ 잘 잡았네요^^

텐서보드로 구조를 보면 Layer1과 Layer2로 입력층에서 은닉층을 거치는 것이 보입니다. 이렇게 하면 XOR 문제도 해결을 할 수 있다는 것과... 은닉층을 추가하는 것도 텐서플로우에서는 꽤 쉽다는 것도 함께 알 수 있네용^^

반응형