본문으로 바로가기

대부분의 딥러닝 혹은 신경망 책, 동영상 강의등을 보면 이렇게 진행해 오다가 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 문제도 해결을 할 수 있다는 것과... 은닉층을 추가하는 것도 텐서플로우에서는 꽤 쉽다는 것도 함께 알 수 있네용^^


댓글을 달아 주세요

  1. BlogIcon 공수래공수거 2018.02.19 08:25 신고

    즑웠던 설 연휴를 보내고
    한주 활기차게 시작하시기 바랍니다^^

    • BlogIcon PinkWink 2018.02.19 16:48 신고

      왠지 즑웠던 이라는 단어가 오타이시겠지만..
      전.. 즐겁지만 또한 피곤함과 뭔가 모를 공허함과 우울함이 느껴지는 뭐 그런 느낌의 단어입니다. ㅎㅎㅎ

  2. BlogIcon 휴식같은 친구 2018.02.19 15:29 신고

    exclusive OR...오랜만에 들어보네요.
    잘 보고 갑니다.
    즐거운 한 주 시작하세요.

  3. BlogIcon 『방쌤』 2018.02.19 16:06 신고

    설 연휴는 잘 보내셨나요?
    이번 주는 날씨가 많이 풀렸네요^^
    즐거운 한 주 보내세요!

  4. BlogIcon 귀요미디지 2018.02.19 17:45 신고

    즐거운 명절 보내시고 다시 일상이네요~
    앞으로의 일상도 항상 즐거운 나날되세요 ^^

  5. 2018.02.19 19:10

    비밀댓글입니다

  6. BlogIcon peterjun 2018.02.20 00:45 신고

    딥러닝 역사 한 번 찾아봐야겠습니다. ^^

  7. BlogIcon Bliss :) 2018.02.20 08:38 신고

    아....집중해서 읽으려고 했으나..집중력을 분산케 하는 제 무지함이 느껴지네요ㅎㅎㅎ 연휴의 후유증 잘 극복하시고 행복한 한 주 보내시길요^^