조이 생각

반응형

( ※ 본 포스팅은 저자 개인의 한정적인 지식을 바탕으로 쓰여진 글입니다. 내용의 오류나, 오타 등을 언제든지 알려주시면 감사하겠습니다.)





이전 포스팅에서 보였던 코드를 보면서 머신러닝의 아주 기초적인 개념과 더불어

텐서플로우에서는 어떻게 코딩해야하고 작동하는지를 설명하려고 합니다.


실행환경


- OS : 윈도우7 (Windows 7 64bit)

- 아나콘다 (Anaconda 4.4.0 64-bit)


- 파이썬 (python 3.6.1)

- 텐서플로우 (TensorFlow 1.4.0)



텐서플로우(TensorFlow)는 신경망 구조(그래프)를 설계해 놓고 사용(실행) 하는 방법이며 데이터를 실행시 사용되는 데이터는 placeholder라는 개념을 사용하여 feed_dict로 값을 적용합니다. 


아주 간단하지만, 저도 처음에 그랬고(사실 지금도.. 어렵지만) 누군가에게는 어려울 수도 있다고 생각하기 때문에..

이번 포스팅이 많은 분들이 TensorFlow와 머신러닝을 시작하는데 도움이 되길 바라며 



저번 python 코드를 한줄 한줄 뜯어 보겠습니다.



# Parameters
learning_rate = 0.3
training_epochs = 500


위의 두 변수는 학습에 사용되는 값들로 사용자가 정해줍니다.

  • learning_rate : 최적화(optimizer)알고리즘에서 사용하는 변수

지도학습에서 신경망의 학습은 신경망이 예측한 값과 학습에 사용되는 정답을 비교해서 그 차이(cost, loss)를 구합니다.

그 차이가 작아지는 방향으로 학습에 사용되는 파라미터를 조절하는데,

이 때 얼마큼씩 조절해줄 것인가를 정해주는 것이 learning_rate가 적용됩니다.

  • training_epochs : 전체 데이터 학습 횟수

신경망 학습에서 epoch이라는 개념은 데이터가 100개 있다고 가정했을 때,

이 100개의 데이터 전체를 학습에 적용하는 횟수입니다.


이 코드에서 batch 개념을 사용하지 않았지만,

예를 들어 학습 설정이 아래와 같을때


- 데이터 (data row) : 100

- 배치 사이즈 (batch size) : 20


1 epoch = 5 batch 가 실행됩니다.




# real data
data = np.loadtxt('./data/train.csv', delimiter=',', dtype=str).astype(np.float32)
input = data[:,:-1]
output = data[:,-1].reshape([len(data),1])
features = input.shape[1]
 
test_data = np.loadtxt('./data/test.csv', delimiter=',', dtype=str).astype(np.float32)
test_data = test_data.reshape([-1, features]) # make uniform shape


구현된 신경망에 넣어줄 실제 데이터를 읽어오는 부분입니다.

이 부분은 구현한 신경망의 구조에 따라 직접 실행해보며 맞춰가야 합니다.



# placeholders for train
= tf.placeholder(tf.float32, shape=[None, features], name='x')
= tf.placeholder(tf.float32, shape=[None, 1], name='y')
 
# Set model weights
= tf.Variable(tf.random_normal([features, 1],dtype='float'), name='weight')
= tf.Variable(tf.random_normal([1],dtype='float'), name='bias')


앞서 말했던 placeholder

이 신경망의 값 예측 수식은 X*W + b (Y는 cost때 설명)

학습 수식에서 사용되는 형태를 미리 설계해놓는 것 입니다.


신경망을 미리 설계할 때 주의 할 점을 크게 두 가지로 (저의 생각..)

  1. 실제 데이터의 구조
  2. 학습 연산의 구조


tf.placeholder의 첫 파라미터(tf.float32)는 데이터의 타입이고 데이터 형태(shape)위주로 설명하겠습니다.

  • None : 데이터의 크기 제한이 없음 
  • feature : 실제 데이터를 가져올 때 입력데이터(input)의 열의 개수

X와 W는 행렬 곱을 할 수 있도록 데이터 형태를 맞춰줍니다. 

행렬 곱을 하기 위해서는 예) (a,m)(m,b) 가 충족되어야 하기 때문에...


그리고 이 신경망에서는 값 하나를 예측하기 때문에 W의 데이터 형태를 [feature, 1]로 했습니다.

b는 X*W의 결과 데이터 형태가 [1]일 것이기 때문에 + 연산을 위한 b의 데이터 형태도 맞췄습니다.


# Construct a linear model
hypothesis = tf.matmul(X, W) + b
= tf.identity(hypothesis, name='h')
 
# Mean squared error
cost = tf.reduce_mean(tf.square(hypothesis - Y))
 
# accuracy
acc = tf.equal(tf.round(hypothesis), Y)
acc = tf.reduce_mean(tf.cast(acc, tf.float32))
 
# Minimize
optimizer = tf.train.GradientDescentOptimizer(learning_rate=learning_rate)
train = optimizer.minimize(cost)


앞서 말한 예측 수식을 hypothesis 변수에 넣어주었고

h는 단순히 hypothesis 값을 사용하기 위해서 +b 까지 통틀어 name='h'에 지정하기 위함입니다.


(자바(java)에서 학습된 신경망을 사용하기 위해서는 원하는 연산에 name을 지정해주어야 합니다.

전에 했던 실수로는 tf.matmul 안에 name을 지정해서 java로 실행시켰는데

파이썬이랑 다른 결과가 나와서 애를 많이 먹었던 기억이...

여러분들은 저같은 실수를 범하지 않으시길 바랍니다.)


cost는 앞에서 지정한 Y와 hypothesis를 사용합니다.

  • hypothesis : 신경망이 예측한 값
  • Y : 실제 정답 값

여기서 이 두개의 차이에는 MSE(Mean Square Error) 식을 사용했습니다.

이 차이를 줄이는 최적화 알고리즘으로는 GD(Gradient Descent)를 사용했으며

앞에서 정해준 learning_rate를 여기서 적용합니다.


  • train : 구한 cost(loss)를 줄이는 minimize(cost) 연산으로 학습



# Launch the graph in a session.
sess = tf.Session()
# Initializes global variables in the graph.
sess.run(tf.global_variables_initializer())
 
for step in range(training_epochs):
    sess.run(train, feed_dict={X: input, Y: output})
    if(step%100==0):
        cost_val, hy_val = sess.run([cost, hypothesis], feed_dict={X: input, Y: output})
        if step==0:
            print("[",step+1,"] Cost:", cost_val)
        else:
            print("[",step,"] Cost:", cost_val)


여기서부터 진짜 학습이 시작됩니다.


tensorflow를 실행하기 위한 세션을 생성하고 run 메소드를 통해서 모든 변수를 초기화합니다.

혹시나 초기화를 모르시는 분들을 위해 설명하자면,

모든 변수의 값을 다 없애는 null, 0으로 만들어주는게 아니라

우리가 지정해준 초기 값들을 설정해 주는 정도로 생각하면 될 것 같습니다.


학습 실행 부분

    sess.run(train, feed_dict={X: input, Y: output})


위 코드에서 train 부분을 살펴보면

train 에서 cost를 사용하고,

cost에서 hypothesis와 Y를 사용하고,

hypothesis에서 W, X, b를 사용합니다.


여기서 placeholder로 지정해준 부분은 feed_dict 방법으로 값을 넣어주어야 합니다.

즉, train 을 실행하는데 사용되는 변수들 중에 placeholder가 있는 부분을 충족시켜 주어야한다고 볼 수 있습니다.


이 학습 과정을 반복문(for)으로 설정해준 training_epochs 만큼 반복해 줍니다.


print("=============TRAIN END==============")
for i in range(len(data)):
    hy_val = sess.run(hypothesis, feed_dict={X: input[i,:].reshape([1,features])})
    print(" Answer:", output[i], " Prediction:", round(hy_val[0,0]))
 
cost_val, acc_val = sess.run([cost,acc], feed_dict={X: input, Y: output})
print(" Cost:", cost)
print(" Acc:", acc_val)
 
print("=============PREDICT==============")
for i in range(test_data.shape[0]):
    pre = sess.run(hypothesis, feed_dict={X: test_data[i].reshape(1,features)})
    print(test_data[i],"==> ", pre[0])


TRAIN END 부분은 학습이 모두 끝난 모델의 오차(cost, loss)와 정확도(accuracy)를 확인하는 부분이고

PREDICT는 다른 데이터를 학습이 완료된 모델에 적용해 보는 부분입니다.

적용하고 싶은 데이터를 X에 feed_dict로 넣어 hypothesis를 실행해 주면,

신경망의 예측값을 얻을 수 있습니다.


여기서 X만 feed_dict 해주면 되는 이유는, hypothesis 연산에 사용되는 placeholder 변수가 X뿐인 것도 있지만,

학습을 하는게 아니기 때문에 정답 데이터 Y를 넣어줄 필요가 없기 때문입니다.



데이터와 소스코드 풀 버전은 아래 링크에 있습니다.

https://github.com/joyspark/TensorFlow




읽어주셔서 감사합니다. : )






반응형

이 글을 공유합시다

facebook twitter kakaoTalk kakaostory naver band
loading