한 페이지 머신러닝

Tensorflow로 인공신경망을 만든다는 것

[CODE] https://goo.gl/1wAbJ5

인공신경망 만들기

텐서플로우로 인공신경망을 설계한다는 것은, 여러 모양의 파이프로 배수관을 설계하는 것과 같습니다.
어떤 목적으로 어떤 종류의 인공신경망을 만들든 간에, 다음 세 가지 절차를 따르게 됩니다.

1. 데이터(물)를 준비합니다. 데이터의 모양(shape)을 잘 봐둡니다.
2. 신경망(파이프)을 설계합니다. 준비된 데이터의 모양을 잘 보고 그에 맞추어 설계해줍니다.
3. 물을 파이프 안으로 부어넣습니다.

1. 데이터 준비

지도학습(Supervised Learning)을 수행할 때는,
입력 데이터(X)를 집어넣고
정답 레이블(Y)에 맞추어 학습을 시킵니다.
이번 예제에서는 

6마리의 동물들(X)을 집어넣고, 3가지 이름으로 분류(Y)로 분류하는 인공신경망 모델을 구현해보겠습니다.

입력 데이터(X)는 animal_0부터 animal_5까지 6마리 동물들의 특징을
꼬리(tail), 짖는가(bark), 다리개수(legs), 크기(size)로 각각 설정했습니다.

정답 레이블(Y)은 각각의 동물에 해당하는 정답입니다.

가령 animal_0은 dog이고, animal_3은 rat 이라는 식으로요.
컴퓨터는 dog이니 cat이니 하는 글자를 읽을 줄 모르므로, 
dog은 [1, 0, 0]
cat은 [0, 1, 0]
rat은 [0, 0, 1]
의 숫자로 표현해줍니다. 이런 표현 방식을 원-핫 인코딩(one-hot encoding)이라고 합니다.

나중에 학습이 끝난 후에는
[ㅁ, ㅁ, ㅁ] 형식의 숫자에서 가장 높은 값을 정답으로 출력하게 됩니다.
아래 그림에서 빨갛게 칠해진 부분 처럼요.


                  

입력 데이터의 모양은 [6 x 4]입니다. (6행 4열)
6마리의 동물들 각각을 4가지 특징으로 기억하고 있지요.
행(row)의 수가 6, 
열(column)의 수가 4입니다.

이번 예제에서는 총 6마리의 동물들로 학습을 시킬 것이지만,
나중에 언제든 10마리 100마리도 입력받을 수 있게끔
동물의 마리수는 지정하지 않은 채로 놓아둡니다.
그림에는 [?x4]로 표기되어 있고,
코드에는 [None, 4]로 표기합니다.

마찬가지로 정답 레이블의 모양은 [6 x 3]입니다. (6행 3열)
나중에 언제든 10마리 100마리를 입력받아도 되게끔
동물의 마리수는 지정하지 않은 채로 놓아둡니다.
그림에는 [?x3]으로 표기되어 있고,
코드에는 [None, 3]으로 표기합니다.

numpy 라는 파이썬 패키지는, 이렇게 데이터가 담기는 그릇의 모양을 다루는 용도로 사용합니다.

                                                   

import tensorflow as tf
import numpy as np

# [꼬리(tail), 짖음(bark), 다리갯수(legs), 크기(size(cm))]
x_data = np.array(
    [[1, 1, 4, 50], [1, 0, 4, 5], [1, 0, 4, 20], [1, 0, 4, 10], [1, 1, 4, 100], [1, 0, 4, 12]])

# [dog, rat, cat]
y_data = np.array([
    [1, 0, 0],  # 개(dog)
    [0, 0, 1],  # 쥐(rat)
    [0, 1, 0],  # 고양이(cat)
    [0, 0, 1],  # 쥐(rat)
    [1, 0, 0],  # 개(dog)
    [0, 0, 1]   # 쥐(rat)
])
2. 신경망 설계

tf.placeholder는, 파이프의 입구와 출구 부분입니다.
입력 데이터와 정답 레이블을 받는 곳이므로, 각각 [None, 4], [None, 3]으로 잡아줍니다.

                                                                          

이제 신경망의 중추를 설계합니다. 
아래 그림에서 
세로로 노란 동그라미 네 개를 묶어 인풋 레이어(input layer)
세로로 빨강 동그라미 세 개를 묶어 아웃풋 레이어(output layer)
세로로 파랑 동그라미 각각을 히든 레이어(hidden layer)들 이라고 부릅니다.
그리고 각각의 레이어 사이의 연결 부위를 tf.Variable이라는 빈 파이프들로 이어줍니다.

그래서 tf.Variable은 '컴퓨터가 학습하는 값'을 담게 됩니다.
tf.Variable은, 일단 모양을 정하고 내용물을 랜덤으로 아무렇게나 채운 뒤,
데이터를 붓고 정답과의 차이(cost)를 최소화 하는(optimize) 방향으로 계산이 일어나는데
이 때 tf.Variable에 담긴 초기 랜덤값이 특정한 수치를 향하여 변해갑니다. 이 과정을 학습(learning)이라고 부릅니다.

히든 레이어는 아래 그림에서 다섯 층으로 만들어져 있는데, 
첫째 층은 4개
둘째 층은 5개
셋째 층은 6개
넷째 층은 4개
다섯째 층은 3개의 노드(node)로 구성되어 있습니다.

인공신경망을 몇 층짜리 히든 레이어로 구성할지,  각각의 히든 레이어마다 몇 개의 노드로 구성할지는
파이프를 설계하는 사람 마음입니다.
이렇게도 해보고, 저렇게도 해볼 수 있습니다.


각각의 히든레이어에는 수도꼭지 밸브가 들어있어서, 
이전 단계에서 받은 값이 정해진 특정 수준이 되는지 아닌지를 평가하여, 이후로 전달할지 말지를 결정합니다.
이 밸브는 활성화 함수(activation function)이라고 부르고,
sigmoid, ReLU 등의 종류가 있습니다. 


#########
# 신경망 모델 구성
######
X = tf.placeholder(tf.float32, shape=[None, 4])
Y = tf.placeholder(tf.float32, shape=[None, 3])

# 첫번째 가중치의 차원은 [특성, 히든 레이어의 뉴런갯수] -> [4, 4] 으로 정합니다.
W1 = tf.Variable(tf.random_uniform([4, 4], -1., 1.))

# b1은 편향(bias)이며, 첫 번째 히든 레이어의 뉴런 갯수입니다. 
b1 = tf.Variable(tf.zeros([4]))

# 신경망의 히든 레이어에 가중치 W1과 편향 b1을 적용합니다
L1 = tf.nn.relu(tf.add(tf.matmul(X, W1), b1))


W2 = tf.Variable(tf.random_normal([4, 5]))
b2 = tf.Variable(tf.zeros([5]))
L2 = tf.nn.relu(tf.add(tf.matmul(L1, W2), b2))

W3 = tf.Variable(tf.random_normal([5, 6]))
b3 = tf.Variable(tf.zeros([6]))
L3 = tf.nn.relu(tf.add(tf.matmul(L2, W3), b3))

W4 = tf.Variable(tf.random_normal([6, 4]))
b4 = tf.Variable(tf.zeros([4]))
L4 = tf.nn.relu(tf.add(tf.matmul(L3, W4), b4))

W5 = tf.Variable(tf.random_normal([4, 3]))
b5 = tf.Variable(tf.zeros([3]))
L5 = tf.nn.relu(tf.add(tf.matmul(L4, W5), b5))

W6 = tf.Variable(tf.random_normal([3, 3]))
b6 = tf.Variable(tf.zeros([3]))
model = tf.add(tf.matmul(L5, W6), b6)



# 텐서플로우에서 기본적으로 제공되는 크로스 엔트로피 함수를 이용해
# 복잡한 수식을 사용하지 않고도 최적화를 위한 비용 함수를 다음처럼 간단하게 적용할 수 있습니다.
cost = tf.reduce_mean(
    tf.nn.softmax_cross_entropy_with_logits_v2(labels=Y, logits=model))

optimizer = tf.train.AdamOptimizer(learning_rate=0.01)
train_op = optimizer.minimize(cost)
3. 데이터를 신경망에 부어넣습니다.

tf.global_variables_initializer()는 컴퓨터가 학습할 값들을 초기화 합니다.
sess = tf.Session() 으로 세션을 열고
학습을 하고
sess.close()로 세션을 닫습니다.

#########
# 신경망 모델 학습
######
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}))


#########
# 결과 확인
# 0: 개(dog) 1: 고양이(cat), 2: 쥐(rat)
######
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}))
sess.close()

 

댓글

댓글 본문