TigerCow.Door


안녕하세요. 문범우입니다.

이번 포스팅에서는 dropout과 model ensemble에 대해서 살펴보도록 하겠습니다.



1. Dropout


우리가 dropout을 하는 이유는 바로 아래와 같은 overfitting 때문입니다.



우리가 과거에 알아봤던 것처럼, 훈련 data에 있어서는 100%의 accuracy를 내지만, 실제로 test data에 있어서는 높은 예측율을 내지 못하게 되는 현상이죠.



위와 같이, 파란색 그래프, training 에서는 에러율이 점점 낮아지지만, 실제로 빨간색 그래프처럼 test data를 통해 확인해보니 어느 시점부터 에러율이 더 증가하게 됩니다.


이러한 overfitting은 우리가 더 깊게 만들수록 일어날 확률이 커집니다.

왜냐하면 더 깊어질수록 더 많은 변수가 생기기 때문입니다.


그럼 이를 해결하기 위해서는 무슨 방법이 있을까요?


첫번째로는, 더 많은 데이터를 훈련시키는 것입니다.

또는 feature를 줄여주는 방법도 있을 것입니다.

그리고 우리가 예전에 간단히 알아봤던, Regularization 이라는 방법이 있습니다.



우리가 예전에 알아봤던 것처럼, 위의 식과 같이 처리함으로써 Regularization을 하는 L2regularization도 있습니다.


그리고 Neural Network에서는 또다른, dropout이라는 방법이 있습니다.

dropout이란 쉽게 말해서, 위 그림에서 왼쪽 그림과 같은 모델에서 몇개의 연결을 끊어서, 즉 몇개의 노드를 죽이고 남은 노드들을 통해서만 훈련을 하는 것입니다.

이때 죽이는, 쉬게하는 노드들을 랜덤하게 선택합니다.




쉽게 말해 각 노드들을 어떤 전문가라고 생각해본다면 랜덤하게 몇명은 쉬게하고 나머지만 일하게 합니다. 

그리고 마지막에는 모든 전문가들을 총 동원해서 예측을 하게 합니다.


이러한 아이디어가 dropout 입니다.


실제로 텐서플로우에서 구현하기에도 어렵지 않게 가능합니다.

우리가 원래 만들었던 layer를 dropout함수에 넣어서, 몇 퍼센트의 노드가 일하게 할 것인지 함께 적어줍니다.

위의 코드를 보면 Train에서는 0.7, 즉 70%의 노드들이 랜덤하게 훈련되게 하였습니다.

그리고 실수하면 안되는 점이 Evaluation 과정에서는 dropout_rate를 1로 함으로써 100%의 노드들을 참가시키도록 해야 합니다.



2. Ensemble



우리가 추후, 학습시킬 수 있는 장비가 많을때 사용할 수 있는 또 하나의 방법도 있습니다.

Ensemble이라고 하는 것인데, 위와 같이 여러개의 독립적인 모델을 만듭니다. 이때 훈련 데이터셋은 별도로 해도 되고, 모두 같은 훈련 데이터셋을 이용해도 상관 없습니다.

이때 각 모델의 초기값이 서로 다르기때문에 결과도 약간씩 다를 것입니다.

그리고 이후에 독립적인 모델들을 모두 합쳐서 한번에 예측을 하게 합니다.

즉, 이것은 전문가 한명에게 어떤 질문을 하는 것이 아니고 서로 독립적인 전문가 다수를 모아두고 질문을 하는 것과 같습니다.


실제로 Ensembel을 이용하면 2%~5%까지도 예측율이 올라간다고 합니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번에는 지난 포스팅에 이어서 딥러닝을 잘하는 방법 중 weight의 초기값을 설정하는 방법에 대해서 알아보도록 하겠습니다.



1. RBM(Restricted Belief Machine)


우리가 지난 포스팅에서 위의 그림과 같은 Vanishing gradient 문제에 대해서 알아보았습니다.

그리고 이 문제에 대해서는 Hilton 교수님께서는 4가지 이유를 꼬집었습니다.


위의 4가지 항목중 제일 아래에 있는 것은 우리가 지난 포스팅에서 sigmoid함수 대신, ReLU함수를 사용함으로써 해결할 수 있었습니다.

하지만 하이라이트 된 것과 같이 또 다른 문제도 있었습니다.


이전의 테스트에서도 아래와 같이, 같은 ReLU함수를 사용했음해도 불구하고 cost가 초반에 다르게 변화하는 것을 볼 수 있습니다.


이러한 현상이 발생하는 이유는 우리가 테스트를 할때, 초기값을 랜덤하게 지정해서 발생한 현상입니다.


그럼, 이런 초기값에 대해서 좀 더 자세히 살펴보도록 하겠습니다.

단적으로 초기값을 0으로 설정해보면 어떨까요?

그럼, 위와 같은 그림에서 W를 0으로 둔것이고, 이것이 chain rule에서 사용됩니다. 그럼 x = df/dg * W 이므로 x = 0이 되고, 그 앞에 있는 것들도 모두 0이되면서 gradient가 사라져 버립니다.


따라서, 절대로 초기값으로 0을 주면 안된다는 것을 알 수 있습니다.

그럼 초기값을 어떻게 주어져야 할까요?


이에 대해 2006년 Hilton교수님께서 논문을 쓰시면서 RBM(Restricted Boatman Machine)을 사용함으로써 해결하게 됩니다.

그리고 이러한 RBM을 사용한 네트워크를 DBN(Deep Belief Networks)라고 합니다.


어떻게 동작되는 것 일까요?


먼저, 입력을 재생산 해냅니다.


위의 그림과 같이, 입력값을 weight와 곱해서 b값을 얻어냅니다. 또한 b 유닛아래에 있는 것들에 대해서도 같은 방법을 통해서 값을 얻습니다. 이러한 과정을 Forward 라고 합니다.



그리고, Backward 방법으로, 우리가 얻은 값들과 weight를 통해 위의 그림에서의 b 값을 얻습니다.

그럼 우리가 처음에 입력한 값을 x라고 한다면, x와 b의 값의 차이가 존재할텐데 이 차이가 최소가 될 때까지 weight를 조절합니다.


이렇게 해서 weight를 구하는 것을 RBM이라고 합니다.

그리고 위와 같은 방법을 encoder/decoder라고도 합니다.


실제로 이것을 네트워크 상에서 적용시키기 위해서는 아래와 같은 과정을 가집니다.

여러개의 레이어가 있을때, 입력값 측의 레이어부터 시작하여 layer 1과 layer 2를 encoder/decoder를 수행하고, 이후에 layer2 와 layer3에 대해 수행하며 끝까지 나아가는 방법입니다.


이제 이러한 과정을 통해 각 weight를 구할 수 있고, 그것을 학습시킨다, training한다는 표현보다는 fine tunning 이라는 표현을 사용합니다.

학습하는 것보다 훨씬 더 빨리 진행되는 작업이기 때문이죠.

이러한 fine tunning이 끝나게 되면 이후 우리가 학습시키고자 하는 데이터들에 대해서 label을 붙여서 실제로 training을 진행합니다.



2. Xavier initalize




그런데 실제로 이것을 구현하는데 있어서는 복잡한 과정이 있을 수 있습니다.

하지만 좋은 소식은, 2010년에 발표된 논문에서 우리가 굳이 RBM을 쓰지 않아도, 좋은 초기값을 얻을 수 있다는 Xavier initialize라는 알고리즘이 나왔습니다.


이는 입력의 노드의 개수에 비례해서 초기값을 세팅하면 된다는 식의 알고리즘 입니다.


이를 식으로 간단히 살펴보면, 우리가 좋은 값, 좋은 weight를 얻기 위해서 입력값의 개수 fan_in 과 출력 값의 개수 fan_out을 이용하여 초기값을 주는 것입니다. 이러한 식을 통해 어쩌면 RBM보다 더 좋은 결과를 가질 수 있다고 합니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

오늘은 ReLU(Rectified Linear Unit)에 대해서 알아보겠습니다.



1. NN for XOR


우리가 지난 시간에 XOR문제를 위와 같은 모델로 하여 풀이를 진행해보았습니다.

실제로 텐서플로우를 이용하여 구현해보기도 하였습니다.

그때 각 유닛의 결과에 우리가 Sigmoid 함수를 붙여서 결과값이 0~1이내로 출력되게 했었습니다.



이러한 Sigmoid함수를 activation function 이라고 합니다.

각 모델들에게 어떤 값을 보내게 될 때 일정값 이상이면 active되게 하고 그렇지 않으면 active하지 않게 하기 때문에 주로 그렇게 불린다고 합니다.


그리고 우리는 아래와 같이 각각의 W, b를 만들고 layer를 이용하여 2단의 네트워크를 만들었습니다.


그럼 3단을 가진 네트워크는 어떻게 할까요?

당연히 2단때와 같이, 쉽게 구현할 수 있습니다.

이때, 제일 처음이 layer를 input layer라고 부르며, 가장 바깥쪽(마지막)에 있는 layer를 output layer라고 부릅니다. 그리고 그 사이에 있는 layer들을 hidden layer라고 합니다.


그럼 더 깊게 한번 만들어볼까요?

hidden layer가 9단이 되게끔 구현해보도록 하겠습니다.


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
40
W0 = tf.Variable(tf.random_uniform([2,5], -1.01.0), name = 'weight0')
 
W1 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight1')
W2 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight2')
W3 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight3')
W4 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight4')
W5 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight5')
W6 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight6')
W7 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight7')
W8 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight8')
W9 = tf.Variable(tf.random_uniform([5,5], -1.01.0), name = 'weight9')
 
W10 = tf.Variable(tf.random_uniform([5,1], -1.01.0), name = 'weight10')
 
b0 = tf.Variable(tf.zeros([5]), name = 'bias0')
 
b1 = tf.Variable(tf.zeros([5]), name = 'bias1')
b2 = tf.Variable(tf.zeros([5]), name = 'bias2')
b3 = tf.Variable(tf.zeros([5]), name = 'bias3')
b4 = tf.Variable(tf.zeros([5]), name = 'bias4')
b5 = tf.Variable(tf.zeros([5]), name = 'bias5')
b6 = tf.Variable(tf.zeros([5]), name = 'bias6')
b7 = tf.Variable(tf.zeros([5]), name = 'bias7')
b8 = tf.Variable(tf.zeros([5]), name = 'bias8')
b9 = tf.Variable(tf.zeros([5]), name = 'bias9')
 
b10 = tf.Variable(tf.zeros([5]), name = 'bias10')
 
L1 = tf.sigmoid(tf.matmul(X, W0) + b0)
L2 = tf.sigmoid(tf.matmul(L1, W1) + b1)
L3 = tf.sigmoid(tf.matmul(L2, W2) + b2)
L4 = tf.sigmoid(tf.matmul(L3, W3) + b3)
L5 = tf.sigmoid(tf.matmul(L4, W4) + b4)
L6 = tf.sigmoid(tf.matmul(L5, W5) + b5)
L7 = tf.sigmoid(tf.matmul(L6, W6) + b6)
L8 = tf.sigmoid(tf.matmul(L7, W7) + b7)
L9 = tf.sigmoid(tf.matmul(L8, W8) + b8)
L10 = tf.sigmoid(tf.matmul(L9, W9) + b9)
 
hypothesis = tf.sigmoid(tf.matmul(L10, W10) + b10)
cs


위와 같이 hidden layer가 총 9단이 되도록 구현해보았습니다.

그리고 텐서보드를 이용하기 위해서는 추가적으로 name_scope를 사용하면 됩니다.


그리고 이러한 모델을 실제로 훈련시키고 결과를 확인해보면 다음과 같습니다.

Accuracy 가 0.5가 나왔습니다.

왜그럴까요?

우리가 지난번에 했을때보다 더 깊고, 더 넓게 훈련을 시켰는데 오히려 더 좋지 않은 결과가 나와버렸습니다.



2. Vanishing Gradient


우리가 지난 시간에 알아본, backpropagation에 대해서 다시한번 살펴보도록 하겠습니다.


우리가 위와 같은 구조를 공부했었는데, 이때 backpropagation에서 chain rule을 사용한다고 했었습니다.

지난 포스트에서 알아본것에 따르면, 빨간 동그라미, dg/dx = y의 값을 갖게되고 이에 따라 df/dx = df/dg * dg/dx = df/dg * y 가 됩니다.

근데 이때 y가 어떤 값을 가질지 한번 살펴볼까요?

y가 input layer가 아니었다면, 다른 유닛에 통과하고 sigmoid 함수를 통과했을 것입니다. 그럼 우리가 정확한 y의 값을 알지는 못해도 sigmoid 함수의 특성때문에 0~1사이의 값을 갖는다고 생각할 수 있습니다.

그럼 이때 y의 값이 예를 들어 0.01정도라고 생각해보겠습니다.

이렇게 된다면, 다시 올라가서 df/dx = df/dg * 0.01 이 됩니다.


이렇게 되는 것의 단점이 무엇이냐면, 결국에 값들이 sigmoid 함수를 지나게 되면서 그 값이 1보다 작게 되며 경우에 따라서는 굉장히 0에 가까운 값들이 계속 곱해지게 됩니다.

그러면 결국적으로 굉장히 작은 값을 갖게 됩니다.


즉, 그렇게 되면 결과 단에서 점점 깊어질 수록 그 영향을 찾기 힘들다, 예측하기 힘들다라는 결론을 가져오게 됩니다.

이런 현상을 Vanishing gradient 라고 합니다.



3. Rectified Linear Unit, ReLU


그리고 Hilton 교수님은, 이러한 현상에 있어서 sigmoid가 잘못되었다라는 것을 찾게되었습니다.

sigmoid함수 때문에 1보다 큰 값을 가지지 못하게 되었고, 이로 인해 layer가 깊어지면서 오히려 그 값이 작아져 영향을 찾기 힘들어지기 때문입니다.

그리고 새롭게 생각한 함수가 ReLu, Rectified Linear Unit 입니다


ReLU 함수는 단순합니다. 입력값이 0보다 작을 때는 아예 non-activate로 꺼버리고, 0보다 클때에는 그 값을 그대로 반환합니다.


이러한 ReLU를 사용하는 방법도 매우 간단합니다.

단순히 우리가 sigmoid를 사용하던 곳에 대신 ReLU를 사용하면 됩니다.

물론 텐서플로우에서도 위와 같이 매우 간단하게 사용할 수 있습니다.


실제로 우리가 위에서 제대로 값을 얻지못한 9단 hidden layer를 가진 모델에서 sigmoid 대신 ReLU를 사용하면 다음과 같은 cost를 가지게 됩니다.


ReLU를 여러번 돌리면서 약간의 차이는 존재하지만, sigmoid에 비해서는 훨씬 더 올바른 학습을 가지는 것을 볼 수 있습니다.

물론, layer에서 제일 마지막에선 sigmoid함수를 사용하여 결과 값이 0~1 사이로 나오게끔 해야합니다.


오늘 우리가 알아본 ReLU 이외에도 아래와 같이 다양한 activation function이 있습니다.



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

우리가 지난번 실습에서 텐서플로우를 통해 Neural Network를 이용하여 XOR 문제를 풀어보았습니다.

그런데 우리가 Neural Network를 이용하면서 보다 깊고 복잡한 문제를 해결할 때 그 학습과정등을 시각적으로 볼 수 있도록 하는 Tensorboard라는 것이 있습니다.

이번 포스팅에서는 그런 Tensorboard를 사용하는 방법에 대해서 알아보도록 하겠습니다.


1. Tensorboard


우선 텐서보드를 사용하면 위의 그림에서 보이는 것처럼 우리의 TensorFlow 그래프를 시각적으로 볼 수 있습니다.


그리고 cost에 관한 것도 그래프로 확인하면서 훈련이 잘 되고 있는지도 쉽게 확인할 수 있습니다.



텐서보드를 이용하기 위해서는 위와 같은 간단한 5가지 순서를 따라하면 됩니다.

실제로 지난 시간에 풀어본 XOR문제의 코드를 바탕으로 텐서보드를 사용해보도록 하겠습니다.



2. histogram & name_scope


먼저, 초기의 코드는 아래와 같습니다.


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
40
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,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")
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


이제 첫번째로 해야하는 것은, 우리가 그래프를 보기 위해 histogram을 이용하는 것과, 모델을 계층적으로 확인하기 위해 name_scope를 이용하는 것입니다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
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)
 
# name_scope 를 이용하여 계층별로 정리한다.
with tf.name_scope('layer1') as scope:
    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)
    # histogram을 이용하여 그래프를 확인할 수 있다.
    w1_hist = tf.summary.histogram('weight1',W1)
    b1_hist = tf.summary.histogram('bias1',b1)
    layer1_hist = tf.summary.histogram('layer1',layer1)
 
with tf.name_scope('layer2') as scope:
    W2 = tf.Variable(tf.random_normal([10,1]), name="weight2")
    b2 = tf.Variable(tf.random_normal([1]), name="bias2")
    hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)
 
    w2_hist = tf.summary.histogram('weight2', W2)
    b2_hist = tf.summary.histogram('bias2', b2)
    hypothesis_hist = tf.summary.histogram('hypothesis',hypothesis)
 
# cost function / minimize cost
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)
 
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:
    # writer logs and show graph
    merged_summary = tf.summary.merge_all()
    writer = tf.summary.FileWriter('./logs/xor_logs_01')
    writer.add_graph(sess.graph)
 
    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:
            # summary 실행
            summary, _ = sess.run([merged_summary, train], feed_dict={X: x_data, Y: y_data})
            writer.add_summary(summary, global_step=step)
 
            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~36번줄에 name_scope를 이용하여 계층별로 묶어주고, 각각에서 histogram을 이용한 것을 확인할 수 있습니다.



3. add logs & show graph


이제 우리가 훈련시키는 모델에 대한 로그를 작성하고 그것을 그래프로 보여주도록 하는 코드를 작성합니다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
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)
 
# name_scope 를 이용하여 계층별로 정리한다.
with tf.name_scope('layer1') as scope:
    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)
    # histogram을 이용하여 그래프를 확인할 수 있다.
    w1_hist = tf.summary.histogram('weight1',W1)
    b1_hist = tf.summary.histogram('bias1',b1)
    layer1_hist = tf.summary.histogram('layer1',layer1)
 
with tf.name_scope('layer2') as scope:
    W2 = tf.Variable(tf.random_normal([10,1]), name="weight2")
    b2 = tf.Variable(tf.random_normal([1]), name="bias2")
    hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)
 
    w2_hist = tf.summary.histogram('weight2', W2)
    b2_hist = tf.summary.histogram('bias2', b2)
    hypothesis_hist = tf.summary.histogram('hypothesis',hypothesis)
 
# 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:
    # writer logs and show graph
    merged_summary = tf.summary.merge_all()
    writer = tf.summary.FileWriter('./logs/xor_logs_01')
    writer.add_graph(sess.graph)
 
    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


위 코드의 43~45번 줄에 추가된 코드를 통해 로그를 작성하고, 그래프를 추가합니다.


그리고 각 step에서 세션을 실행시키고 우리가 그리고자 하는 그래프에 그 결과를 더해줍니다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
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)
 
# name_scope 를 이용하여 계층별로 정리한다.
with tf.name_scope('layer1') as scope:
    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)
    # histogram을 이용하여 그래프를 확인할 수 있다.
    w1_hist = tf.summary.histogram('weight1',W1)
    b1_hist = tf.summary.histogram('bias1',b1)
    layer1_hist = tf.summary.histogram('layer1',layer1)
 
with tf.name_scope('layer2') as scope:
    W2 = tf.Variable(tf.random_normal([10,1]), name="weight2")
    b2 = tf.Variable(tf.random_normal([1]), name="bias2")
    hypothesis = tf.sigmoid(tf.matmul(layer1, W2) + b2)
 
    w2_hist = tf.summary.histogram('weight2', W2)
    b2_hist = tf.summary.histogram('bias2', b2)
    hypothesis_hist = tf.summary.histogram('hypothesis',hypothesis)
 
# 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:
    # writer logs and show graph
    merged_summary = tf.summary.merge_all()
    writer = tf.summary.FileWriter('./logs/xor_logs_01')
    writer.add_graph(sess.graph)
 
    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:
            # summary 실행
            summary, _ = sess.run([merged_summary, train], feed_dict={X: x_data, Y: y_data})
            writer.add_summary(summary, global_step=step)
            
            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


52,53 번줄에서 그것을 수행합니다.



4. run tensorboard


이제 tensorboard를 실제로 실행시켜 그래프를 확인해보도록 하겠습니다.

터미널을 실행시켜서 아래와 같은 명령어를 입력합니다.


tensorboard -logdir=./logs/xor_logs_01


이때 명령어의 뒤에 있는 ./logs/xor_logs_01 은 우리가 로그 파일을 작성할때 경로와 파일 이름입니다.

물론 저는 터미널을 현재 파이썬 파일의 경로에 두고 실행시켰기 때문에 위와 같은 명령어로 진행했지만 다른 경로에서 명령어를 실행시키는 분들은 로그파일의 경로를 알맞게 작성해주셔야 합니다.



이렇게 실행시키고 웹 브라우저를 켜서 localhost:6006 또는 127.0.0.1:6006 으로 접속해보시면 tensorboard 창이 뜨고 여러가지 메뉴가 있습니다.

가장 쉽게 확인해 볼 수 있는 것은 아래와 같은 cost 그래프입니다.



cost가 학습을 하면서 0에 가까워지는 모습을 시각적으로 확인할 수 있으며 때문에, 우리의 모델이 제대로 훈련되었다고 생각해볼 수 있습니다.



5. Multiple runs


만약, learning rate를 서로 다르게한 두 모델을 비교해보고 싶다던가, 또 다른 요소를 다르게 한 모델을 서로 비교하여 한번에 tensorboard 에서 확인해보고 싶다면 아래와 같이 하면 됩니다.


위와 같이, 각각의 모델에 대해 로그파일을 만들고 tensorboard를 실행시킬때 그 로그파일들의 상위 경로를 입력하여 실행시킵니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요.

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

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


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



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개 사용하였습니다.



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




블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요



안녕하세요. 문범우입니다.

이번 포스팅에서는 Backpropagation에 대해서 알아보겠습니다.

지난 포스팅에서 XOR문제를 풀어보았는데, 정확하게 W나 b에 대한 값을 구하지는 못하였습니다. 그럼 이런 상황에서 어떻게 W와 b를 구하는지, 정확하게는 backpropagation이 어떻게 사용되는 것인지 알아보도록 하겠습니다.



1. Intro


먼저, 우리가 어떻게 W나 b와 같은 값을 구할 수 있을까요?

우리가 그동안 다루어 보았던 Gradient의 개념을 이용합니다.

우리는 보통 결과로 나오는 Y값을 통해 Cost함수를 정의하였습니다.

그리고 위와 같은 그래프형태로 나타날때, W가 어떤 초기값으로 시작하는지에 상관없이 그 점에서의 기울기를 이용하여 global minimum을 찾을 수 있었습니다.

즉, 이것을 구현하기 위해서는 특정 위치에서의 미분값을 필요로 합니다.


그런데 이것이 Neural Network로 가면서 복잡해지기 시작합니다. 


위와 같이 노드들이 한두개가 아니고, 각 노드에도 우리가 저번에 사용했듯이 sigmoid함수를 사용하는 등의 상황이 있었기 때문입니다.

여기서 미분값을 구한다는 것은 입력값 X이 결과 값 Y에 끼치는 영향을 알아야 한다는 것입니다. 그런데 단순히 입력값 X 뿐아니라, 각각의 노드들에 대해서도 구해야 각 노드들에 대한 W와 b값을 구할 수 있게됩니다.


그리고 이것은 1969년에 Minsky교수님께서 아무도 이것을 구할 수 없다라고 하실만큼 복잡한 과정이 되어버립니다.



2. Backpropagation


그런데 그러한 문제를 Backpropagation으로 해결하게 되었습니다.

Backpropagation은 그 이름에서도 알 수 있듯이, 우리가 forward로 진행하여 얻은 결과값과 실제값을 비교하여 얻은 error, 즉 cost를 통해 다시 뒤로 돌아가는 과정(backward)을 통해 어떻게 무엇을 설정해야 하는지 알아내겠다라는 개념입니다.


그럼 간단한 예제를 통해 실제로 Backpropagation이 어떻게 작동되는지 살펴보도록 하겠습니다.


위와 같이 정의된 f, g가 있습니다.

그리고 이제 여기서 알고자 하는 것은 w가 f에 미치는 영향, x가 f에게 미치는 영향, b가 f에게 미치는 영향입니다.

즉 알고자 하는 것을 그래프에 표시해본다면 아래와 같습니다.



그럼 이제 각각의 값들을 알기 위해 아래와 같은 과정을 진행합니다.


 1. forward(w = -2, x = 5, b = 3)

 2. backward 


1번 과정은 우리가 학습 데이터에서 값을 가져오는 과정이고 그리고 그 후 2번과정을 통해 실제 미분값을 구해보도록 합니다.


1번에서 주어진 데이터를 입력해본다면, g = -10, f = -7의 값을 가지게 됩니다.

그리고 우리가 처음에 정의한 식들을 편미분하여 아래와 같은 결과를 얻을 수 있습니다.

이렇게 정리가 되면 벌써 b가 f에 미치는 영향을 알 수 있게 됩니다.

df/db = 1 이기 때문이죠.


그리고 이어서 나머지 두 값을 얻기 위해, 먼저 g가 f에 미치는 영향을 생각해보면 df/dg = 1 이라는 식이 있기 때문에 이도 쉽게 구할 수 있습니다.


따라서 w가 f에 미치는 영향을 구해봅니다.

df/dw를 구하는 것인데 이때 chain rule을 이용합니다.

즉, df/dw = df/dg * dg/dw 와 같이 생각합니다.

그런데 이렇게 두고보니 df/dg와 dg/dw 두 값모두 알고 있습니다.

df/dg = 1, dg/dw = x = 5 이므로, df/dw = 1 * 5 = 5가 됩니다.


동일한 방식으로, x가 f에 미치는 영향, df/dx를 구해보면 아래의 식과 같습니다.

df/dx = df/dg * dg/dx = 1 * w = 1 * (-2) = -2


이렇게 구할 수 있습니다.


즉, 우리가 지금 간단한 예제로 진행해보았지만 실제로 더 복잡한 모델에서도 위와 같이 뒤에서부터 하나씩 순서대로 계산하면 매우 간단하게 w와 b등과 같은 값을 구할 수 있습니다.


또한 우리가 사용했던 sigmoid도 위와 같은 방법을 적용시킬 수 있습니다.

위의 그래프와 같이 g값을 이용하여 1/x에 대한 미분값을 얻고, 그 값과 +1 자체의 미분값을 구합니다. 그리고 같은 과정을 반복하면서 앞쪽으로 나아가면 됩니다.



이러한 방법을 통해 아래 그림과 같이 매우 복잡한 모델에 대해서도 기계적이고 반복적인 계산을 통해 미분값, 기울기를 구할 수 있습니다.



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요



안녕하세요. 문범우입니다.

이번 포스팅에서는 XOR문제에 대한 이야기를 해보도록 하겠습니다.


1. XOR 문제의 개요


지난 포스팅에서 딥러닝에 대한 개념과 그 동안의 역사에 대해서 알아보며, XOR문제가 매우 까다로운 문제로 다가왔음을 알아보았습니다.


그럼 그 골치덩이 문제를 어떻게 풀 수 있을까요?


먼저, 그때에 그 문제에 부딪혔던 이유 중 하나는, XOR문제가 단순히 하나의 모델로는 풀이가 불가능하다라는 증명 및 사실들 때문이었습니다.


그렇다면, 하나의 모델이 아닌 2개, 3개, 다수의 모델을 이용하면 어떨까요?


이러한 경우에는 XOR문제에 대해 풀이가 가능하다고 했습니다.


하지만, 또 한번의 문제가 발생했습니다.


여러개의 모델을 사용하는 경우에, 각각의 모델에 대한 학습은 어떻게 할 것이냐가 문제였습니다.

문제가 복잡해지고 어려워질수록 다수의 모델을 사용해야 하는데, 이 때 그러한 모델들을 학습하기 위한 W와 b를 구할 수 있는 해결방안이 없었습니다.



2. XOR using NN


그럼 먼저, Neural Network로 XOR문제를 해결해보도록 하겠습니다.

XOR은 위와 같은 속성을 가지고 있습니다.

x1 과 x2가 서로 다를 때만 그 결과가 1이고 나머지 경우에는 0의 결과값을 가집니다.

그리고 위의 그래프와 같이, 이를 그래프로 표현했을때 결과값 1과 0에 대해서 하나의 직선으로 정확히 나눌 수가 없습니다.


이러한 문제를 우리가 3개의 모델을 가지고 풀어보도록 하겠습니다.


위의 그림과 같은 3개의 모델을 이용합니다.

Model1 과 Model2에는 각각 x1과 x2의 데이터가 입력되고, 이에 대한 결과 값 y1과 y2를 Model3의 입력값으로 하여 최종 y값을 얻습니다.

이때 그림에서 동그라미 S가 있는 것은 sigmoid 함수를 나타낸 것입니다.


sigmoid는 과거에 살펴보았는데 아래와 같은 형태를 띄는 함수 입니다.



그럼 3개의 모델을 이용하는 것을 표로 정리해보면 다음과 같습니다.


X1

X2

Y1

Y2

Y

XOR

0

0




0

0

1




1

1

0




1

1

1




0


이제 이를 토대로 하여 실제 계산을 해보겠습니다.

다만 각 모델에 대한 W값과 b 값이 필요한데, 이를 구하는 방법은 다음 포스팅에서 다루도록 하고 일단은 임의의 값을 대입하여 풀이해보도록 해보겠습니다.



위와 같이 각 모델에 대한 W 와 b 값을 정하여 계산을 진행합니다.



위와 같이 각각의 X1, X2에 따라서 계산해보았습니다.

시그모이드에 관해서는 입력값이 양수이면 1, 음수이면 0으로 단순하게 계산하였습니다.

계산을 통해 얻은 값들을 표에 정리하면 다음과 같습니다.


X1

X2

Y1

Y2

Y

XOR

0

0

0

1

0

0

0

1

0

0

1

1

1

0

0

0

1

1

1

1

1

0

0

0

위의 표와 같이, 3개의 모델을 이용했을 때 최종적인 결과 값인 Y와 XOR의 결과 값이 일치함을 볼 수 있습니다.



즉, 위와 같이 3개의 모델을 이용해서 Neural Network를 구성하면 XOR 문제를 해결할 수 있습니다.

그런데 우리가 임의로 설정했던 W와 b값과 같은 형태말고도 다른 형태의 값들이 존재할까요?

한번 스스로 생각해보고 고민해보시길 바랍니다.


또한, 위와 같은 모델은 우리가 과거에 보았던 Multinomial 을 이용해 아래와 같이 표현할 수도 있습니다.



Model 1과 Model 2를 합친 것인데, 이때 W와 b를 알맞게 수정해줘야 합니다.

그리고 위에서 Model 1+2의 W를 W1, b를 b1이라고 하고 Model3의 W를 W2, b를 b2라고 한다면


K = sigmoid(X*W1 + b1)

Y = sigmoid(K*W2 + b2)


가 될 것이며, 이를 tensorflow 를 이용해 아래와 같이 표현할 수도 있습니다.


그럼, 이제 최종적으로 위와 같은 모델에서 W1, b1, W2, b2를 어떻게 계산해낼 수 있을까요?

이에 대한 것은 다음 포스팅에서 다뤄보도록 하겠습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요



안녕하세요. 문범우입니다.

이번 포스팅에서는 딥러닝의 기본 개념으로써 딥러닝의 시작과 XOR문제, 그리고 '딥'의 출현에 대해서 이야기 해보도록 하겠습니다.



1. 딥러닝의 시작



많은 과학자들은 인간이 고민하고 어려워 하는 문제들에 대해서 기계가 해결시켜주기를 바랬습니다.

그리고 그 시작으로 먼저 인간의 뇌를 분석하기 시작했습니다.



그리고 분석된 뇌에 대해서 수학적으로 식을 세우고, 풀어냈습니다.


이를 간단히 하여 위와 같은 그림으로 나타내게 되었습니다.

지난 포스팅들에서도 확인했던 그림들입니다.

그리고 이러한 구조를 직접 하드웨어를 통해 만들기도 하였습니다.

57년도에 Frank 박사님께서 하드웨어로써 이를 구성하기도 하면서 많은 사람들이 이에 대한 꿈을 꾸기 시작했습니다.

그리고 58년도에 NewYork Times에는 이러한 기계들이 스스로 학습하며 보고, 듣고, 말하고, 심지어 스스로를 인지한다는 말까지 하게 되었습니다.

이러한 상황은 역시나 많은 사람들의 관심을 갖게되는 시작이 되었습니다.


그 시작으로 x1과 x2에 대해서 AND와 OR에 대한 답을 내는 문제를 풀기 시작했습니다.

그리고 그 문제들을 풀면서 굉장한 희망을 갖게되었지만,

다시 한번 좌절을 겪게 되는 문제가 있었습니다.


그 문제는, 매우 간단하지만 이전과 다른 XOR문제 이었습니다.

즉, 그전의 AND와 OR문제에 대해서는 linear하게 선을 그어서 문제를 해결할 수 있었지만 XOR문제에 있어서는 어떤 linear한 선을 그어도 그 정확도가 매우 낮을 수 밖에 없었습니다.

그리고 69년도에 MIT AI lab에 있었던 Minsky교수는 이를 수학적으로 풀 수 없는 문제임을 증명합니다. 동시에 MLP(Multilayer perceptrons, Multilayer neural nets) 이 필요하지만 각각의 layer에 대해서 아무도 학습시킬 수 없다고 이야기합니다.


그리고 74년도, Paul Werbos 박사님과 86년도 Hinton 박사님에 의해서Backpropagation 이라는 개념이 등장면서 XOR을 포함한 더 복잡한 문제들을 해결할 수 있게 되었습니다.

또한 LeKun 박사님에 의해서 Convolution Neural Networks 라는 알고리즘이 개발되기도 하였습니다.




기존에는 forward 방식으로 학습을 진행하는 방식이었는데 이러한 방법에서는 앞에서 부터 에러를 수정하는 등의 방법이 어려웠지만 Backpropagation 에서는 에러를 검출하고 그곳에서 부터, 즉 backward 방식으로 에러를 수정하는 알고리즘입니다.



그리고 Convolutional Neural Networks 란 어떤 이미지에 대해서 한번에 인식하게끔 하는 것이 아니라, 부분부분으로 나눠서 이를 학습하고 나중에 합치는 방법입니다.

우리가 흔히 알고있는 '알파고' 또한 이러한 방식의 AI입니다.


그렇지만, 95년도에 다시 한번 큰 문제에 부딪히게 됩니다.



그 동안 진행했던 Backpropagation 은 간단한 문제들을 해결 할 수 있었지만, 우리가 실질적으로 해결하고자 하는 복잡한 문제들에 대해서는 앞에서 발생한 에러를 뒤로 보내다 보니 이 에러의 신호가 너무 약해져 뒤에 가서는 무의미해지게 됩니다. 즉, 복잡한 문제에 대한 훈련을 할 수록 성능이 더 떨어지게 됩니다.

또한 LeKun 교수님께서도 오히려 다른, 랜덤 방식의 알고리즘들이 더 성능이 좋다고 하면서 다시한번 AI분야에 대한 열기가 식게 되었습니다.



2. CIFAR 와 '딥'의 출현



이러한 찬바람 속에서 등장한 단체가 있었습니다.

바로 CIFAR 라는 캐나다에 위치한 단체인데, 이 단체는 당장 지금 돈이 되지 않아도 연구를 하라는 등의 지원을 했습니다.

그리고 Hinton 교수님은 이 단체가 위치한 캐나다로 이주하게 됩니다.



그리고 마침내 2006년, 2007년에 Hinton 교수님과 Bengio 교수님의 논문들을 통해 큰 돌파구가 생기게 됩니다.

그 전에는 우리가 매우 '딥'한 문제들에 대해서 학습을 시키는데 문제가 발생했는데 2006년 논문에서, 우리가 이러한 문제들이 생기는 이유는 초기값을 제대로 설정하지 못해서라고 이야기를 합니다.

그리고 2007년에는 그 초기값문제가 맞으며 한걸음 더 나아가 깊은 '딥'한 문제를 풀수 있음을 보여주게 됩니다.

그리고 이때, Neural Nets 가 아닌, 새로운 이름 Deep Nets, Deep Learning 으로 새로운 시작을 하게 됩니다.



그리고 실제로 더 주목을 받게되는 계기는 ImageNET이라는, 이미지를 보고 컴퓨터가 무엇인지 맞추는 문제에서 입니다.

그 전에는 매년 1~2%의 오차율을 감소시키며 2011년 기준으로 약 26%의 오류를 가지고 있었지만 2012년 Hinton 교수님의 연구실에 있는 박사과정 학생이 오류를 15%로 떨어뜨리게 됩니다.

이는 2015년, Deep Learning 기술을 기반으로 해서 약 3%대의 오류를 가지게 됬는데, 이때 사람의 오류는 약 5%였다고 합니다.


그리고 이후에는 컴퓨터가 단순히 이미지를 맞추는 것이 아니라 이미지에 대해 설명을 하는 기술까지 개발이 되었습니다.


그리고 이후 Hinton 교수님은 우리가 왜 그전에는 잘 하지 못했을까에 대해 4가지 문제를 이야기합니다.

이제 이러한 것들에 대해서 천천히 이야기를 해보도록 하겠습니다.

그리고 다음 포스팅에서는 우리가 직접 XOR문제를 딥러닝으로 해결해보도록 하겠습니다.


블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

오늘 포스팅에서는 실전데이터를 이용해서 모델을 만들어 보도록 하겠습니다.


1. MNIST data



오늘 우리가 사용해볼 데이터는 위의 그림과 같은 MNIST dataset 입니다.

보시면 아시듯이 손으로 쓴 숫자들 입니다.

이 데이터들은 아래 주소에서 손쉽게 다운받을 수 있습니다.


http://yann.lecun.com/exdb/mnist/


위의 사이트에서 4개의 알집을 모두 다운받았습니다.

그럼 각 데이터가 어떤 형태를 가지고 있는지 좀 더 자세히 알아보도록 하겠습니다.


MNIST의 데이터들은 위와 같이 28x28 픽셀로 이루어져 있습니다.

하나의 데이터에 총 784개의 픽셀이 존재합니다.

즉 우리는 784 개의 shape의 데이터를 이용하는 것 입니다.

그리고 결과 값 y 로는 0~9까지 10개의 출력이 될 것입니다.


이러한 MNIST 데이터는 많이 이용되기 때문에, 우리가 보다 쉽게 다룰 수 있도록 라이브러리를 지원해주고 있습니다.


from tensorflow.examples.tutorials.mnist import input_data


위와 같은 코드로 라이브러리를 불러올 수 있습니다.


먼저 전체적인 코드는 아래와 같습니다.


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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import tensorflow as tf
import matplotlib.pyplot as plt
import random
from tensorflow.examples.tutorials.mnist import input_data
 
# loading data
mnist = input_data.read_data_sets("/Users/doorbw/Desktop/Beomwoo/deep_learning_zeroToAll/", one_hot=True)
 
nb_classes = 10
 
= tf.placeholder(tf.float32,[None,784])
= tf.placeholder(tf.float32,[None,nb_classes])
 
# using softmax classifier
= tf.Variable(tf.random_normal([784, nb_classes]))
= tf.Variable(tf.random_normal([nb_classes]))
 
# Hypothesis(using Softmax)
hypothesis = tf.nn.softmax(tf.matmul(X, W) + b)
 
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(hypothesis), axis=1))
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
 
# Test model
is_correct = tf.equal(tf.arg_max(hypothesis,1), tf.arg_max(Y, 1))
# Calculate accuracy
accuracy = tf.reduce_mean(tf.cast(is_correct,tf.float32))
 
# parameters
# Training epoch/batch
training_epochs = 15
batch_size = 100
 
with tf.Session() as sess:
    # Init Tensorflow variables
    sess.run(tf.global_variables_initializer())
    # Training cycle
    for epoch in range(training_epochs):
        avg_cost = 0
        total_batch = int(mnist.train.num_examples / batch_size)
 
        for i in range(batch_size):
            batch_xs, batch_ys = mnist.train.next_batch(batch_size)
            c, _= sess.run([cost,optimizer], feed_dict={X: batch_xs, Y: batch_ys})
            avg_cost += c / total_batch
 
        print('Epoch:''%04d' %(epoch+1), 'cost = ''{:.9f}'.format(avg_cost))
 
    print("Learning finished")
    print("Accuracy: ", accuracy.eval(session=sess,feed_dict={X: mnist.test.images, Y: mnist.test.labels}))
 
    # Get one and predict using matplotlib
    r = random.randint(0, mnist.test.num_examples - 1)
    print("Label: ", sess.run(tf.argmax(mnist.test.labels[r:r + 1], 1)))
    print("Prediction: ", sess.run(
        tf.argmax(hypothesis, 1), feed_dict={X: mnist.test.images[r:r + 1]}))
 
    plt.imshow(
        mnist.test.images[r:r + 1].reshape(2828),
        cmap='Greys',
        interpolation='nearest')
    plt.show()
 
cs


전체적인 학습 부분에 있어서는 그동안 실습을 진행했던 내용과 동일합니다.

그렇지만 중간에 새롭게 다루는 개념이 하나 있는데 epoch이라는 개념입니다.

먼저 정의는 아래와 같습니다.



epoch이라는 것은 전체 데이터셋을 한번 학습하는 것이라고 합니다.

하지만 우리가 메모리상의 문제등이 있기 때문에 하나의 epoch을 나누어서 학습하는데 그 때의 단위가 batch size입니다.


위의 코드에서는 15번의 epoch을 진행하며 batch size는 100으로 잡아서 학습을 진행합니다.


50번째 줄까지 진행하면 각 epoch 당 cost 가 출력되며 마지막에는 accuracy 가 출력되도록 하였습니다. 

그리고 이후 52번째 줄에서는 matplotlib를 이용하여 하나의 x 데이터를 랜덤하게 뽑아내서 이를 matplotlib 을 통해 출력하고 우리가 만들었던 모델이 예측하게 합니다.


결과를 확인하니 accuracy 는 약 82~88% 정도가 나오는 듯 합니다.



블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요


안녕하세요. 문범우입니다.

이번 포스팅에서는 우리가 만든 모델에 대한 Learning rate 를 설정하는 방법과 evaluation을 해보는 과정을 진행해보도록 하겠습니다.



1. Training and Test data sets


이번에 알아볼 내용은 우리가 가진 데이타셋을 training 과 test로 나눠보는 것입니다.

이전까지의 실습에서는 이런 구분 없이 우리가 가진 모든 데이터를 통해 traning을 하고 test를 했는데, 엄밀히 말해서 이는 틀린 방법입니다.


이제부터는 반드시 데이타셋을 나눠서 진행합니다.

즉, 우리가 가진 데이터셋을 Training datasets과 Test datasets으로 나눠서 진행하는 것입니다.

그럼 이것을 어떻게 나눌까요?

이는 생각보다 매우 쉽습니다.

우리가 가진 데이터를 10개라고 했을때, 이중 7개정도는 그동안 했던 것처럼 x_data와 y_data로 설정을 하고 나머지 3개에 대해서 x_test, y_test로 설정을 해둡니다.



그리고 위와 같이 우리가 지난 실습에서 했던 것처럼 코드를 작성하고, 빨간색 밑줄쳐져 있는 부분처럼, 학습할때는 x_data 와 y_data 를 이용하며, 이후 prediction에서는 x_test와 y_test를 이용합니다.



2. Learning rate


두번째로 우리가 알아보아야 하는 것은 Learning rate 입니다.

이전 실습에서는 우리가 learning rate를 단순히 0.1 또는 0.01 이라는 식으로 진행했는데 이번에는 이에 대해서 좀 더 자세히 알아보도록 하겠습니다.


Learning rate를 잘못 설정했을때 야기되는 문제는 크게 2가지가 있습니다.

위의 그림에서 왼쪽 그래프와 같이 Learning rate가 클때는 overshooting 이라는 문제가 생길 수 있으며 Learning rate가 작을 때는 왼쪽 그래프와 같은 문제가 발생할 수 있습니다.


그럼 실제로 확인해보도록 하겠습니다.



위 코드는 이전과 같은 모델에 대한 코드입니다. 단지 learning rate를 1.5로 매우크게 설정해보았습니다.

이에 대한 결과는 오른쪽 초록색글씨로 되어 있는데, 초반부터 cost가 매우 큰것을 확인할 수 있는데, 5번째 스텝을 보시면 cost가 무한대가 되고 이후에는 nan 값으로 학습되지 않는 것을 볼 수 있습니다.


반대로 아래코드와 같이 learning rate 를 매우작게 해보면,



오른쪽 결과와 같이 학습이 제대로 이루어지지 않고 있는 것을 볼 수 있습니다.



3. Normalization


그런데, learning rate 조차 제대로 설정한 것 같은데 제대로 결과가 나오지 않을때가 있습니다. 이럴땐 데이터의 normalization을 확인해봐야 합니다.



위와 같이 xy 데이터가 존재하는데 값을 살펴보시면, 데이터끼리 매우 큰 차이가 나고 있습니다.

이는 그 아래의 그래프와 같은 형태를 띄게 되어서 학습을 하면서 약간의 움직임만으로도 cost가 튕겨져 나가는 현상이 발생될 수 있습니다.



이런 데이터를 위의 코드처럼 간단한 linear regression을 구현해보았는데 오른쪽 결과와 같이 제대로된 학습이 되지 않는 것을 볼 수 있습니다.

즉, 데이터간의 차이가 너무 커서 발생되는 문제인데 이러한 데이터는 normalization을 진행해야 합니다.



normalization 을 하는 방법은 다양하지만 그 중 minmaxscaler 함수를 위와 같이 이용해보면 데이터간의 큰차이가 존재하지 않게 됨을 볼 수 있습니다.



그리고 이전과 동일한 코드를 통해 학습을 해보면 오른쪽 결과와 같이 학습이 매우 잘 이루어 지는 것을 확인할 수 있습니다.

블로그 이미지

Tigercow.Door

Web Programming / Back-end / Database / AI / Algorithm / DeepLearning / etc

댓글을 달아 주세요