Lab07-1. Application&Tip
Application & Tip
Learning rate, Evaluation
1. Learning rate
Linear regression과 Classification에서 학습은 GradientDescent를 이용하여 cost를 최소화 함
tf.train.GradientDescentOptimizer 함수의 파라미터로 learning_rate를 임의로 지정하여 전달
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.1).minimize(cost)
즉, learning rate는 학습의 속도를 나타냄
1) Learning rate에 따라 발생하는 문제
Overshooting (좌측그림)
- 지정한 learning rate가 클 때 발생하는 문제
- cost가 최소화 되지 않고 cost가 증가하여 그래프를 벗어나는 문제가 발생할 수 있음
Small learning rate (우측그림)
- 지정한 learning rate가 작을 때 발생하는 문제
- 학습이 종료될때까지 cost가 최소화 되지 않는 문제 발생
2) Learning rate를 지정하는 방법
Learning rate를 잘 지정하는 특별한 방법은 없으며 환경과 데이터에 따라 learning rate가 변경되어야 함
먼저 learning rate를 0.01 정도로 지정하여 학습을 시작한 후 cost에 따라 변경하여 지정하는 것이 좋음
2. Data preprocessing
Learning rate에 따라 overshooting과 같은 문제가 발생할 수 있으므로, data preprocessing이 필요
1) Standardization
특정한 분포들의 평균($\mu$)과 표준편차($\sigma$)를 이용하여 데이터를 변환
x_std[:,0] = (x[:,0]) - x[:,0].mean()) / x[:,0].std()
2) Normalization
실제값 범위를 표준값 범위(일반적으로 -1~1 또는 0~1)로 변환하는 과정
최소값($x_{min}$), 최대값($x_{max}$)이용
3. Overfitting
Overfitting은 머신러닝의 가장 큰 문제점
1) Overfitting
생성한 모델이 training data set에 지나치게 잘 맞는 경우를 의미, test data set이나 실생활에서 사용할 수 없음
Overffing의 문제점
모델이 과도하게 복잡해짐
새 데이터를 올바르게 예측하지 못함
범용성 있게 사용 불가능
2) Overfitting의 해결책
더 많은 Training data
Feature의 수를 줄임
Regularization: feature의 수를 유지하면서 overfitting을 피하는 방법
3) Regularization
Regularization strength($\lambda$)를 곱해주는 것으로 각각 엘리먼트의 제곱 합의 값을 줄일 수 있음
- Regularization strength는 일종의 패널티 값으로 이해
- Regularization strength값이 커지면 underfitting 문제가 발생하여 accuracy가 떨어질 수 있음
4. Training, validation and test sets
1) Data set
모든 데이터를 모델 학습에 이용하여 값을 예측하는 것은 안좋은 방법
- 100% correct(accuracy) 이지만 모든것을 기억해야 하는 문제가 있음
전체 original data set을 training data set와 test data으로 나눔
- Training data set: 학습을 위한 data set
- Test data set: 학습을 위해서는 사용하지 않음, 예측값과 실제값을 비교하는 최후 모델의 평가를 위한 data set
Training data set을 다시 training data set과 validation data set으로 나누기도 함
- Training data set을 모의시험 하여 learning rate($\alpha$)와 regularization strength($\lambda$)값을 튜닝하기 위함
2) Online learning
- 데이터 셋을 분할하거나 지속적으로 데이터를 수집할 때 사용
이미 어떤 데이터를 통해 학습 시킨 모델을 계속해서 새로운 데이터로 학습시키며 점차 모델을 발전시키는 학습 형태
3) Accuracy
예측(실제데이터와 모델이 예측한 값의 비교)이 얼마나 정확한가를 의미
Example Code
1. Learning rate and Evaluation
학습에는 training data set을 model 테스트에는 test data set을 사용
소스코드
import tensorflow as tf # training dataset 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, 0], [0, 0, 1], [0, 0, 1], [0, 1, 0], [0, 1, 0], [0, 1, 0], [1, 0, 0], [1, 0, 0]] # test dataset 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("float", [None, 3]) Y = tf.placeholder("float", [None, 3]) W = tf.Variable(tf.random_normal([3, 3])) b = tf.Variable(tf.random_normal([3])) 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) ''' # big learning rate optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.5).minimize(cost) # small learning rate optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-10).minimize(cost) ''' # test model prediction = tf.argmax(hypothesis, 1) is_correct = tf.equal(prediction, tf.argmax(Y, 1)) accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32)) with tf.Session() as sess: sess.run(tf.global_variables_initializer()) for step in range(201): cost_val, W_val, _ = sess.run([cost, W, optimizer], feed_dict={X: x_data, Y: y_data}) print("step:{}, cost:{}, W:{}".format(step, cost_val, W_val)) print("\nPrediction: ", sess.run(prediction, feed_dict={X: x_test})) print("\nAccuracy: ", sess.run(accuracy, feed_dict={X: x_test, Y: y_test}))
결과
(...) step:198, cost:0.6307041645050049, W:[[-1.0179197 1.0029908 1.5980065 ] [ 0.5376595 0.3441221 0.3152033 ] [ 1.0510079 0.7980461 0.26807705]] step:199, cost:0.6298766732215881, W:[[-1.0219159 1.0022653 1.6027282 ] [ 0.5378086 0.3443701 0.31480628] [ 1.0524209 0.7982381 0.26647204]] step:200, cost:0.6290534734725952, W:[[-1.0259045 1.001546 1.6074361 ] [ 0.53795606 0.34461716 0.3144118 ] [ 1.0538331 0.79842794 0.26487 ]] Prediction: [2 2 2] Accuracy: 1.0
1) Big learning rate: overshooting
Big learning rate 지정 소스 코드: learning rate를 1.5로 지정
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1.5).minimize(cost)
결과: 학습이 되지 않고 발산이 됨
step:0, cost:6.2002129554748535, W:[[-1.9641786 1.2899761 -1.3891757 ] [ 1.1825768 1.8974146 -4.0632467 ] [ 0.84914625 0.9796692 -4.0303288 ]] step:1, cost:10.956174850463867, W:[[-1.594028 0.5448255 -1.0141757] [ 3.6063232 -1.651332 -2.9382467] [ 3.2675161 -2.5637007 -2.9053288]] step:2, cost:nan, W:[[nan nan nan] [nan nan nan] [nan nan nan]] step:3, cost:nan, W:[[nan nan nan] [nan nan nan] [nan nan nan]] (...) Prediction: [0 0 0] Accuracy: 0.0
2) Small learning rate
Small learning rate 지정 소스 코드: learning rate를 1e-10으로 지정
optimizer = tf.train.GradientDescentOptimizer(learning_rate=1e-10).minimize(cost)
결과: 학습이 느리게 진행됨, local minimize에서 벗어나지 못함, 예측 정확도가 낮음
step:0, cost:9.160271644592285, W:[[-1.569604 0.8670777 1.6502079 ] [ 1.7600275 0.34616604 -1.6269072 ] [ 0.91174084 -1.7635736 -0.40749222]] step:1, cost:9.160271644592285, W:[[-1.569604 0.8670777 1.6502079 ] [ 1.7600275 0.34616604 -1.6269072 ] [ 0.91174084 -1.7635736 -0.40749222]] (...) step:199, cost:9.160271644592285, W:[[-1.569604 0.8670777 1.6502079 ] [ 1.7600275 0.34616604 -1.6269072 ] [ 0.91174084 -1.7635736 -0.40749222]] step:200, cost:9.160271644592285, W:[[-1.569604 0.8670777 1.6502079 ] [ 1.7600275 0.34616604 -1.6269072 ] [ 0.91174084 -1.7635736 -0.40749222]] Prediction: [1 2 0] Accuracy: 0.33333334
2. Non-normalized input
1) Non-normalized input
소스코드
import tensorflow as tf import numpy as np ''' def MinMaxScaler(data): numerator = data - np.min(data, 0) denominator = np.max(data, 0) - np.min(data, 0) # noise term prevents the zero division 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]]) ''' print(xy) xy = MinMaxScaler(xy) print("\n>> Normalized input\n", xy) ''' x_data = xy[:, 0:-1] y_data = xy[:, [-1]] X = tf.placeholder(tf.float32, shape=[None, 4]) Y = tf.placeholder(tf.float32, shape=[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=1e-5) train = optimizer.minimize(cost) sess = tf.Session() sess.run(tf.global_variables_initializer()) for step in range(101): cost_val, hy_val, _ = sess.run([cost, hypothesis, train], feed_dict={X: x_data, Y: y_data}) print("Step: {}, \tCost: {}, Prediction: {}".format(step, cost_val, hy_val))
결과
(...) Step: 5, Cost: inf, Prediction: [[inf] [inf] [inf] [inf] [inf] [inf] [inf] [inf]] Step: 6, Cost: nan, Prediction: [[nan] [nan] [nan] [nan] [nan] [nan] [nan] [nan]] (...)
NaN이 출력된 이유: 각 데이터의 값이 심하게 차이가 나서 생기는 문제, 즉 normalization 되지 않아서 생기는 문제
2) Normalization input
Normalization input Data
def MinMaxScaler(data): numerator = data - np.min(data, 0) denominator = np.max(data, 0) - np.min(data, 0) # noise term prevents the zero division 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]]) print(xy) xy = MinMaxScaler(xy) print("\n>> Normalized input\n", xy)
Normalized input data
[[8.28659973e+02 8.33450012e+02 9.08100000e+05 8.28349976e+02 8.31659973e+02] [8.23020020e+02 8.28070007e+02 1.82810000e+06 8.21655029e+02 8.28070007e+02] [8.19929993e+02 8.24400024e+02 1.43810000e+06 8.18979980e+02 8.24159973e+02] [8.16000000e+02 8.20958984e+02 1.00810000e+06 8.15489990e+02 8.19239990e+02] [8.19359985e+02 8.23000000e+02 1.18810000e+06 8.18469971e+02 8.18979980e+02] [8.19000000e+02 8.23000000e+02 1.19810000e+06 8.16000000e+02 8.20450012e+02] [8.11700012e+02 8.15250000e+02 1.09810000e+06 8.09780029e+02 8.13669983e+02] [8.09510010e+02 8.16659973e+02 1.39810000e+06 8.04539978e+02 8.09559998e+02]] >> Normalized input [[0.99999999 0.99999999 0. 1. 1. ] [0.70548491 0.70439552 1. 0.71881782 0.83755791] [0.54412549 0.50274824 0.57608696 0.606468 0.6606331 ] [0.33890353 0.31368023 0.10869565 0.45989134 0.43800918] [0.51436 0.42582389 0.30434783 0.58504805 0.42624401] [0.49556179 0.42582389 0.31521739 0.48131134 0.49276137] [0.11436064 0. 0.20652174 0.22007776 0.18597238] [0. 0.07747099 0.5326087 0. 0. ]]
결과: 소스코드에서 normalization하는 주석 부분을 제거하고 실행해야 함
(...) Step: 100, Cost: 1.0541142225265503, Prediction: [[-0.1801064 ] [ 0.01909077] [-0.29041588] [-0.67692447] [-0.43428123] [-0.595112 ] [-0.87752855] [-1.0806464 ]]