티스토리 뷰

모두의 딥러닝

ML 실용과 몇가지

강의

이번 강의에서는 러닝레이트(learning rate), 오버피팅(overfitting), 그리고 일반화(regularization) 대해서 학습한다.

우선 위의 이미지는 Gradient decent 그래프와 그를 구성하는 소스 그리고 함수를 나타낸다. 여기서 Learning rate 우리가 Gradient decent 알고리즘을 적용시킬 , 얼마만큼 경사각을 내려갈 것인지 정하는 부분이다. 지금까지 0.0001 ~ 0.1까지 다양하게 학습시켰던 숫자가 함수에서 나타나는 a값이고 Learning rate 이다.

Learning rate 값을 어떻게 정하느냐에 따라 학습이 잘될 수도, 안될 있을 만큼 아주 중요한 숫자이다.

Learning rate값을 잘못지정하면 값이 솟구쳐서 Nan이라는 값이 나타나는데 경우를 Overshooting 되었다고 표현한다. 위의 이미지와 같이 너무 Learning rate값이 커서 이동범위가 너무 넓어 계속 증가하는 현상을 말한다.

다음은 반대 현상인데 Learning rate 값을 너무 작게 정한 경우, 다음과 같이 오래동안 학습을 시켜도 Cost값이 내려가지 않는 경우가 발생한다.

그렇다면 어떻게 Learning rate 정해야 될까? 정답은 여러번의 테스트와 경험밖에 없다.

여러 번의 값으로 학습을 시키고, Cost 함수를 관찰하여 적당한 Learning rate 찾아야 우리가 원하는 학습 모델을 쉽게 만들 있을 것이다.

 

다음으로는 학습 시키는 데이터의 형태에 대해 말한다.

여러 개의 변수가 있는 경우 위의 그림과 같은 등고선 또는 3차원 입체 모양으로 나타날 것이다.

다음과 같은 형태로 되어있다면, 가운데 점을 우리가 원하는 Cost함수의 최저점이라고 정의하면

Gradient decent 경사각을 따라 쉽게 내려갈 있을 것이다.

그러나 다음과 같은 형태로 되어있다면 어떻게 될까?

그림과 같이 타원과 같은 형태로 되어있는 경우, 수평으로 이동할 때와, 수직으로 이동할 불균형이 발생하여, 최저점을 찾기 어려울 것이다.

데이터 값의 차이가 경우, 이러한 타원을 원형의 형태로 만들어주는 작업을 해야한다.

위의 이미지를 보면, 우선 기본적인 데이터를 두고, 최저점을 0 위치에 두도록 옮긴다. 그리고 타원으로 있는 데이터를 원형으로 만드는 작업을 진행하여 Gradient decent 적용시킬 있도록 데이터를 분포 시킨다.

 

이렇게 타원형으로 데이터를 원형으로 분포시키는 방법은 대표적으로 2가지 방법이 있다.

하나는 Standardization이고 다른 하나는 Normalization이다.

참조(http://pythonkim.tistory.com/23)

Normalization
수식 : (요소값 - 최소값) / (최대값 - 최소값)

설명 : 전체 구간을 0~100으로 설정하여 데이터를 관찰하는 방법으로, 특정 데이터의 위치를 확인할 있게 해줌

Standardization
수식 : (요소값 - 평균) / 표준편차
설명 : 평균까지의 거리로, 2 이상의 대상이 단위가 다를 , 대상 데이터를 같은 기준으로 있게 해줌
이미지 참조(http://gentlej90.tistory.com/26)

 

다음은 오버피팅(Overfitting) 대해 설명을 해주신다.

다음 그림에서 오른쪽 그림이 오버피팅이 경우이다. 그림에서 보이는 것과 같이 데이터셋에는 맞춰져 있지만, 과도하게 데이터셋에만 맞춰져 테스트 데이터 또는 실제 데이터에서는 맞지 않는 현상을 말한다.

오버피팅이 발생하는 이유는 다음과 같이 정의할 있다.

·       트레이닝 데이터가 작은 경우.

·       변수가 너무 많은 경우

그렇다면 오버피팅을 방지하기 위해선 어떻게 하면 될까?

발생하는 이유를 반대로 하면 된다.

·       트레이닝 데이터를 늘린다.

·       중복되는 변수를 줄인다.

·       정규화 한다.

정규화란 너무 w 값을 갖지 않도록 하는 것이다. W값이 너무 크면 위의 그래프와 같이 고불고불한 형태의 그래프가 되어 Gradient decent 사용해도 우리가 원하는 학습을 시키긴 어려울 것이다.

아래의 이미지 참조(http://pythonkim.tistory.com/23)

위에 3개의 그래프가 있다. Underfitting 학습이 이루어진 경우라, 학습을 시키면 된다. 그러나 Overfitting 경우는, 너무 데이터 셋과 맞아서, 학습데이터는 너무 정확하나, 테스트 또는 실제 데이터로 적용을 하는 경우는 안맞는 상황을 나타내는 그래프이다. 우리가 원하는 그래프는 Just right 형태이다.

정규화 시키는 방법은 w 너무 커서 Overfitting 발생하였으므로, w값을 낮추면 된다.

l2reg 변수를 살펴보면, 모든 w 제곱을 하여 더한 , 특정 (벌점)으로 곱해준다.

람다(λ)라고 부르는 부분에 우리가 원하는 값을 넣어 주면 된다.

 

강의-2

이번 강의는 학습 데이터와 테스트 데이터를 나눠서 학습시키는 것에 대해 다룬다.

위의 이미지와 같이 트레이닝 데이터를 사용하고 일부는 학습이 제대로 되었는지 안되었는지 확인하는 테스트 데이터 셋으로 분류를 한다.

위의 이미지를 보면, 트레이닝과 테스트가 분류 되어있고, 데이터가 많은 경우, 트레이닝과 발리데이션 그리고 테스트로 분류 되어있다.

 

다음으로는 실시간 또는 너무 많은 데이터를 학습시킬 사용할 있는 방법이다.

데이터가 너무 많은 경우, 위의 그림과 같이 조금씩 나눠서 학습을 시키는 방법이다.

 

Lab-1

우선 학습 데이터와 테스트 데이터를 분류하여 학습하도록 소스를 구성해보겠다.

import tensorflow as tf

x_data = [[
1, 2, 1], [1, 3, 2], [1, 3, 4], [1, 5, 5], [1, 7, 5], [1, 2, 5], [1, 6, 6], [1, 7, 7]]
y_data = [[
0, 0, 1], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [1, 0, 0]]

x_test = [[
2, 1, 1], [3, 1, 2], [3, 3, 4]]
y_test = [[
0, 0, 1], [0, 0, 1], [0, 0, 1]]

X = tf.placeholder(tf.float32
, [None, 3])
Y = tf.placeholder(tf.float32
, [None, 3])

W = tf.Variable(tf.random_normal([
3, 3]), name='weight')
b = tf.Variable(tf.random_normal([
3]), name='bias')

logits = tf.matmul(X
, W) + b
hypothesis = tf.nn.softmax(logits)

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

train = tf.train.GradientDescentOptimizer(
learning_rate=0.1).minimize(cost)

prediction = tf.argmax(hypothesis
, 1)

correct_prediction = tf.equal(prediction
, tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(correct_prediction
, dtype=tf.float32))

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

   
for step in range(201):
        cost_
, train_ = sess.run([cost, train], feed_dict={X: x_data, Y: y_data})
       
print("step: ", step, "\tcost: ", cost_)

   
print("prediction: ", sess.run(prediction, feed_dict={X: x_test}))
   
print("accuracy: ", sess.run(accuracy, feed_dict={X: x_test, Y: y_test}))

 

기존의 내용과 다른 테스트 데이터를 분류하여 테스트를 진행했다는 점이다. 다른 내용과 부분 외에는 차이가 없다.

 

다음으로 learning rate 대해 나오는데 위의 코드로는 아무리 learning rate 조절해도 Cost 값이 Nan 되는 경우는 발생하지 않았다원인이 무엇일까.. 부분은 숙제로 남은 같다.

 

결과만 보자면 김성훈 교수님이 주신 자료를 토대로 말하면, learning rate 크면 위의 그림과 같은 결과가 나타난다.

반대로 너무 learning rate 작으면 어떻게 될까? Cost 값이 너무 커서 정확한 결과값을 얻기 힘들 이다.

 

다음으로 Non-normalized 데이터를 normalized 시키는 방법이다.

import tensorflow as tf
import numpy as np

def Normalized(data):
    numerator = data - np.min(data
, 0)
    denominator = np.max(data
, 0) - np.min(data, 0)

 
   
return numerator / (denominator + 1e-7)

xy = np.array([[
828.659973, 833.450012, 908100, 828.349976, 831.659973],
              
[823.02002, 828.070007, 1828100, 821.655029, 828.070007],
              
[819.929993, 824.400024, 1438100, 818.97998, 824.159973],
              
[816, 820.958984, 1008100, 815.48999, 819.23999],
              
[819.359985, 823, 1188100, 818.469971, 818.97998],
              
[819, 823, 1198100, 816, 820.450012],
              
[811.700012, 815.25, 1098100, 809.780029, 813.669983],
              
[809.51001, 816.659973, 1398100, 804.539978, 809.559998]])

xy = Normalized(xy)

# print(xy)
x_data = xy[:, 0:-1]
y_data = xy[:
, [-1]]

X = tf.placeholder(tf.float32
, [None, 4])
Y = tf.placeholder(tf.float32
, [None, 1])

W = tf.Variable(tf.random_normal([
4, 1]), name='weight')
b = tf.Variable(tf.random_normal([
1]), name='bias')

hypothesis = tf.matmul(X
, W) + b
cost = tf.reduce_mean(tf.square(hypothesis - Y))

optimizer = tf.train.GradientDescentOptimizer(
learning_rate=0.1)
train = optimizer.minimize(cost)

sess = tf.Session()
sess.run(tf.global_variables_initializer())

for step in range(101):
    cost_
, hy_, _ = sess.run(
        [cost
, hypothesis, train], feed_dict={X: x_data, Y: y_data})
   
print(step, "Cost: ", cost_, "\nPrediction:\n", hy_)

 

Linear regression 사용하였고, 차이점은 Normalized라는 함수에 데이터셋을 넣어 데이터를 normalized 한다는 점이 차이점이다. 참고로 1e-7 더해주는 이유는 분모가 0 상황을 대비하기 위해 (영향을 미치지 않는 작은 크기의 ) 넣어 것으로 보인다.

 

Lab-2

이번 강의에서는 글씨로 작성된 숫자를 분류하는 학습을 만들어본다.

해당 소스는 Tensorflow에서 대표적인 분류 모델 하나로 다음 링크에서 더욱 상세히 확인할 있다. (https://www.tensorflow.org/get_started/mnist/beginners)

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

X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32
, [None, nb_classes])

W = tf.Variable(tf.random_normal([
784, nb_classes]), name='weight')
b = tf.Variable(tf.random_normal([nb_classes])
, name='bias')

logits = tf.matmul(X
, W) + b
hypothesis = tf.nn.softmax(logits)

cost_i = tf.nn.softmax_cross_entropy_with_logits(
logits=logits, labels=Y)
cost = tf.reduce_mean(cost_i)
train = tf.train.GradientDescentOptimizer(
learning_rate=0.1).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})
            avg_cost += c_ / total_batch

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

   
print('accuracy', accuracy.eval(session=sess, feed_dict={X: mnist.test.images, Y: mnist.test.labels}))

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

 

기존의 소스와는 다른 부분이 많이 보인다. 그리고 그만큼 소스 또한 길어진 같다.

우선 달라진 것으로, random 모듈을 불러온다. 나중에 랜덤으로 값을 불러와 테스트를 하기 위해서다.

 

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets(
"MNIST_data/", one_hot=True)

해당 내용은 데이터를 가져오고, 그리고 해당 데이터를 읽는 역할을 하는 명령어이다.

 

nb_classes = 10

X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32
, [None, nb_classes])

해당 이미지는 가로 28픽셀 x 세로 28픽셀로 구성이 되어 있다. 해당 값을 곱해보면 784라는 숫자가 나온다. 하나의 픽셀당 하나의 변수(특징) 784개라는 변수가 생성된다고 보면 된다.

그리고 숫자는 0~9 10개이므로, Y hat값을 10개의 (확률)으로 출력한다.

 

여기서 epoch batch 대해서 나오는데 해당 내용에 대한 설명은 위의 그림과 같다.

우선 1epoch = total batch size 이다.

Epoch >= batch 있다.

Batch size 메모리는 한정적이므로 데이터를 일부분 가져와 메모리에 저장하여 학습을 시키는데, 크기를 말한다.

그리고 epoch 위에 간략히 설명했지만, 바퀴 개념으로 보면 된다. 모든 데이터 셋이 학습시킨 단위를 1epoch라고 한다.

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})
            avg_cost += c_ / total_batch

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

 

epoch 15 설정하고, batch size 100으로 설정한다.

내용을 해석하면, 메모리에 100개씩 데이터를 올려서 처리하고, 모든 데이터는 15 학습한다.

 

# mnist.test.num_examples = 10000
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]}))

랜덤으로 0~ 9999개의 데이터에서 하나를 뽑아, 테스트를 진행한다.

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