티스토리 뷰

모두의 딥러닝

Neural Network 2: ReLU and 초기값 정하기 (2006/2007 breakthrough)

강의-1

이번 강의는 2006/2007년도 논문에 대해 이야기를 시작하며, Back-propagation에서 발생했던 문제에 대해 이야기한다.

지금까지의 이야기를 정리하면, 다른 문제는 Linear regression으로 해결 되었지만, XOR 문제의 경우, 기존의 방식으로는 해결이 불가능했다. 그래서 발견한게 Layer 2 이상으로 처리하는 것이었고, 그로 인해, 해당 문제는 해결할 있었다. 이것을 뉴럴 네트워크라 불렀다. 그러나 뉴럴 네트워크의 문제점은, 우리는 Cost함수 값을 최저값으로 만들어야되는데, W b값을 조절할 수가 없었다. 그렇게 침체기를 맞다, 나온게 Back-propagation이라는 알고리즘이다. 뒤에서부터 역추적하여, W b 값을 조절할 있단 것이었다.

그래서 우리는 위의 이미지와 같은 Hidden Layer 9개인 Deep 뉴럴 네트워크 또한 쉽게 구현할 있다. 지금까지 배운 내용으로는 Deep하거나 Wide하면 정확도는 높아질 것이라 생각할 있다.

그러나 결과는 위와 같다. 0.5, 50% 확률이다. 이런 문제가 발생할까?

이유는 우리는 결과값 이후, Sigmoid 처리해주는데, Sigmoid 0 또는 1 가까운 수를 가지게 되면서, 점점 Input Layer 가까울수록 W b값이 중요한데, 위의 이미지처럼 0.01 * 0.01 * 0.03 같이 곱해지면서 점점 값이 희미 해지게 된다. 아무리 커도 1이기 때문에, 계속 의미는 작아질 밖에 없다.

그래서 위의 이미지와 같이 Vanishing gradient라는 말이 나오게 되었고, Back-propagation로는 Deep 뉴럴 네트워크는 학습 시킬 없다라는 결론이 나오게 된다.

그러나 2006 이런 부분을 해결할 있는 논문이 발표되었다.

아주 황당한 함수이지만, 너무 뛰어난 함수인 ReLU 대한 발표이다.

해당 그래프는 0이하의 값에 대해서는 0으로 보내고, 0이상의 값에 대해서는 비율만큼 곱해 주자는 간단한 원리이다.

ReLU 그림과 같이 기존에 Sigmoid 있던 위치에 대체해주면 된다.

그림과 같이 기존의 Sigmoid위치를 ReLU 교체해주면 된다. 주의할 것은 우리가 최종적으로 결과값을 나타나는 Output Layer(마지막 레이어)에는 Sigmoid 사용 해줘야된다. 이유는, 우리는 분류를 하기 위해, Y hat 구하는데 ReLU 사용하면, 1이상되는 수가 나타날 있기 때문이다. 확률을 가장 나타내는 함수는 Sigmoid만한 없는 같다.

Sigmoid ReLU로만 바꿨을 뿐인데 결과값은 아주 만족스럽다. ReLU 대한 발표가 2006년도에 있었고, 논문은 파장을 일으켰다.

ReLU 등장으로 인해, 많은 다양한 그래프들이 생겼다. 기존 Sigmoid 대체하는 Tanh 그리고 ReLU 조금 변형한 Leaky ReLU 해당 그래프들을 숙지하고 학습시킬 , 비교하면서 학습을 해보면 좋은 결과를 수도 있다고 말씀하셨다.

내용은 각각 그래프를 변경하여 비교한 결과 테이블이다.

강의-2

다음으론 초기값 세팅에 대해 설명하신다.

위의 이미지처럼, W 초기값을 모두 0으로 두면, 학습은 이루어지지 않을 것이다.

이전 강의에서 비교했던 그래프를 텐서보드로 나타내었다. 그림에서 3개의 그래프를 확인할 있는데 우선, Sigmoid 학습이 안되던 것을 ReLU 통해 학습시켜 Cost값을 떨어뜨릴 있단 , 그리고 ReLU 그래프 2개를 비교해보면, 학습속도에서 차이가 난다. 이유는 무엇일까?

해당 부분은 초기값을 어떻게 설정하느냐에 따라 학습속도가 차이 나는 모습을 보여주는 그래프이다.

우리는 초기값 설정이 중요하다는 것을 확인할 있다. 그래서 RBM이라는 적절한 초기값을 설정하는 초기값 설정 학습법을 발표하였다.

해당 내용은 Layer(Input Layer) 다음 Layer(2번째) 각각 출력, 입력을 연결한 다음, 나온 값을 다시 Backward시켜, 최초의 X값과 X hat 값을 비교하여, 최적의 값을 구해 초기값(W,b) 설정하도록 되어있다.

최적의 초기값을 찾을 때까지 반복하다, 다음 Layer 넘어가 다시 반복하고, 최적의 값을 찾고, 다음 Layer 넘어 가고를 계속 반복하며 마지막 Layer까지 도달한다. 이것을 Deep Belief Network 부른다.

위의 이미지와 같이 Layer 하나씩 하나 옮겨가며 초기값을 설정하고, 1, 입력 Layer에서 마지막 Layer 학습시키는 학습법이다. 그래서 이미 학습을 시키기 초기값으로 학습이 되었다고 하여, 학습이라 부르지않고 Fine Tuning이라고 부른다고 한다.

우선 좋은 소식들로 RBM 구현하기가 조금 복잡했는데, 해당 내용은 사용하지 않아도 되는 좋은 성능의 초기값 설정 학습법이 나왔다. 이름은 Xavier initialization으로 발표한 사람의 이름이 Xavier 같다.

우선 복잡했던, RBM 달리 Xavier 정말로 간단하게 되어있다. 그러나 놀라운 것은 2015년도에 ImageNet에서 3% 에러를 발생시킨 He initialization이다. 내용은 기존 Xavier (입력값과 출력값 사이의 임의의 ) / (출력 / 입력값 제곱) 에서 (입력값과 출력값 사이의 임의의 ) / (출력 / (입력값/2) 제곱) 하여 변형을 시켰을 뿐이다.

Xavier 위의 이미지와 같이 간단히 구현할 있다. 물론, 현재는 텐서플로우에서 자체적으로 Xavier Initialization 사용할 있다.

초기값을 설정하고 다음의 결과값을 비교한 내용이다. Xavier뿐만 아니라 여러 개의 초기값을 세팅하는 함수가 존재한다는 것을 있다.

현재 초기값 설정 함수는 아직도 연구 중이며, 많은 새로운 함수들이 개발되고 있다.

강의-3

이번 강의도 학습을 시키기 위한 함수를 소개한다.

이전 강의에서 Overftting 대해 이야기했다. 너무 데이터 셋에 학습이 잘돼, 테스트 그리고 실전 데이터를 사용하면 정확도가 내려가는 현상이다.

Overfitting인지 아닌지 아는 방법은 학습시킨 데이터셋과 테스트 데이터 셋의 차가 심하면 Overfitting으로 정의하면된다.

해결법으로는 3가지가 있었고 우리는 정규화(Regularization) 대해 알아보려고 한다.

정규화는 너무 W값을 크게 갖게 하지 말자이다.

그림과 같이 특정 벌점 (여기서는 0.001) W 제곱하고 전체를 합한 값을 Cost 함수에 더해서 정규화 한다고 이전강의에서 설명했었다.

이와 같은 역할을 하는 알고리즘이 2014년에 발표되는데 Dropout이란 알고리즘이다.

학습을 시킬 , 일부를 랜덤하게 0으로 만들어 꺼버리는 것이다. 이게 학습이 잘될까? 하는 의문이 생길 있지만, 학습이 잘된다.

우선 Overfitting 경우, 여러가지의 원인 하나인 너무 데이터셋에만 맞게 학습이 이루어져 발생하는 문제이다. 해당 알고리즘을 사용하여, 너무 데이터셋에만 맞도록 학습 되는걸 방지하는 목적이 있는 같다.

텐서플로우에서 사용하는 방법은 간단한데, ReLU다음 dropout 추가해주면 된다. 추가적으로 설정할 부분이 있는데 얼마만큼 절전(데이터를 0)시킬 것인지에 대한 비율을 입력해야 된다. 부분이 dropout_rate이고, 보통 0.5 ~ 0.7 사이로 사용한다고 말씀하셨다.

, 주의 점은 dropout 학습시킬 때는, 0.5 ~ 0.7 설정하지만, 테스트 또는 실전 데이터를 입력으로 사용할 경우, 1(100%) 설정해야 된다.

다음으로는 앙상블이라는 개념이 나온다. 간단히 말하면, 여러 개의 모델을 학습시켜 하나로 합치는 방법이다.

부분 또한, 모델을 학습시키는 정확도를 향상시키는데 많은 도움이 된다. 2 ~ 5% 까지 향상시킬 있다고 말씀하셨다.

강의-4

이번에는 비싼 장난감으로 유명한 레고와 관련하여 이야기를 하신다.

레고와 딥러닝과의 공통점에 대해 말씀하시는데, 레고 블록을 쌓는 것과 같이 딥러닝을 구성하는 사람이 원하는 형태로 뉴런을 배치시키면 된다.

해당 방법은 ImageNet에서 3% 이하의 에러를 보인 방법으로, 그림과 같이 뉴런을 건너뛰는 것이다.

뿐만 아니라, 뉴런을 분배 시킬 수도, 합칠(CNN) 수도 있다. 그리고 RNN으로 알려진 뉴런 네트워크는 방향이 아닌 방향으로 뉴런이 구성되어 있다.

모델을 학습시키는 것의 한계는 오직 상상력이다.” 라고 말씀하시면서 어느 형태로 뉴런들을 배치시켜 학습시킬 있단 말씀하신다.

Lab-1

이번 강의는 지금까지 배웠던 것들을 이용해, MNIST 정확도를 높이는 소스를 만들어 본다.

import tensorflow as tf
import random

from tensorflow.examples.tutorials.mnist import input_data

mnist = input_data.read_data_sets(
"MNIST_data/", one_hot=True)

nb_classes =
10

dropout_rate = tf.placeholder(tf.float32)

X = tf.placeholder(tf.float32
, [None, 784])
Y = tf.placeholder(tf.float32
, [None, nb_classes])
# Deep 환경의 Back-Propagation 위한 초기값 설정
W1 = tf.get_variable(
"w1", shape=[784, 512],
                    
initializer=tf.contrib.layers.xavier_initializer())
b1 = tf.Variable(tf.random_normal([512]), name='bias1')

# Vanish Back-Propagation 위한 ReLU 함수 적용
L1_ = tf.nn.relu(tf.matmul(X
, W1) + b1)

# Overfitting 방지를 위한 Dropout 적용

L1 = tf.nn.dropout(L1_, keep_prob=dropout_rate)

W2 = tf.get_variable("w2", shape=[512, 512],
                    
initializer=tf.contrib.layers.xavier_initializer())
b2 = tf.Variable(tf.random_normal([
512]), name='bias2')
L2_ = tf.nn.relu(tf.matmul(L1
, W2) + b2)
L2 = tf.nn.dropout(L2_
, keep_prob=dropout_rate)

W3 = tf.get_variable(
"w3", shape=[512, 512],
                    
initializer=tf.contrib.layers.xavier_initializer())
b3 = tf.Variable(tf.random_normal([
512]), name='bias3')
L3_ = tf.nn.relu(tf.matmul(L2
, W3) + b3)
L3 = tf.nn.dropout(L3_
, keep_prob=dropout_rate)

W = tf.get_variable(
"w", shape=[512, nb_classes],
                   
initializer=tf.contrib.layers.xavier_initializer())
b = tf.Variable(tf.random_normal([nb_classes])
, name='bias')
hypothesis = tf.matmul(L3
, W) + b

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits(
logits=hypothesis, labels=Y))

# Gradient보다 정확도가 평균적으로 높다.
train = tf.train.AdamOptimizer(
learning_rate=0.001).minimize(cost)

is_correct = tf.equal(tf.argmax(hypothesis
, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_correct
, tf.float32))

epoch_size =
15
batch_size = 100

with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())

   
for epoch in range(epoch_size):
        avg_cost =
0
       
total_batch = int(mnist.train.num_examples / batch_size)

       
for batch in range(total_batch):
            batch_x
, batch_y = mnist.train.next_batch(batch_size)
            c_
, t_ = sess.run([cost, train], feed_dict={X: batch_x, Y: batch_y, dropout_rate: 0.5})
            avg_cost += c_ / total_batch

       
print("epoch: ", "%04d" % (epoch + 1), "cost: ", "{:.9f}".format(avg_cost))

    r = random.randint(
0, mnist.test.num_examples - 1)

    acc_ = sess.run(accuracy
, feed_dict={X: mnist.test.images, Y: mnist.test.labels, dropout_rate: 1})
   
print('accuracy: ', acc_)
   
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], dropout_rate: 1}))

 

우선 이번 소스에서 특이한 점은,

초기값을 Xavier initializer() 사용하여, 설정한 것과

Vanish Back-propagation 방지를 위한, ReLU 함수의 적용,

Overfitting 방지를 위한 Dropout 사용. 여기서는 0.5 학습을 시켰다.

마지막으로 AdamOptimizer 학습을 시킨 내용이다.

다른 부분들에 대해서는 이전 강의에서 설명을 내용이지만, AdamOptimizer 처음 들어봤는데 현재 텐서플로우에서는 학습 방법을 다양하게 제공한다.

위의 이미지처럼 다양한 Optimizers 있다.

해당 이미지는 optimizer 비교한 그림인데. 그림에 있는 링크(http://www.denizyuret.com/2015/03/alec-radfords-animations-for.html) 들어가면 해당 이미지뿐만 아닌 다양한 이미지로 비교를 것을 있다.

AdamOptimizer 성능을 다른 것과 비교한 것이다. 가장 Cost값이 낮아지는 확인 수있다.

김성훈 교수님은 Adam Optimizer 현재 나온 알고리즘 가장 뛰어나다고 한다. 그리고 사용법 또한 Gradient decent 다르지 않다고 한다. 정말 이름만 바꿔주면 위의 이미지처럼 사용할 있다.

댓글
공지사항
최근에 올라온 글
링크
«   2024/12   »
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
글 보관함