안녕하세요.
오늘의 파이썬 코딩 독학 주제는 MNIST 입니다.
MNIST는 손으로 쓴 숫자들의 이미지를 모아놓은 데이터셋으로써
0부터 9까지의 숫자를 28*28 픽셀 크기로 구성해놓은 이미지 집합입니다.
MNIST는 머신러닝에서 상당히 유명한 예제 중 하나로써
전처리도 잘 되어있어서 번거로운 작업없이 바로 머신러닝을 진행할 수 있습니다.
1. 텐서플로우 외에 필요한 라이브러리
tensorflow.examples.tutorials.mnist.input_data : MNIST 예제가 들어있는 라이브러리입니다.
2. 전체 소스코드
import tensorflow as tf
from tensorflow.examples.tutorials.mnist import input_data
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])
W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01))
L1 = tf.nn.relu(tf.matmul(X, W1))
W2 = tf.Variable(tf.random_normal([256, 256], stddev=0.01))
L2 = tf.nn.relu(tf.matmul(L1, W2))
W3 = tf.Variable(tf.random_normal([256, 10], stddev=0.01))
model = tf.matmul(L2, W3)
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
batch_size = 100
total_batch = int(mnist.train.num_examples / batch_size)
for epoch in range(15):
total_cost = 0
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
_, cost_val = sess.run([optimizer, cost], feed_dict = {X:batch_xs, Y:batch_ys})
total_cost += cost_val
print('Epoch:', '%04d' % (epoch + 1), 'Avg. cost=', '{:.3f}'.format(total_cost / total_batch))
print('최적화 완료')
is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print('정확도:', sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels}))
3. 소스코드의 목적
MNIST 데이터셋을 이용하여
2개의 은닉층을 통해
손글씨 이미지를 학습시켜보겠습니다.
아래 그림이 바로 MNIST 데이터셋에 들어있는
손글씨 이미지입니다.
4. 소스코드 분석
아래의 코드로 MNIST 데이터를 mnist/data/ 디렉토리에 다운받을 수 있습니다.
루트 폴더에 mnist와 data폴더가 생성되며 그 안에 데이터가 다운로드 됩니다.
이후 데이터를 one-hot 인코딩 방식으로 불러들입니다.
mnist = input_data.read_data_sets("./mnist/data/", one_hot=True)
MNIST의 손글씨 이미지는 28*28픽셀이므로
총 784개의 특징으로 이루어져 있습니다.
또한 0부터 9까지의 숫자가 표현되어 있으므로
10개의 분류로 나눌 수 있습니다.
아래의 코드를 통해 입력값과 출력값을 정의하겠습니다.
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])
머신러닝을 할 때 여러개의 이미지를 한번에 학습시키는게 좋지만
높은 성능이 필요하므로 보통은 데이터를 적당한 크기로 잘라서 학습시킵니다.
이와 같은 데이터 정제 과정을 미니배치(Minibatch)라고 부릅니다.
위의 코드에서 텐서의 첫번째 차원이 None이라고 입력되어있는데,
이 자리에는 한번에 학습시킬 이미지의 개수를 지정하는 값이 들어갑니다.
원하는 갯수로 정확히 지정할수도 있지만
그냥 None이라고 입력하면 텐서플로우가 임의로 계산해줍니다.
아래의 코드를 이용해
2개의 은닉층을 가진 신경망을 만들어줍니다.
W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01))
L1 = tf.nn.relu(tf.matmul(X, W1))
W2 = tf.Variable(tf.random_normal([256, 256], stddev=0.01))
L2 = tf.nn.relu(tf.matmul(L1, W2))
W3 = tf.Variable(tf.random_normal([256, 10], stddev=0.01))
model = tf.matmul(L2, W3)
위와 같은 코드를 입력하게 되면
아래 그림과 같은 신경망이 만들어 지게 됩니다.
tf.random_normal() 함수에서 stddev=0.01이라고 작성하면
표준편차가 0.01인 정규분포를 가지는 임의의 값으로 변수를 초기화시킵니다.
tf.matmul() 함수를 이용해서 입력값에 각각의 가중치를 곱해줍니다.
tf.nn.relu() 함수를 이용해서 ReLU함수를 활성화 함수로 사용합니다.
아래의 코드에서
tf.nn.softmax_cross_entropy_with_logits_v2() 함수를 사용하여
각 이미지에 대해 예측값과 실제값의 차이값인 손실값을 구해주고,
tf.reduce_mean() 함수를 사용해서 미니배치 손실값의 평균을 구해줍니다.
tf.train.AdamOptimizer() 함수로 최적화를 수행하여 손실값을 최소화하여줍니다.
cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)
아래의 코드에서
신경망 모델을 초기화하고 학습을 진행할 세션을 시작합니다.
init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)
MNIST는 데이터가 수만개에 달하므로
모든 데이터를 학습하면 너무 오랜 시간이 걸리게 됩니다.
따라서 아래와 같은 코드를 사용하여
미니배치 사이즈를 100개로 지정해줍니다.
또한 학습 데이터의 총 개수인
mnist.train.num_examples를 배치 크기로 나누어서
미니배치가 몇 개인지를 지정해줍니다.
batch_size = 100
total_batch = int(mnist.train.num_examples / batch_size)
이제 아래 코드를 입력하여
MNIST데이터 전체를 15번 반복해서 학습하도록 지정해줍니다.
여기서 데이터 전체를 한번 학습하는 것을 에포크(Epoch)라고 합니다.
for epoch in range(15):
total_cost = 0
아래 코드를 이용해서
미니배치의 총 갯수만큼 반복학습하도록 지정합니다.
for i in range(total_batch):
batch_xs, batch_ys = mnist.train.next_batch(batch_size)
_, cost_val = sess.run([optimizer, cost], feed_dict = {X:batch_xs, Y:batch_ys})
mnist.train.next_batch(batch_size) 함수를 사용해서
학습할 데이터를 배치 사이즈에 맞춰 가져옵니다.
이후 입력값은 batch_xs에,
출력값은 batch_ys에 저장합니다.
이후 sess.run() 함수를 사용하여 최적화를 진행하고
손실값을 저장해줍니다.
이때 feed_dict 매개변수에 입력값 X와 출력값 Y를 넣어줍니다.
아래 코드를 이용해서
손실값을 저장해주고,
학습이 한 바퀴 끝나면, 해당 바퀴의 평균 손실값을 출력합니다.
total_cost += cost_val
print('Epoch:', '%04d' % (epoch + 1), 'Avg. cost=', '{:.3f}'.format(total_cost / total_batch))
print('최적화 완료')
이번에는 학습 결과를 출력해보겠습니다.
아래 코드를 이용해서
예측값인 model과 출력값인 Y를 비교합니다.
is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y, 1))
tf.argmax() 함수를 이용해서 두 번째 차원의 값 중 최댓값의 인덱스를 뽑아냅니다.
tf.equal() 함수를 이용해서 예측값과 실제값이 같은지를 비교해줍니다.
다음 코드에서
tf.cast() 함수를 통해 is_correct를 0과1로 변환해줍니다.
이후
tf.reduce_mean() 함수를 이용해서 평균을 내줍니다.
그럼 정확도를 구할 수 있습니다.
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
다음 코드에서
테스트 이미지를 다루는 객체인
mnist.test를 이용해서
학습의 정확도를 출력해줍니다.
print('정확도:', sess.run(accuracy, feed_dict={X: mnist.test.images, Y: mnist.test.labels}))
5. 결과 확인
정상적으로 학습이 진행되었다면
위 사진과 같은 결과값이 출력됩니다.
오늘은 MNIST로 손글씨 학습을 진행하였습니다.
'코딩 > 텐서플로우' 카테고리의 다른 글
비전공자의 코딩 독학 - 파이썬&텐서플로우(12) <Matplotlib> (0) | 2020.05.01 |
---|---|
비전공자의 코딩 독학 - 파이썬&텐서플로우(11) <과적합> (0) | 2020.04.30 |
비전공자의 코딩 독학 - 파이썬&텐서플로우(9) <시그모이드 예제> (0) | 2020.01.18 |
비전공자의 코딩 독학 - 파이썬&텐서플로우(8) <텐서보드> (0) | 2020.01.15 |
비전공자의 코딩 독학 - 파이썬&텐서플로우(7) <예제3 심층신경망> (1) | 2020.01.14 |