AI & BigData/모두를 위한 딥러닝(정리)

텐서플로우(Tensor Flow) #12_ Neural Network for XOR problem

Tigercow.Door 2018. 4. 18. 01:56


안녕하세요.

이번 포스팅에서는 우리가 딥러닝 이론에서 배웠던 XOR 문제를 텐서플로우로 해결해보도록 하겠습니다.

이론적인 부분은 아래 글에서 설명드렸기에, 코드에 대한 이야기를 주로 할 것 같습니다. 딥러닝에 대한 기본적인 이론이기에 잘 이해가 안되시는 분들은 아래 글을 참고해주세요.


딥러닝(DeepLearning) #1_ 딥러닝의 시작



* 해당 포스트의 모든 내용은 김성훈 교수님의 '모두를 위한 딥러닝'을 바탕으로 제작되었습니다.

관련한 상세 내용은 아래 링크를 참고해주세요.

https://hunkim.github.io/ml/




1. XOR data set


먼저 XOR이 어떤건지 간단히 살펴보겠습니다.



XOR은 위에서 가운데에 있는 심볼로 나타냅니다. 그리고 우리에게 필요한 데이터, truth table은 그 오른쪽 표와 같이 나와있습니다. 두 개의 input이 입력되고, input값이 서로 같을 때는 0을 출력하고, input값이 서로 다를 때는 1을 출력합니다.


이것을 텐서플로우에서 데이터로 입력해본다면 아래와 같은 코드로 입력됩니다.


1
2
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)
cs



2. XOR with Logistic Regression

그럼 이제 전체 모델에 대한 코드를 작성해보겠습니다.
이때, 다시 한번 y, 출력 데이터를 살펴보면 단순히 0 또는 1로만 이루어지기 때문에 우리가 굳이 softmax classifier 등과 같은 알고리즘을 사용할 필요 없이 단순히 logistic regression을 이용하면 됩니다.

지난 실습들에서 구현했던 방식과 마찬가지로 구현해본다면 아래와 같이 코드가 구현됩니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
import tensorflow as tf
import numpy as np
 
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)
 
= tf.placeholder(tf.float32)
= tf.placeholder(tf.float32)
= tf.Variable(tf.random_normal([2,1]), name = "weight")
= tf.Variable(tf.random_normal([1]), name = "bias")
 
# hypothesis: sigmoid(X * W + b)
hypothesis = tf.sigmoid(tf.matmul(X, W) + b)
 
# cost function / minimize cost
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
 
# predicate / accuracy
predicated = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicated, Y), dtype=tf.float32))
 
#
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for step in range(10001):
        sess.run(train, feed_dict={X: x_data, Y: y_data})
        if step%100 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}), sess.run(W))
    h, c, a = sess.run([hypothesis, predicated, accuracy], feed_dict={X: x_data, Y: y_data})
    print("\nHypothesis: ",h,"\nCorrect: ",c,"\nAccuracy: ",a)
 
cs

그리고 이를 실행시켜 결과를 확인해보면 아래와 같은 결과가 나옵니다.



결과에서 무언가 이상함을 느끼셨나요?

Accuracy가 0.5라는 값으로 출력되었습니다.


하지만 이는 이상한 것이 아닙니다.

우리가 이론시간에서 알아보았듯이, 하나의 node로, 그래프에서 생각해본다면 linear한 직선하나로 XOR 문제를 푸는 것은 불가능 하다고 했었죠.


그래서 우리는 layer라는 개념을 통해 여러개의 모델을 사용하고 이를 연결하는 방법을 배웠습니다. 그럼 그러한 방법으로 다시 시도해보도록 하겠습니다.



3. XOR with Neural Network

오히려 텐서플로우에서 layer라는 것을 이용하는 것은 어렵지 않게 느껴집니다.
단순히 우리가 하나로 만들었던 것을 쪼갠다고 생각하시면 됩니다.

전체적인 코드를 보면 아래와 같습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
import tensorflow as tf
import numpy as np
 
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)
 
= tf.placeholder(tf.float32)
= tf.placeholder(tf.float32)
 
# W = tf.Variable(tf.random_normal([2,1]), name = "weight")
# b = tf.Variable(tf.random_normal([1]), name = "bias")
# hypothesis = tf.sigmoid(tf.matmul(X, W) + b)
 
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)
 
# cost function / minimize cost
cost = -tf.reduce_mean(Y * tf.log(hypothesis) + (1 - Y) * tf.log(1 - hypothesis))
train = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
 
# predicate / accuracy
predicated = tf.cast(hypothesis > 0.5, dtype=tf.float32)
accuracy = tf.reduce_mean(tf.cast(tf.equal(predicated, Y), dtype=tf.float32))
 
#
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    for step in range(10001):
        sess.run(train, feed_dict={X: x_data, Y: y_data})
        if step%1000 == 0:
            print(step, sess.run(cost, feed_dict={X: x_data, Y: y_data}), sess.run([W1, W2]))
    h, c, a = sess.run([hypothesis, predicated, accuracy], feed_dict={X: x_data, Y: y_data})
    print("\nHypothesis: ",h,"\nCorrect: ",c,"\nAccuracy: ",a)
 
cs

14~20번 코드를 보시면, 이전에는 하나의 W, b로 hypothesis를 구해내는, 하나의 모델을 이용하는 방법이었는데 이번에는 2개로 나누어서 진행하였습니다.

그리고 결과를 확인해보면 아래와 같습니다.


처음에 나왔던 결과와 다르게, 모델이 제대로 훈련되어 Accuracy 값으로 1이 출력되었습니다.



4. Wide Neural Network

그럼, 우리가 보다 정확하게 예측할수 있는 방법은 무엇이 있을까요?
잠깐, 방금 작성했던 코드를 살펴보겠습니다.


위의 코드에서 빨간색 줄 그어져 있는 부분을 보겠습니다.

처음의 [2,2] 는 x의 입력이 2개이기 때문에 앞의 숫자 2가 나오고, 뒤의 숫자2는 임의로 출력을 2개로 한 것입니다.

그리고 b1에 있는 [2]는 W1에서 출력을 2로 했으므로 같이 맞춰주는 것입니다.


그리고 아래의 [2,1] 에서는 위에서 출력한 2개를 입력으로 받기 때문에 앞의 숫자2가 나오고, 우리가 최종적으로 출력하는 Y는 1개의 출력값을 가지므로 1, 한개로 출력하고 b2도 이와 함께 맞추어 준 것입니다.


즉, 이것을 그림으로 나타내면 아래와 같습니다.



그럼 다시 돌아와서, 우리가 보다 더 정확하게 예측할 수 있는 방법 중에 하나는, 위에 그림에서 두개의 모델 사이의 연결선을 증가시키는 방법입니다.


즉, 그림으로 생각하면 다음과 같이 되겠으며


코드로는 다음과 같이 구현이 되겠습니다.



그리고 이러한 변화를 결과로 확인해보면 다음과 같습니다.



모델을 보다 더 Wide 하기전과 비교해본다면, hypothsis의 작은 값은 더 작게, 큰 값은 더 크게 되는 것을 확인하실 수 있습니다.



5. Deep Neural Network


예측율을 높이는 다른 방법은 layer를 더 깊게 만드는 것입니다.


코드로 보면 아래와 같이, 단순하게 layer를 총 4개 사용하였습니다.



그리고 그 결과는 역시, 처음보다 더 좋은 예측율을 보여줍니다.




728x90