10강 인공신경망 2편

2018. 9. 28. 01:05Python-이론/python-인공지능2

10.3 텐서플로의 저수준 API로 심층 신경망 훈련하기 



이번에는 텐서플로우의 고수준 api인 tf.estimator를 사용하지 않고 저수준 api를 사용하여 mnist를 평가해보겠습니다. 


10.3.1 구성


1. 입력과 출력의 크기를 설정하고 출력수를 정한다. 

import tensorflow as tf

n_inputs = 28 * 28
n_hidden1 = 300
n_hidden2 = 100
n_outputs = 10


2. placeholder로 데이터 그릇 만들기 

X = tf.placeholder(tf.float32, shape=(None, n_inputs), name="X")
Y = tf.placeholder(tf.float32, shape=None, name="y")


3. 다중 퍼셉트론 층 만들기 


def neuron_layer(X, n_neurons, name, activation=None):
with tf.name_scope(name):
n_inputs = int(X.get_shape()[1])
stddev = 2 / np.sqrt(n_inputs)
init = tf.truncated_normal((n_inputs, n_neurons), stddev=stddev)
W = tf.Variable(init, name="kernel")
b = tf.Variable(tf.zeros([n_neurons]), name="bias")
Z = tf.matmul(X, W) + b
if activation is not None:
return activation(Z)
else:
return Z


첫줄에 이름 범위를 사용하여 텐서 보드에서 간단히 볼 수 있게 만들어주고 

n_inputs를 만들어 특성수를 만듭니다. 

stddev를 이용해서 표준편차를 만듭니다. 그리고 정규분포를 잘라내서 W를 완전히 난수 값으로 초기화 시켜줍니다. 

bias 값은 0으로 초기화 시켜주고 최종으로 W*X + b로 초기화 시켜줍니다. 


그리고 W*X는 2차원 배열이고 b는 1차원 배열인데 더할 수 있나 싶기도 한데 뒤에 b가 열의 수가 같으면 자동으로 브로드 캐스팅 해주어 바뀌어 집니다. 


이제 심층신경망을 만들어보겠습니다. 


with tf.name_scope("dnn"):
hidden1 = neuron_layer(X, n_hidden1, name="hidden1", activation=tf.nn.relu)
hidden2 = neuron_layer(hidden1, n_hidden2, name="hidden2", activation=tf.nn.relu)
logits = neuron_layer(hidden2, n_outputs, name="outputs")

히든레이어 첫층과 두번째 층은 relu를 써서 만들고 출력층은 일단 최적화를 위해 아무것도 안넣어 줬습니다. 


이번엔 비용함수를 구해보겠습니다. 크로스 엔트로피를 사용해보겠습니다. 

with tf.name_scope("loss"):
xentropy = tf.nn.sparse_softmax_cross_entropy_with_logits(
labels=Y, logits=logits
)
loss = tf.reduce_mean(xentropy, name="loss")


tf.nn.sparse_softmax_cross_entropy_with_logits는 우선 로짓에 소프트맥스를 적용한다음 크로스엔트로피를 적용시켜줍니다. 

하지만 더 효율적이고 특정한 상황에 적절히 다룹니다. 


훈련과 평가 받기


with tf.name_scope("train"):
optimizer = tf.train.GradientDescentOptimizer(learning_rate)
training_op = optimizer.train(loss)

with tf.name_scope("eval"):
correct = tf.nn.in_top_k(logits, Y, 1)
accuracy = tf.reduce_mean(tf.cast(correct, tf.float32))

훈련은 경사하강법을 이용하여 훈련해주고 평가는 in_top_k를통해 해준다. 평균을 만들어서 정확도를 만듭니다. 


in_top_k 함수는 예측값과 타깃 레이블을 입력받아 타깃 레이블의 예측값이 크기순으로 k번째 안에 들면 True 아니면 False를 반환합니다. 



실행 시켜보기

from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("/tmp/data/")

init = tf.global_variables_initializer()

n_epochs = 40 #40번 정도 반복해서 훈련
batch_size = 50 #한번의 훈련에 50개의 데이터 활용

with tf.Session() as sess:
init.run()
for epoch in range(n_epochs):
for iteration in range(mnist.train.num_examples // batch_size):
X_batch, y_batch = mnist.train.next_batch(batch_size)
sess.run(training_op, feed_dict={X:X_batch, Y:y_batch})
acc_train = accuracy.eval(feed_dict={X:mnist.validation.images, Y:mnist.validation.labels})
acc_val = accuracy.eval(feed_dict={X:mnist.validation.images,
Y:mnist.validation.labels})
print(epoch, "Train accuracy:", acc_train, "validation", acc_val)

결과

~

20 Train accuracy: 0.9742 validation 0.9742

21 Train accuracy: 0.9744 validation 0.9744

22 Train accuracy: 0.975 validation 0.975

23 Train accuracy: 0.9752 validation 0.9752

24 Train accuracy: 0.9748 validation 0.9748

25 Train accuracy: 0.975 validation 0.975

26 Train accuracy: 0.9764 validation 0.9764

27 Train accuracy: 0.976 validation 0.976

28 Train accuracy: 0.9762 validation 0.9762

29 Train accuracy: 0.977 validation 0.977

30 Train accuracy: 0.9772 validation 0.9772

31 Train accuracy: 0.978 validation 0.978

32 Train accuracy: 0.978 validation 0.978

33 Train accuracy: 0.978 validation 0.978

34 Train accuracy: 0.9778 validation 0.9778

35 Train accuracy: 0.979 validation 0.979

36 Train accuracy: 0.98 validation 0.98

37 Train accuracy: 0.9792 validation 0.9792

38 Train accuracy: 0.9794 validation 0.9794

39 Train accuracy: 0.9796 validation 0.9796


10.4 신경망 하이퍼파라미터 튜닝하기


텐서플로우는 유연성이 좋다보니 설정해야하는 파라미터가 많습니다. dense에 입력되어야하는 입력 개수, 출력 개수, 활성화 함수 등 수많은 파라미터가 있습니다. 이러한 것을 최적의 파라미터를 설정하기 위해선 이전에 사용한 그리드 서치라는 방법이 있습니다. 하지만 이는 대규모 데이터를 훈련할 떄 오래걸리기 때문에 랜덤 탐색이나 오스카 같은 도구를 사용하면 좋습니다. 


10.4.1 은닉층의 수 


다양한 문제가 하나의 퍼셉트론으로도 해결할 수 있습니다. 하나의 층에 많은 뉴런을 가질 수 있다면 ... 그래서 깊은 신경망 연구에 대한 필요성을 느끼지 못했습니다. 하지만 심층 신경망이 얇은 신경망 보다 훨씬 효율적이라는 것을 몰랐을 떄죠.


심층 신경망은 복잡한 함수를 모델링하는데 얕은 신경망 보다 훨씬 적은 수의 뉴런을 사용하기 떄문에 더 빠르게 훈련됩니다. 


예를 들어 


처음 히든레이어에는 저수준은 간단한 기능을 하는 것으로 만들고 중간은 저수준을 연결하여 중간 수준의 레이어를 만들고 고수준의 층은 중간층을 연결하여 출력층과 은닉층을 연결해줍니다. 이런 방식으로 효율적인 퍼셉트론을 만들수 있습니다.