Skip to content

기계학습 Evaluation, Normalization #
Find similar titles

Structured data

Category
Programming

Evaluation & Normalization #

Evaluation, Normalization는 분석의 마무리 단계에서 사용하며 그 의미를 보면 Evaluation은 평가, Normalization은 일반화이다. 특히 Normalization은 여러 가지로 번역되는데 일반화 외에도 정규화, 표준화라고도 한다. 여기서는 일반화라고 칭하여 사용하였다. 참고로 일반화, 정규화, 표준화는 주요 기능은 같은데 사용하는 분야가 다른 용어이며 세부적인 내용은 다음을 참고한다.

  • 일반화(Generalization) : 통계에서 주로 사용하는 단어
  • 정규화(Regularization) : 제약을 건다는 의미로 필터링을 통해 오류 값을 줄인다는 의미
  • 표준화(Standardization) : 각 속성의 분포, 간격 등으로 만드는 공식을 의미

Evaluation & Normalization Meaning #

평가는 정확도와 비슷한 개념으로, 머신러닝으로 만든 모델이 얼마나 훈련 데이터를 맞추었는지를 보는 것으로 대체로 90%, 55%, 78% 등의 수치로 나타낸다. 여기서 90%는 훈련용 데이터를 90%의 정확도로 분석했다는 의미이다.

일반화는 데이터에 이상값이나 결측값을 제거 또는 대치하여 균등하게 맞추는 작업이다. 수많은 데이터를 비교 분석하는 과정에서 어떤 값은 관측되지 않아 빈 값이 들어갈 수도 있고, 반대로 허용범위를 넘어가는 너무 큰 값이 있을 수도 있고, 비교 값마다 단위가 달라 같이 분석할 시 오류가 날 수도 있기 때문이다.

Evaluation : Confusion Matrix #

평가 단계는 머신러닝에 있어 중요한 단계이다. 단순히 얼마나 많이 정답과 맞추었느냐만 중요한 것이 아니며 그 밖에도 다양한 평가 측도가 있다. 이를 위해 혼돈 행렬(Confusion Matrix)라는 테이블을 사용하여 정확성의 지표를 계산한다.

Desease Classifier

이미지 출처 : Data School

예를 들어 병원에서 환자들의 질병을 예측한다고 할 때 병이 있는 환자는 Y, 병이 없는 환자는 N이라고 할 수 있다. 위 테이블을 보면 총 165명의 환자를 조사했으며 병이 있다고 예측한 환자는 총 110명, 반대로 병이 없다고 예측한 환자는 55명으로 대략 환자의 2/3 정도가 병을 가지고 있다고 생각할 수 있다. 그리고 조사한 환자들 중 실제로 병이 없는 환자는 60, 실제로 병이 있는 환자는 105이다. 각각 5명의 오차가 생긴 것이다.

  • TP(True Positives) : 질병이 있다고 예측한 환자 중 실제로 질병이 있는 환자 수
  • FN(False Negative) : 질병이 없다고 예측한 환자 중 실제로 질병이 있는 환자 수
  • TN(True Negative) : 질병이 없다고 예측한 환중 중 실제로 질병이 없는 환자 수
  • FP(False Positive) : 질병이 있다고 예측한 환자 중 실제로 질병이 없는 환자 수

Confusion Matrix

이미지 출처 : Data School

위에서 가정한 테이블을 통해 혼돈 행렬을 만들어 보았다. 이 테이블을 통해 정확도, 오류율, 민감도, 재현도, 특이도 등을 계산할 수 있다. 정확한 내용은 다음 사항을 참고한다.

  • Accuracy 정확도 : (TP+TN)/Total, 올바르게 검출 (실제 악성/정상을 예측)
  • Misclassification Rate, Error Rate 오류율 : (FP+FN)/Total, 잘못되게 검출 (잘못된 악성/정상 예측)
  • Precision 정밀도 : TP/Predicted YES, 참으로 분류한 것 중 올바른 참의 비율 (악성으로 예측한 것 중 실제 악성 샘플의 비율)
  • Recall, Detection Rate 재현율, 검출률 : TP/Actual YES, 실제 참을 참으로 분류 (실제 악성 중에서 악성으로 예측
  • False Alarm 오검출률, 오경보율 : FP/Actual NO, 실제 거짓을 거짓으로 분류 (실제 정상 중에서 악성으로 예측
  • TPR(True Positive Rate),Recall, Sensitivity 적중확률, 민감도 : TP/Actual YES, 예측과 실제 모두 참 (실제 악성 중에서 악성으로 예측)
  • TNR(True Negative Tate), Specificity 특이도 : TN/Actual NO, 예측과 실제 모두 거짓 (실제 정상 중에서 정상으로 예측)
  • FPR(False Positive Rate) False Alarm : FP/Actual NO, 실제 거짓인데 참으로 분류 (실제 정상을 악성으로 예측)
  • (FNR False Negative Rate) : FN/Actual YES, 실제 참인데 거짓으로 검출 (실제 악성을 정상으로 예측)

Evaluation : Precision, Accurancy #

recision, Accuracy라는 단어 둘 다 정확하다는 의미를 담고 있어 일반적으로 이 둘을 명확하게 구분하기는 쉽지 않다. 하지만 머신러닝이나 통계에서는 이 둘을 문맥에 따라 구분하여 사용한다. Precision은 정밀도를 의미하고, Accuracy 정확도를 의미한다.

예를 들어 5분 느리게 작동하는 시계가 있는데 1시간 뒤에도, 1일 뒤에도, 심지어 1년 뒤에도 동일하게 5분 느리다면 이 시계는 정밀하지만 정확하지 않다고 할 수 있다. 그리고 기상 예보를 보면 예보와 실제 기상이 맞는다면 그 예보는 정확하다라고 할 수 있다. 그리고 예보를 위해 같은 기상 자료를 분석하는데 어제, 오늘, 내일 분석하여 그 기상예보의 예측 내용이 같다면 정밀한 모델이라고 할 수 있다.

  • 정밀도(Precision) : 출력결과가 얼마나 참에 가까운지를 나타냄(참값과의 거리)
  • 정확도(Accuracy) : 시스템이 얼마나 일관된 값을 출력하는지 나타냄(반복에 따른 차이)

Implement : Precision #

일반적인 예제를 실습하여 정확도 개념을 알아보자

Implement 1 - Set Data #

학습한 모델이 얼마나 정확한지 평가하기 위해 주어진 데이터를 훈련용과 평가용으로 나누어서 작업한다.

# training data
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]]

# Evaluation data
x_test = [[2,1,1],[3,1,2],[3,3,4]]
y_test = [[0,0,1],[0,0,1],[0,0,1]]
  • y_data는 실제값을 의미
  • 여러개의 값이 있을 수 있기 때문에 형렬 형식으로 나타냄
  • one-hot 인코딩 방식이라고 하며 특정 수만 1로, 나머지는 0으로 표현
  • 예> [0,1,2] 중 실제값이 1이라고 하면 [0,1,0]으로 나타냄

Implement 2 - Set Variables #

분석에 사용할 입력 변수를 설정한다.

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]))
  • [None, 3]은 행과 열의 숫자를 의미
  • None은 행은 정하지 않고 자동으로 입력, 3는 3열을 의미
  • W는 가중치(Weight), b는 증가값(Bias)을 의미
  • 행과 열의 개수를 맞추는 것에 주의
  • X는 [8X3], Y는 [8X3] 이므로 X에 [3X3]행렬을 곱해야 Y행렬의 형태 [8X3]가 됨

Implement 3 - Set Hypothesis #

정의한 변수들을 통해 SoftMax 함수식을 작성한다. 그리고 Cost값을 명시한 후 최적화 방법을 지정한다.

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)
  • hypothesis 가설이며 예측값을 의미
  • cost는 예측값과 실제값의 차이를 의미
  • cost 함수는 저번 시간의 cost 공식을 code로 표현
  • 최적화는 GradientDescentOptimizer함수를 사용

Implement 4 - Prediction #

계산된 값들의 정확도를 측정하기 위한 기능을 추가한다.

# Correct Prediction Test model
prediction = tf.arg_max(hypothesis, 1)
is_correct = tf.equal(prediction, tf.arg_max(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
  • prediction : 어떤 갑을 예측하였는지 확인
  • is_correct : 예측한 값이 맞았는지, 틀렸는지 확인하여 맞으면 1, 틀리면 0으로 표시
  • accuracy : is_correct의 평균을 계산하여 100% 정확하면 1, 전부 다 틀릴 경우 0으로 표시. 대체로 0과 1 사이 값으로 0.95, 0.73 등으로 표시

Implement 5 - Train & modeling #

반복해서 훈련을 시행하며 그래프로 그리기 위해 200번째 계산마다 계산 값들을 출력한다.

# Launch Graph
with tf.Session() as sess:
    sess.run(tf.global_variables_initializer())
    feed = {X:x_data, Y:y_data}

    for step in range(2001):

        if step % 200 == 0:

            pre_val = sess.run(prediction, feed_dict={X:x_data})
            cost_val, w_val, hy_val, cor_val, acc_val, _ = sess.run([cost, W, hypothesis, is_correct, accuracy, optimizer], feed_dict=feed)

            print("-> step{:4}  cost: {:.2f}  \033[1maccuracy: {:.2f}%\033[0m / First_ hypothesis: {:.2f}  Preficted: {:1}  \033[1mCurrect: {}\033[0m" 
                  .format(step, cost_val, acc_val*100, hy_val[0][0], pre_val[0], cor_val[0]))

    feed_test = {X:x_test, Y:y_test}   # use Test Data
    pre_val = sess.run(prediction, feed_dict=feed_test)
    acc_val, cur_val = sess.run([accuracy, is_correct], feed_dict=feed_test)

    print("->  \033[1maccuracy: {:.2f}%\033[0m  Preficted: {}  Currect: {}" 
                  .format( acc_val*100,  pre_val, cur_val ))

Train_Result

결과 이미지

  • 훈련하고서 평가할 때는 test 데이터를 사용
  • 해당 예제에서는 정확도가 낮게 나오는데 Learning Rate 값을 조절 필요

Implement 6 - Increase Learning Rate #

정확도를 높이기 위해 Learning Rate 비율을 10으로 증가시킨다.

optimizer = tf.train.GradientDescentOptimizer(learning_rate=10).minimize(cost)
# Launch Graph
with tf.Session() as sess:
sess.run(tf.global_variables_initializer())
feed = {X:x_data, Y:y_data}

for step in range(2001):

    if step % 200 == 0:

        pre_val = sess.run(prediction, feed_dict={X:x_data})
        cost_val, w_val, hy_val, cor_val, acc_val, _ = sess.run([cost, W, hypothesis, is_correct, accuracy, optimizer], feed_dict=feed)

        print("-> step{:4}  cost: {:.2f}  \033[1maccuracy: {:.2f}%\033[0m / First_ hypothesis: {:.2f}  Preficted: {:1}  \033[1mCurrect: {}\033[0m" 
              .format(step, cost_val, acc_val*100, hy_val[0][0], pre_val[0], cor_val[0]))

feed_test = {X:x_test, Y:y_test}   # use Test Data
pre_val = sess.run(prediction, feed_dict=feed_test)
acc_val, cur_val = sess.run([accuracy, is_correct], feed_dict=feed_test)

print("->  \033[1maccuracy: {:.2f}%\033[0m  Preficted: {}  Currect: {}" 
              .format( acc_val*100,  pre_val, cur_val ))

Increase_Result

결과 이미지

  • learning_rate를 10으로 높혔더니 hypothesis값이 Nan으로 나옴
  • 최적화가 되지 않고 값이 발산
  • 이후 테스트 진행 불가

Implement 7 - Decrease Learning Rate #

이번에는 반대로 Learning Rate 비율을 0.00001로 감소시킨다.

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

# Launch Graph

with tf.Session() as sess: sess.run(tf.global_variables_initializer()) feed = {X:x_data, Y:y_data}

for step in range(2001):

    if step % 200 == 0:

        pre_val = sess.run(prediction, feed_dict={X:x_data})
        cost_val, w_val, hy_val, cor_val, acc_val, _ = sess.run([cost, W, hypothesis, is_correct, accuracy, optimizer], feed_dict=feed)

        print("-> step{:4}  cost: {:.2f}  \033[1maccuracy: {:.2f}%\033[0m / First_ hypothesis: {:.8f}  Preficted: {:1}  \033[1mCurrect: {}\033[0m" 
              .format(step, cost_val, acc_val*100, hy_val[0][0], pre_val[0], cor_val[0]))

feed_test = {X:x_test, Y:y_test}   # use Test Data
pre_val = sess.run(prediction, feed_dict=feed_test)
acc_val, cur_val = sess.run([accuracy, is_correct], feed_dict=feed_test)

print("->  \033[1maccuracy: {:.2f}%\033[0m  Preficted: {}  Currect: {}" 
              .format( acc_val*100,  pre_val, cur_val ))

Decrease_Result

결과 이미지

  • learning_rate를 0.00001으로 낮추면 hypothesis 변화가 거의 없음
  • 너무 조금만 변해서 최적화 작업이 진행되지 않음

Implement : Normalization #

일반적인 예제를 실습하여 일반화 개념들 알아보자

Implement 1 - Non-normalized Inputs #

학습이 정상적으로 이루어져도 값이 비정상적으로 출력되거나 None 값이 나올 수 있다. 주로 데이터가 일반화되지 않을 때 발생한다. 차이가 큰 데이터를 설정하여 실습해본다.

import numpy as np
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]])

Implement 2 - Set Variables #

분석에 사용할 입력 변수를 설정한다.

x_data2 = xy[:, 0:-1]
y_data2 = xy[:, [-1]]
X2 = tf.placeholder("float", [None, 4])
Y2 = tf.placeholder("float", [None, 1])
W2 = tf.Variable(tf.random_normal([4, 1]), name="weight")
b2 = tf.Variable(tf.random_normal([1]), name="bias")

Implement 3 - Set Hypothesis #

단순히 행렬끼리의 곱으로 가설을 설정한다. 최적화는 GradientDescentOptimizer를 사용한다.

hypothesis2 = tf.matmul(X2, W2) + b2
cost2 = tf.reduce_mean(tf.square(hypothesis2 - Y2))
optimizer2 = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
train2 = optimizer2.minimize(cost2)

Implement 4 - Train & modeling #

반복해서 훈련을 실시하며 그래프로 그리기 위해 200번째 계산마다 계산 값들을 저장한다.

sess = tf.Session()
sess.run(tf.global_variables_initializer())
for step in range(2001):

if step % 200 == 0:
    cost_val, hy_val, _ = sess.run([cost2, hypothesis2, train2], feed_dict={X2:x_data2, Y2:y_data2})

    print("step{:5}  cost: {:.2f}  predicted: {}...". format(step, cost_val,  hy_val.flatten()[:3]))

Implement 5 - Non-normalized Result #

결과값을 보면 일반화되지 않아 계산되지 않는 문제가 발생했다. 출력결과를 보면 Non으로 뜨는 것을 확인할 수 있다.

Non Result

비일반화 훈련 결과

Implement 6 - Normalized input : Min-max Scaler #

예제에서 입력값들을 보다 균일하게 맞추기 위한 작업이 필요하다. 주로 min-max scaler를 사용한다. 사용결과 데이터들이 0과 1 사이의 일정한 비율로 변환된 것을 확인할 수 있다.

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

return numerator / (denominator + 1e-7)

xy = MinMaxScaler(xy)
xy

MinMax

일반화를 위해 MinMaxScaler 함수 사용 결과

Implement 7 - Modeling #

이후 이전 과정과 같이 모델을 설정하여 훈련한다.

x_data3 = xy[:, 0:-1]
y_data3 = xy[:, [-1]]
X3 = tf.placeholder("float", [None, 4])
Y3 = tf.placeholder("float", [None, 1])
W3 = tf.Variable(tf.random_normal([4, 1]), name="weight")
b3 = tf.Variable(tf.random_normal([1]), name="bias")

hypothesis3 = tf.matmul(X3, W3) + b3
cost3 = tf.reduce_mean(tf.square(hypothesis3 - Y3))
optimizer3 = tf.train.GradientDescentOptimizer(learning_rate=1e-5)
train3 = optimizer3.minimize(cost3)

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

for step in range(2001):

if step % 200 == 0:
    cost_val, hy_val, _ = sess.run([cost3, hypothesis3, train3], feed_dict={X3:x_data3, Y3:y_data3})

    print("step{:5}  cost: {:.3f}  predicted: {}...". format(step, cost_val, hy_val.flatten()[:3]))

Implement 8 - Normalized Result #

일반화를 적용한 결과 이전에는 계산되지 않았던 데이터가 정상적으로 계산 된 것을 확인할 수 있다.

Normalizaion_Resutl

일반화를 적용한 계산 결과

참고 링크 #

0.0.1_20140628_0