Early Stopping 및 Index Shuffling


그런데 실제로 Deep Learning을 학습할 때에는 우리가 정한 횟수만큼의 iteration을 무조건 반복하는 것이 아니라, 적당히 학습이 완료되었다고 생각되면 학습을 중단하는 Early Stopping을 해야한다. 이것을 하지 않고 무조건 정해진 iteration을 하게되면, 모델이 주어진 데이터에만 과도하게 학습하여, 보지않은 데이터에 대한 일반화 성능이 떨어지는 overfitting이 일어나게 된다. 따라서 Early Stopping을 통해 이러한 일이 일어나기 전에 학습을 중단해야 한다.

또한 위의 MNIST 데이터는 이미 구현된 함수를 통해 미리 순서가 뒤섞이고, one-hot coding이 된 데이터를 필요한 개수만큼 가져올 수 있었다. 그러나 실제로 자신의 데이터를 학습시키기 위해서는 이러한 과정도 파이썬의 numpy를 이용해 구현해 주어야한다.

그래서 이번 예제에서는 아주 간단하면서 유명한 Iris 데이터를 이용해 위의 구현을 실습해보도록 한다.

Iris data : 50개*3종의 iris 꽃에서 4종류의 feature를 추출한 데이터

https://en.wikipedia.org/wiki/Iris_flower_data_set

%matplotlib inline
import tensorflow as tf
from tensorflow.contrib.learn.python.learn.datasets.base import load_iris
import numpy as np
tf.reset_default_graph()

def MLP_iris():
    # load the iris data.
    iris = load_iris()

    np.random.seed(0)
    random_index = np.random.permutation(150)

    iris_data = iris.data[random_index]
    iris_target = iris.target[random_index]
    iris_target_onehot = np.zeros((150, 3))
    iris_target_onehot[np.arange(150), iris_target] = 1

    accuracy_list = []
    
    # build computation graph
    x = tf.placeholder("float", shape=[None, 4], name = 'x')
    y_target = tf.placeholder("float", shape=[None, 3], name = 'y_target')

    W1 = tf.Variable(tf.zeros([4, 128]), name = 'W1')
    b1 = tf.Variable(tf.zeros([128]), name = 'b1')
    h1 = tf.sigmoid(tf.matmul(x, W1) + b1, name = 'h1')

    W2 = tf.Variable(tf.zeros([128, 3]), name = 'W2')
    b2 = tf.Variable(tf.zeros([3]), name = 'b2')
    y = tf.nn.softmax(tf.matmul(h1, W2) + b2, name = 'y')

    cross_entropy = -tf.reduce_sum(y_target*tf.log(y), name = 'cross_entropy')

    train_step = tf.train.GradientDescentOptimizer(0.01).minimize(cross_entropy)

    correct_prediction = tf.equal(tf.argmax(y, 1), tf.argmax(y_target, 1))

    accuracy = tf.reduce_mean(tf.cast(correct_prediction, "float")) 

    sess = tf.Session(config=tf.ConfigProto(gpu_options=tf.GPUOptions(allow_growth=True)))
    sess.run(tf.initialize_all_variables())

    for i in range(500):
        sess.run(train_step, feed_dict={x: iris_data[0:100], y_target: iris_target_onehot[0:100]})

        train_accuracy = sess.run(accuracy, feed_dict={x: iris_data[0:100], y_target: iris_target_onehot[0:100]})
        validation_accuracy = sess.run(accuracy, feed_dict={x: iris_data[100:], y_target: iris_target_onehot[100:]})
        print ("step %d, training accuracy: %.3f / validation accuracy: %.3f" %(i, train_accuracy, validation_accuracy))

        accuracy_list.append(validation_accuracy)
        
        if i >= 50:
            if validation_accuracy - np.mean(accuracy_list[int(round(len(accuracy_list)/2)):]) <= 0.01 :
                break
            
    sess.close()

MLP_iris()

핵심 코드는 아래와 같다.
1,2 번 째의 validation accuracy 값은 제거하고 너무 큰 값이기 때문이
그 이후부터의 값을 누적 시켜서 평균을 계산하게 된다.
그 다음 해당 값이 현재의 validation accuracy와의 차이를 구해서 그 차이가 0.01보다 큰지 작은지를 반단해서
break 여부를 결정하게 된다.

if i >= 50:
	if validation_accuracy - np.mean(accuracy_list[int(round(len(accuracy_list)/2)):]) <= 0.01 :
	    break

실행 결과를 보면 어느정도 동작하다가 멈추는 것을알 수 있다.

step 166, training accuracy: 0.970 / validation accuracy: 0.960
step 167, training accuracy: 0.970 / validation accuracy: 0.960
step 168, training accuracy: 0.970 / validation accuracy: 0.960
step 169, training accuracy: 0.970 / validation accuracy: 0.960
step 170, training accuracy: 0.970 / validation accuracy: 0.960
step 171, training accuracy: 0.970 / validation accuracy: 0.960


+ Recent posts