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

딥러닝(DeepLearning) #4_ ReLU::Rectified Linear Unit

Tigercow.Door 2018. 4. 19. 22:30


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

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


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

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

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




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이 있습니다.



728x90