XOR 문제

두 개의 인풋에 대해 1개의 결과값이 나오는 문제이므로 텐서플로우로 구현해보자.

결과값이 0 또는 1이므로, logistic regression으로 만들 수 있다.

# 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])
 
W = tf.Variable(tf.random_normal([2, 1]), name="weight")
b = tf.Variable(tf.random_normal([1]), name="bias")
 
# Hypothesis using sigmoid: tf.div(1., 1. + tf.exp(tf.matmul(X, W)))
hypothesis = tf.sigmoid(tf.matmul(X, W) + b)
 
# 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, w_val = sess.run(
                  [train, cost, W], feed_dict={X: x_data, Y: y_data}
        )
        if step % 100 == 0:
            print(step, cost_val, w_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:  [[ 0.5]
 [ 0.5]
 [ 0.5]
 [ 0.5]]
Correct:  [[ 0.]
 [ 0.]
 [ 0.]
 [ 0.]]
Accuracy:  0.5
'''

응? 그런데 왜 잘 안되지..?

정확도가 50%면 틀린 결과라는 것도 같은 말이다!

어떻게 해결할 수 있을까?

Neural Net

이걸 해결하는 방법이 Layer를 쌓아버리는 것이다.

Layer란 위에서 sigmoid 함수를 통과한 출력값을 다시한번

훈련시키는 것이다.

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

이 때, 주의해야 하는 것은, layer1의 출력 차원을 내가 조절할 수 있고,

또한 이 값이 layer2에 들어가게 되므로, 이 숫자를 맞춰서 넣어줘야 한다. 즉,

W1 = tf.Variable(tf.random_normal([feature의 수, output1의 차원]), name='weight1')
b1 = tf.Variable(tf.random_normal([output1의 차원]), name='bias1')
layer1 = tf.sigmoid(tf.matmul(X, W1) + b1)
 
W2 = tf.Variable(tf.random_normal([output1의 차원, output2의 차원]), name='weight2')
b2 = tf.Variable(tf.random_normal([output2의 차원]), name='bias2')
hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)

이런식으로 꼬리를 물고 들어가게 된다.

머릿속으로 구체화가 되어있어야 한다!

이부분만 바꿔주고 다시 돌리게 되면,

'''
Hypothesis:
[[0.01338216]
 [0.98166394]
 [0.98809403]
 [0.01135799]] 
Predicted:
[[0.]
 [1.]
 [1.]
 [0.]] 
Accuracy:
1.0
'''

잘 예측하는 것을 알 수 있다.

Wide NN for XOR

[2, 2] → [2, 1] 으로 부터, [2, 10] → [10, 1] 으로 바꿔서 진행해보자.

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

더 잘 학습되었다!

Deep NN for XOR

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)

레이어가 많을 수록 모델이 더 잘 학습된다.