본문 바로가기

[프로그래밍]/모두를 위한 딥러닝

[모두를위한딥러닝] XOR 문제를 딥러닝으로 풀기

Neural Network 하나로는 XOR 문제를 해결 할 수 없다.

그렇기에 다중 Neural Network로 이것을 해결하고자 하는데

이것이 딥러닝의 시작이다.

 

기존에 머신러닝이 XOR을 해결하고자 한다면 에러가 난다. 이론상으로 해결할 수가 없기 때문이다.

X1 X2 Y
1 0 0
0 1 0

 

그렇기에 연구자들은

딥러닝 hidden Layer라는 개념을 도입한다.

 

아래와 같이 가정해보자

hidden layer  1 ==> w=[5,5] b=-8

hidden layer  2 ==> w=[-7,-7], b=3

hidden layer  3 ==> w=[-11,-11], b=6

 

그리고 X의 xor에 들어가는 인자라고 하고 결과 값을 구해보자

 

hidden layer  1 ==> W*x +b ==> 0+5-8 =-3 ==> sigmoid(-3)=0

hidden layer  2 ==> 0+-7 +3 =-4 ==> sigmoid(-4)=0

hidden layer  3 ==> 0+0+6 ==> sigmoid(6) =1

 

x1 X2 Y1(hidden layer1) Y2(hidden layer2) Y
0 0 0 1 0
0 0 0 0 1
1 0 0 0 1
1 1 1 0 0

성공적으로 xor 값을 계산한 것을 알 수 있다.

 

즉, 3개의 layer를 통해서 원하는 값을 얻을 수 있게 된다.

 

그리고 이것을 소스코드로 보면 다음과 같다.

# Lab 9 XOR
import tensorflow as tf
import numpy as np

tf.set_random_seed(777)  # for reproducibility

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])
Y = tf.placeholder(tf.float32, [None, 1])

W1 = tf.Variable(tf.random_normal([2, 10]), name='weight1')
b1 = tf.Variable(tf.random_normal([10]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_normal([10, 10]), name='weight2')
b2 = tf.Variable(tf.random_normal([10]), name='bias2')
layer2 = tf.sigmoid(tf.matmul(layer1, W2) + b2)

W3 = tf.Variable(tf.random_normal([10, 10]), name='weight3')
b3 = tf.Variable(tf.random_normal([10]), name='bias3')
layer3 = tf.sigmoid(tf.matmul(layer2, W3) + b3)

W4 = tf.Variable(tf.random_normal([10, 1]), name='weight4')
b4 = tf.Variable(tf.random_normal([1]), name='bias4')
hypothesis = tf.sigmoid(tf.matmul(layer3, W4) + b4)

# cost/loss function
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))
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))

# Launch graph
with tf.Session() as sess:
    # Initialize TensorFlow variables
    sess.run(tf.global_variables_initializer())

    for step in range(10001):
        _, cost_val = sess.run([train, cost], feed_dict={X: x_data, Y: y_data})
        if step % 100 == 0:
            print(step, cost_val)

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


'''
Hypothesis:  [[  7.80511764e-04]
 [  9.99238133e-01]
 [  9.98379230e-01]
 [  1.55659032e-03]]
Correct:  [[ 0.]
 [ 1.]
 [ 1.]
 [ 0.]]
Accuracy:  1.0
'''

 

여기서 sigmoid를 쓰는 이유는 무엇일까?

자세한 내용은 

https://m.blog.naver.com/PostView.nhn?blogId=infoefficien&logNo=221170205067&scrapedType=1&scrapedLog=221623016275&scrapedOpenType=2

 

Softmax vs Sigmoid

logistic regression 개념을 학습하는 동안, 혼란스러운 개념은 확률 계산에 사용되는 함수에있을 것입니다...

blog.naver.com

이 블로그를 참조해주면 좋겠다. 정리하자면, sigmoid는 0과 1의 데이터를 구분 짖는 binary classification 문제에서 사용되며, softmax는 y값이 n 개인 multi-classification에서 사용된다.

 

즉, 아래와 같이 0과 1로만 출력값을 내놓아야하는 binary classification에선 sigmoid를

y= [[0],[1],[0],[1]]

 

엘리먼트가 n 개인 경우에선 softmax를 사용한다.

y=[[0,0,0,1],[0,1,0,0],[0,0,1,0]]

 

아무튼, 그리고 wide와 deep의 차이는 다음과 같다.

 

wide하다라는 것은 sigmoid로 연산되는 출력 값들이 많아짐을 의미하고

W1 = tf.Variable(tf.random_normal([2, 10]), name='weight1')
b1 = tf.Variable(tf.random_normal([10]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_normal([10, 1]), name='weight2')
b2 = tf.Variable(tf.random_normal([1]), name='bias2')
layer2 = tf.sigmoid(tf.matmul(layer1, W2) + b2)

deep 하다라는 것은 아래와 같이 layer가 많은 것을 의미한다.

W1 = tf.Variable(tf.random_normal([2, 10]), name='weight1')
b1 = tf.Variable(tf.random_normal([10]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)

W2 = tf.Variable(tf.random_normal([10, 10]), name='weight2')
b2 = tf.Variable(tf.random_normal([10]), name='bias2')
layer2 = tf.sigmoid(tf.matmul(layer1, W2) + b2)

W3 = tf.Variable(tf.random_normal([10, 10]), name='weight3')
b3 = tf.Variable(tf.random_normal([10]), name='bias3')
layer3 = tf.sigmoid(tf.matmul(layer2, W3) + b3)

W4 = tf.Variable(tf.random_normal([10, 1]), name='weight4')
b4 = tf.Variable(tf.random_normal([1]), name='bias4')

그럼 무엇이 좀더 연산에 정확할까? 

굳이 따지면 layer가 많은게 좀더 정확하다 하지만,

그만큼 연산에 오래걸린다!