TensorFlow 무작정 따라하기 2 : Getting Started With TensorFlow

이 글에서 쓸 예제는 TensorFlow 무작정 따라하기 1에서 참조한 글의 가장 아랫 부분에 있는 내용이다. 하지만 그 내용이 조금 어렵게 느껴질 수도 있는 것 같아 글을 나누어서 작성했다. 또한 글이 너무 길어지는 것을 방지하기 위한 목적도 있다.

TensorFlow 무작정 따라하기 1에서 우리는 y = Wx + b 라는 모델을 작성한 후에, Gradient Descent 알고리즘을 이용하여 W 와 b를 알아내었다. 사실 이 모델은 Linear Regression  이라는 모델인데, TensorFlow가 제공하는 함수에 포함되어 있는 모델이다. TensorFlow는 이처럼 이미다양한 종류의 모델을 미리 함수로 제공하고 있다. 이 글에서는 TensorFlow 무작정 따라하기 1와 똑같은 내용을 TensorFlow에서 제공하는 함수를 이용하여 조금 더 간편하게 작성하는 것을 목적으로 한다.

전체 코드를 보면서 설명하겠다.
import tensorflow as tf# NumPy 는 수학 계산을 python에서 쉽게 할 수 있게 만든 라이브러리이다.
import numpy as np
# feature 리스트를 선언한다. 우리가 사용할 feature는 1개이다.
features = [tf.contrib.layers.real_valued_column("x", dimension=1)]
# estimator는 데이터를 통해 머신러닝을 실행한 후 결과를 평가하는데 쓰인다.
# LinearRegression 뿐만 아니라 더 많은 함수도 제공한다.
estimator = tf.contrib.learn.LinearRegressor(feature_columns=features, model_dir = "폴더경로")
# TensorFlow는 데이터를 설정하고 읽기 위한 많은 함수를 제공한다.
# 여기서는 머신러닝을 위한 훈련용 데이터(train)와 평가용 데이터(eval)가 있다.
# batch의 수와 크기를 함께 설정한다.
x_train = np.array([1., 2., 3., 4.])
y_train = np.array([0., -1., -2., -3.])
x_eval = np.array([2., 5., 8., 1.])
y_eval = np.array([-1.01, -4.1, -7, 0.])
train_input_fn = tf.contrib.learn.io.numpy_input_fn({"x":x_train}, y_train,
                                              batch_size=2,
                                              num_epochs=1000)

eval_input_fn = tf.contrib.learn.io.numpy_input_fn(
    {"x":x_eval}, y_eval, batch_size=2, num_epochs=1000)
# 1000번 함수를 반복 실행하며 훈련용 데이터를 전송한다.
estimator.fit(input_fn=train_input_fn, steps=500)
# Here we evaluate how well our model did.
train_loss = estimator.evaluate(input_fn=train_input_fn)
eval_loss = estimator.evaluate(input_fn=eval_input_fn)
print("train loss: %r"% train_loss)
print("eval loss: %r"% eval_loss)
(파란 부분은 설명을 위해 원본 코드에서 수정된 부분이다.)

featrue는 모델에 들어갈 데이터의 특징이다.
예를 들어, 집의 가격을 구하는 모델을 다음처럼 정한다고 하자.

Y  = 집의 가격
X1 = 집의 크기
X2 = 방의 개수
X3 = 화장실 개수

Y = W1X1 + W2X2 + W3X
위 식에서 X는 feature이고 W는 각 feature의 가중치이다.
따라서 feature는 3개이다.

estimator = tf.contrib.learn.LinearRegressor(feature_columns=features, model_dir = "폴더경로")
moder_dir 는 원본 코드에서는 없는 파라미터이다. 실제로 저 파라미터를 지우고 실행시켜보면 오류가 나서 실행이 되지 않는다. 모델을 이용해 계산을 하면 그 output이 생길 폴더가 지정되어 있어야하는데, 원본 코드에서는 model_dir이 없는 것으로 보아 환경설정 등으로 지정할 수 있을 것으로 추측이 된다. 하지만 지금은 그 방법을 모르기 때문에 저렇게 model_dir 파라미터에 output이 생길 폴더의 경로를 지정해주어야한다.

만약 소스코드가 C:\Users\SJHong\Documents에 있다고 하자. 그리고 output 폴더도 Documents 폴더에 지정하기를 원한다면, model_dir = "../Output" 과 같이 상대경로로 간단하게 지정할 수 있다.

train_input_in 에서  batch란, 한 번에 계산할 데이터의 양을 의미한다.
만약 데이터의 개수가 10만개라고 하자. 그런데 10만개의 데이터를 하나의 행렬로 만들어서 계산을 하기는 힘들 것이다. 따라서 한 번에 계산할 데이터들을  batch 라고 하며 그 데이터들의 수를 batch size라고 한다.

num_epoch는 batch가 데이터 전체를 다 도는 횟수의 제한을 의미한다. 예를 들어서, 전체 데이터 개수가 1천개이고 batch_size=10 일 때, batch는 100번을 돈다. 그런데 위 예제 코드에서 데이터 개수는 4개이고 batch_size=2 이므로, batch가 두 번 돌 때 마다 전체 데이터를 다 돌게 되므로 두 번 함수를 실행할 때마다 epoch도 1 증가한다. 따라서 위 함수 조건에서는 최대 2000번까지 함수가 실행될 수 있다. (2 x 1000 = 2000)

estimator.fit(input_fn=train_input_fn, steps=500)
steps는 함수가 최대 몇 번 실행될지를 의미한다.  steps=1 이면 함수를 한 번 실행한다는 뜻인데, num_epochs=1000 이라고해서 함수가 실행될 때마다 전체 데이터를 1000번 돈다는 뜻이 아니다. 함수를 한 번 실행하면 batch도 한 번 돈다.

다시 예시를 들어서 전체 데이터 개수를 1000개라고 하고 batch_size=10 이라고 하자. 1 epoch를 충족시키기 위해서는 batch가 100번 돌아야한다. 즉, 함수를 100번 실행시켜야 한다. steps=100 이어야한다는 말이다.

그렇다면 위 코드에서 steps=500이고, num_epochs=1000 이니까, batch는 500 x 1000 = 50만번 실행된다는 뜻일까? 아니다. steps와 num_epochs는 서로 독립적인 조건이라고 할 수 있다. 둘 다 충족해야만 함수 실행이 끝나는게 아니라, 둘 중 하나만 충족되면 함수 실행이 완료되는 것이다.

즉, steps=500 이니까 함수를 500번 실행하거나 혹은num_epchos=1000이니까 전체 데이터를 1000번 돌리는 것 중 하나의 조건이 먼저 충족되면 함수 실행이 종료된다.

그렇다면 위 코드에서 함수는 몇 번 실행되는 것일까?

1. step 조건
함수는 500번까지만 실행할 수 있다.

2. epoch 조건
전체 데이터는 1000번 돌 수 있다. 즉, 함수가 2000번 실행될 수 있다. (4/2 * 1000 = 2000)

2번 조건이 충족되기 전에 1번 조건이 충족되므로 함수는 1번 조건에 의해 종료된다.
따라서 위 코드에서 함수는 500번만 실행하고 끝난다.

step 과 epoch의 개념이 너무 헷갈려서 아래 링크의 글을 참조했다. 만약 내 글이 이해가 안 되는 사람은 아래 링크에서 이해하기 바란다.
https://stackoverflow.com/questions/42816124/steps-vs-num-epochs-in-tensorflow-getting-started-tutorial

또는 실제로 위 코드에서 step과 epoch의 수를 달리하여 여러 번 테스트해보면 더 쉽게 알 수 있다.

estimator.fit(input_fn=train_input_fn, steps=500)
fit은 머신러닝에 사용한 모델에 사용자가 입력한 데이터를 이용하여 파라미터를 구하는 함수이다. fit을 하게 되면 y=Wx+b 라는 함수가 있을 때 W와 b를 구하게 된다.

train_loss = estimator.evaluate(input_fn=train_input_fn)
eval_loss = estimator.evaluate(input_fn=eval_input_fn)
estimator.evaluate의 input_fn 파라미터는 위에서 fit을 통해 W와 b를 알게 된
Linear Regression 모델과의 결과값 차이를 구하기 위한 파라미터이다.

모델의 파라미터(W, b)는 train 데이터를 이용해서 구했다.
train_loss 는 x_train을 다시 모델에 넣어 y를 구한 후 y_train과의 차이를 구한 것이고,
eval_loss 는 x_eval을 모델에 넣어 y를 구한 후 y_train과의 차이를 구한 것이다.

train_loss 는 당연히 train 데이터를 통해 훈련된 모델에 train 값을 다시 넣어 그 차이를 구한 것이기 때문에 오차가 작게 난다. 하지만 eval_loss 는 모델을 훈련시킬 때 사용하지 않은 데이터와의 차이를 구한 것이기 때문에 상대적으로 train_loss보다 큰 오차가 난다. 따라서 eval_loss가 작을수록 훈련이 잘 되었다고 평가할 수 있다.