2019. 6. 4. 19:55ㆍmachine learning
골빈 해커님이 쓰신 3분 딥러닝을 코드 위주로 설명한 포스팅.
4장 01에서는 2개의 특징 데이터(털, 날개)를 가지고 [기타, 포유류, 조류]를 분류하는 모델을 설명하고 있으며, 전체 코드는 아래와 같다.
step by step으로 하나씩 살펴보자.
import tensorflow as tf
import numpy as np
텐서플로우와 numpy를 import 하고 있다. 참고로 실행 환경에서의 텐서플로우와 numpy 버전은 각각 1.13.0, 1.16.3을 사용하였다.
x_data = np.array([[0, 0], [1, 0], [1, 1], [0, 0], [0, 0], [0, 1]])
y_data = np.array([ [1, 0, 0], # 기타
[0, 1, 0], # 포유류
[0, 0, 1], # 조류
[1, 0, 0], [1, 0, 0], [0, 0, 1] ])
X = tf.placeholder(tf.float32)
Y = tf.placeholder(tf.float32)
x와 y 데이터를 각각 선언하고, train 시에 x와 y 데이터를 담을 수 있는 placeholder도 선언한다.
x data는 [털, 날개] 여부를 가지는 2차원 데이터로 나타나고, y data는 [기타,포유류,조류]를 각각 one-hot encoding으로 표현하였다.
W = tf.Variable(tf.random_uniform([2, 3], -1., 1.))
b = tf.Variable(tf.zeros([3]))
weight와 bias를 선언한다. weight는 -1 ~ 1 사이의 정규분포를 가지는 2x3 행렬의 난수로 표현이 되고, bias는 1x3의 0값으로 초기화가 된다.
input data가 1x2 행렬이기 때문에 wx + y = [1x2] * [2x3] + [1x3] 으로 행렬 계산이 되고 최종 결과 값은 [1x3]의 행렬 값이 나타난다.
L = tf.add(tf.matmul(X, W), b)
L = tf.nn.relu(L)
model = tf.nn.softmax(L)
input data에 weight를 곱한 후 bias를 더한 식을 L로 정의하고, L에 대해 relu를 적용한다.
그리고 마지막으로 L에 대해 softmax를 적용한다. softmax는 간단히 설명하자면 각각의 가중치 데이터를 총 합이 1이 되게 확률값을 만들어 주는 기능을 한다.
cost = tf.reduce_mean(-tf.reduce_sum(Y * tf.log(model), axis=1))
모델을 정의 했다면 이번에는 cost 함수를 정의한다. cost 함수는 cross entropy로 정의한다. Y 값 * log(모델의 예측확률)의 전체 합이 cross entropy가 되며 마지막에 reduce_mean을 해주는 이유는 해당 함수가 batch size 입력을 받기 때문에 해당 batch에 대한 평균 loss를 구하기 위해 reduce_mean이 필요하다.
reduce_sum의 axis가 헷갈리는 부분인데, axis가 없는 경우는 전체 합, axis가 0일 경우에는 열단위 합, axis가 1일 경우에는 행단위 합을 진행한다고 생각하면 된다.
아래의 예를 보면, 이해가 쉽다.
x = [[0,1,2], [3,4,5]]
print(sess.run(tf.reduce_sum(x))) # 전체 계산 15
print(sess.run(tf.reduce_sum(x, axis=0))) # 열단위 계산 [3,5,7]
print(sess.run(tf.reduce_sum(x, axis=1))) # 행단위 계산 [3, 12]
optimizer = tf.train.GradientDescentOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(cost)
optimizer로 gradient descent optimizer를 사용하고 learning rate 를 0.01로 주자.
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
for step in range(100):
sess.run(train_op, feed_dict={X: x_data, Y: y_data})
if (step + 1) % 10 == 0:
print(step + 1, sess.run(cost, feed_dict={X: x_data, Y: y_data}))
이제 만들어진 모델을 학습해보자.
먼저 tf.global_variables_initializer()를 통해 기존 선언한 변수들에 대한 초기화를 진행하자.
session을 선언한 후 변수 초기화를 실행 시키자.
range 100만큼 돌면서 x_data와 y_data를 집어 넣어서 train_op를 실행시키자.
10 단위로 cost 함수를 실행시켜서 cross_entropy date를 출력해 보자.
prediction = tf.argmax(model, 1)
target = tf.argmax(Y, 1)
print('예측값:', sess.run(prediction, feed_dict={X: x_data}))
print('실제값:', sess.run(target, feed_dict={Y: y_data}))
is_correct = tf.equal(prediction, target)
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print('정확도: %.2f' % sess.run(accuracy * 100, feed_dict={X: x_data, Y: y_data}))
마지막으로 모델에 대한 성능 평가를 진행한다.
model에서 행단위로 가장 높은 값을 가지는 index를 리턴하는 함수를 prediction에 정의한다.
그리고 현재 y_data 중 가장 높은 값 (1인 데이터) 의 index 를 리턴하는 함수를 target에 정의한 후 각각 sess.run을 실행시켜서 결과를 확인해 보자.
출력해보면, 예측 값 : [2 2 2 2 2 2], 실제값 : [0 1 2 0 0 2] 로 나타나게 된다.
두 개의 리스트를 tf.equal을 통해 비교하자. 일치하면 True, 틀리면 False를 리턴하게 될 것이다. ex) [False, False, True, False, False, True]
True, False 리스트를 정수로 변환한 후 reduce_mean을 함으로써 평균을 구하자.
약 33%의 정확도를 확인해 볼 수가 있으며, 이 결과가 지금 현재의 모델 성능임을 확인해 볼 수가 있다.