머신러닝 팁과 응용


Learning Rate

learning_rate = 0.001
cost = tf.reduce_mean(-tf.reduce_sum(Y*tf.log(hypothesis), reduction_indices=1))
optimizer = tf.train.GradientDescentOptimmizer(learning_rate).minimize(cost)

경사하강법에서 임의의 \(\alpha\)값을 주어 할당했다. Learning rate는 경사하강법에서 반복문 1회마다 이동할 경사(Gradient)의 보폭(step size)을 뜻하기 때문에 이 Learning rate의 값이 너무 클 경우 학습 진행도중 cost값이 경사의 최저점을 지나치게 된다. 또 그럴 경우 알고리즘은 또 다시 최저 경사를 찾아 경사를 내려가게 되고 무한 루프에 빠지거나 경사의 바깥으로 나가버릴 수도 있다. 이 현상을 overshooting이라고 부른다.

import tensorflow as tf
import numpy as np

xy = np.loadtxt('train.txt', unpack=True, dtype='float32')
x_data = xy[0:-1]
y_data = xy[-1];

X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)

W = tf.Variable(tf.random_uniform([1,len(x_data)], -1.0, 1.0))

h = tf.matmul(W, X)
hypothesis = tf.div(1., 1+tf.exp(-h))

cost = -tf.reduce_mean(Y*tf.log(hypothesis) + (1-Y)*tf.log(1-hypothesis))

learning_rate = tf.Variable(1)
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
train = optimizer.minimize(cost)

init = tf.global_variables_initializer()

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

for step in range(501):
    sess.run(train, feed_dict={X:x_data, Y:y_data})
    if step % 50 == 0:
        print(step, sess.run(cost, feed_dict={X:x_data, Y:y_data}), sess.run(W))

>>

0 2.59841 [[-1.21369731 -0.35063034 -0.45811498]]
50 nan [[ nan  nan  nan]]
100 nan [[ nan  nan  nan]]
150 nan [[ nan  nan  nan]]
200 nan [[ nan  nan  nan]]
250 nan [[ nan  nan  nan]]
300 nan [[ nan  nan  nan]]
350 nan [[ nan  nan  nan]]
400 nan [[ nan  nan  nan]]
450 nan [[ nan  nan  nan]]
500 nan [[ nan  nan  nan]]

알고리즘이 숫자가 아닌 값을 반환하는 것을 확인할 수 있다.

하지만 그렇다고 learning rate을 너무 작게 할당하면 알고리즘이 지연된다. 학습도중 cost값이 거의 줄어들지 않는 경우가 발생한다면 learning rate를 조금 크게 조정하는 편이 좋다.
모델이 돌아가는 상태를 print해가며 직접 진단해 몇 가지의 learning rates를 시도해보는 게 좋다. 0.01 정도의 learning rate으로 시작하는 것은 보통 나쁘지 않다.

경사하강법을 위한 변수 전처리

여러 feature가 있을 때 각 feature들의 단위가 다르거나 값이 심하게 차이날 경우 이를 Normalization(정규화, regularization, standardization도 비슷하게, 혹은 똑같이 번역되지만 다른 뜻이다.)시킬 필요가 있을 수 있다. learning rate를 알맞게 설정했음에도 cost값이 자연스럽게 줄어들지 않는 등 증상이 나타날 경우 데이터를 전처리할 필요가 있다.

Standardization(표준화), normalization의 한 방법

\[x'_j=\frac{x_j-\mu_j}{\sigma_j}\]
X_std[:,0] = (X[:,0] - X[:,0].mean()) / X[:,0].std()

과적합(Overfitting)

  • 학습 데이터 셋에 매우, 지나치게 적합한 모델.
  • 시험 데이터셋이나 실제 상황에서 부적합한 모델.

해결책

  • 많은 학습 데이터
  • 설명변수의 수를 줄인다.
  • Regularization(규칙화)시킨다.

Regularization

weight에 너무 큰 값을 부여하지 말자.

\[Loss = \frac{1}{N} \sum_i D(S(WX_i+b)L_i)\]

기존의 cost 함수의 뒤에 Regularization을 추가해주면 된다.

\[Loss = \frac{1}{N} \sum_i D(S(WX_i+b)L_i) + \lambda \sum W^2\]

여기서 \(\lambda\)는 regularization strength라고 한다. (이 값은 learning rate처럼 직접 정하면 된다.)

l2reg = 0.001 * tf.reduce_sum(tf.square(W))
cost = cost + l2reg

모델 평가하기

Train을 시킨 데이터셋으로 모델을 평가하는 건 보통 불공평하거나 의미가 없다. 모델이 이미 데이터를 학습했다는 점 때문에 해당 데이터셋에 대해 100% 정확한 값을 예측할 수도 있고 값을 외울 수도 있지만, 이런 방법으로는 모델이 주어진 데이터에 대해 과적합(Overfitting)한지 확인할 수 없다. 따라서 주어진 데이터셋을 일정비율 나눠 앞 부분의 데이터셋을 학습 데이터셋으로, 뒷 부분의 데이터셋을 시험용 데이터셋으로 사용하는 게 보통이다. 시험용 데이터셋은 사전에 학습시키지 않아야 하며 모델의 성능을 평가할 때에만 사용해야 한다.

이 방법 외에도 데이터 셋을 세 개로 나눠서 첫 부분을 학습용 데이터셋으로, 두 번째 부분을 검증, 튜닝용 데이터셋으로, 세 번째 부분을 최종 시험용 데이터셋으로 확인하는 방법도 있다.

온라인 학습(Online Learning)

데이터셋을 분할하거나 지속적으로 데이터를 수집할 때 이미 어떤 데이터를 통해 학습시킨 모델을 계속해서 새로운 데이터로 학습시키며 점차 모델을 발전시키는 학습의 형태이다.

평가 척도

정확도 : 예측한 값 / 실제 label 값

분류 모델의 평가 척도

재현율 : 진양성(True positive) / 진양성(True positive) + 가음성(False negative)
정밀도 : 진양성(True positive) / 진양성(True positive) + 가양성(False positive)