티스토리 친구하기

본문 바로가기

딥러닝/Your own dataset

your own mnist dataset classification with tensorflow

728x90

Update

2019.8.17: Writing

2019.8.26: Posting

 

  본 포스팅은 github에 업로드한 mnist_dnn repository에 대한 설명이다. 코드에서 사용한 여러가지 API 및 모듈에 대한 해설은 "mnist my own data" 포스트를 참조하기 바란다. 

 

dnn_mnist.py

 

import tensorflow as tf
import numpy as np

from glob import glob
from PIL import Image

from util import get_label_from_path
from util import data_slice_and_batch

# 1.Hyper Parameter
num_epoch = 2
batch_size = 500
height = 28
width = 28
channels = 1
num_classes = 10
shuffle_buffer_size = 100000
shuffle_buffer_size_test = 20000

# 2-1. Import training dataset
DATA_PATH_LIST = glob('./mnist_png/training/*/*.png')
LABEL_LIST = get_label_from_path(DATA_PATH_LIST)
dataset = data_slice_and_batch(DATA_PATH_LIST, LABEL_LIST, shuffle_buffer_size, batch_size)

# 2-2. Import test dataset
TEST_DATA_PATH_LIST = glob('./mnist_png/testing/*/*.png')
TEST_LABEL_LIST = get_label_from_path(TEST_DATA_PATH_LIST)
dataset_test = data_slice_and_batch(TEST_DATA_PATH_LIST, TEST_LABEL_LIST, shuffle_buffer_size_test, batch_size)


# 3.Model Design
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)

W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01))
L1 = tf.nn.relu(tf.matmul(X, W1))
L1 = tf.nn.dropout(L1, keep_prob)

W2 = tf.Variable(tf.random_normal([256, 256], stddev=0.01))
L2 = tf.nn.relu(tf.matmul(L1, W2))
L2 = tf.nn.dropout(L2, keep_prob)

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)


total_batch = int(len(DATA_PATH_LIST)/batch_size)

for epoch in range(num_epoch):
	total_cost = 0
	iterator = dataset.make_initializable_iterator()
	sess.run(iterator.initializer) # Shuffle이 실행됨

	for i in range(total_batch):
		# batch_xs, batch_ys = mnist.train.next_batch(batch_size)
		image, label = sess.run(iterator.get_next())

		batch_xs = image.reshape(batch_size,784)
		batch_ys = tf.one_hot(label, depth=num_classes).eval(session=sess)
		# print(batch_ys)

		a, cost_val = sess.run([optimizer, cost], feed_dict={X: batch_xs, Y: batch_ys, keep_prob: 0.8})
		total_cost += cost_val

		if i % 10 == 0:
			print('batch:', '%04d' % (i*batch_size), 'cost =', '{:.8f}'.format(cost_val))

	print('Epoch:', '%04d' % (epoch+1), 'Avg. cost =', '{:.3f}'.format(total_cost/total_batch))

print('learning finished!!')

iterator_test = dataset_test.make_initializable_iterator()
sess.run(iterator_test.initializer) # Shuffle이 실행됨
image_test, label_test = sess.run(iterator_test.get_next())

batch_xs_test = image_test.reshape(batch_size,784)
batch_ys_test = tf.one_hot(label_test, depth=num_classes).eval(session=sess)

is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print('accuracy: ', sess.run(accuracy, feed_dict={X: batch_xs_test, Y: batch_ys_test, keep_prob: 1}))

sess.close()

 

 

1. tensorflow와 필요한 라이브러리 import

 

import tensorflow as tf
import numpy as np

from glob import glob
from PIL import Image

from util import get_label_from_path
from util import data_slice_and_batch

 

- tensorflow와 numpy를 tf와 np라는 이름으로 import한다.

- 데이터의 path(경로)를 불러오기 위한 glob모듈을, path를 사용해 실제 이미지를 불러오기 위해 PIL에서 Image를 import한다.

- 사용자가 만든 util.py에서 get_label_from_path(경로에서 label를 추려내는 함수)와 data_slice_and_batch(데이터를 batch_size의 크기로 묶어내는 함수)를 import한다.

 

 

2. 하이퍼 파라미터 설정

 

# 1.Hyper Parameter
num_epoch = 2
batch_size = 500
height = 28
width = 28
channels = 1
num_classes = 10
shuffle_buffer_size = 100000
shuffle_buffer_size_test = 20000

 

- epoch과 batch_size는 각각 2와 500으로 설정하였다.

- mnist dataset의 이미지 크기에 맞춰 height와 width는 각각 28로 설정하였다.

- 흑백이미지이므로 channels는 1로 설정하였다.

- training 및 test dataset 각각 모두 shuffle될 수 있도록 shuffle_buffer_size와 shuffle_buffer_size_test는 각각의 dataset의 크기보다 큰 100,000 and 20,000으로 설정하였다. (# of training dataset: 60,000, # of test dataset: 10,000)

 

 

3. traning and test dataset import

 

# 2-1. Import training dataset
DATA_PATH_LIST = glob('./mnist_png/training/*/*.png')
LABEL_LIST = get_label_from_path(DATA_PATH_LIST)
dataset = data_slice_and_batch(DATA_PATH_LIST, LABEL_LIST, shuffle_buffer_size, batch_size)

# 2-2. Import test dataset
TEST_DATA_PATH_LIST = glob('./mnist_png/testing/*/*.png')
TEST_LABEL_LIST = get_label_from_path(TEST_DATA_PATH_LIST)
dataset_test = data_slice_and_batch(TEST_DATA_PATH_LIST, TEST_LABEL_LIST, shuffle_buffer_size_test, batch_size)

 

- DATA_PATH_LIST에 training dataset의 모든 경로를 저장한다.

- LABEL_LIST에는 DATA_PATH_LIST에서 추출한 label들이 저장된다.

- data_slice_and_batch함수에서 처리한 정보는 dataset에 저장된다. 학습을 진행할 때  sess.run(iterator.get_next())을 이용하여 batch_size 크기의 이미지 및 라벨정보를 불러올 수 있다.

- TEST가 붙어있는 변수들은 test dataset을 불러오고 정리한 것이다.

 

 

4. 모델 디자인

 

 

# 3.Model Design
X = tf.placeholder(tf.float32, [None, 784])
Y = tf.placeholder(tf.float32, [None, 10])
keep_prob = tf.placeholder(tf.float32)

W1 = tf.Variable(tf.random_normal([784, 256], stddev=0.01))
L1 = tf.nn.relu(tf.matmul(X, W1))
L1 = tf.nn.dropout(L1, keep_prob)

W2 = tf.Variable(tf.random_normal([256, 256], stddev=0.01))
L2 = tf.nn.relu(tf.matmul(L1, W2))
L2 = tf.nn.dropout(L2, keep_prob)

W3 = tf.Variable(tf.random_normal([256, 10], stddev=0.01))
model = tf.matmul(L2, W3)

 

5. cost function 및 optimizer 선택

 

cost = tf.reduce_mean(tf.nn.softmax_cross_entropy_with_logits_v2(logits=model, labels=Y))
optimizer = tf.train.AdamOptimizer(0.001).minimize(cost)

 

- cross entroty 함수를 cost function으로 사용한다. model에서 나온 출력값과 y(정답)의 차이를 줄이는 방향으로 학습된다.

- optimizer는 AdamOptimizer를 사용한다. learning rate는 0.001로 설정하였다.

 

 

6. 초기화

 

init = tf.global_variables_initializer()
sess = tf.Session()
sess.run(init)

 

- 변수들을 초기화 한다.

 

 

7. 학습

 

total_batch = int(len(DATA_PATH_LIST)/batch_size)

for epoch in range(num_epoch):
	total_cost = 0
	iterator = dataset.make_initializable_iterator()
	sess.run(iterator.initializer) # Shuffle이 실행됨

	for i in range(total_batch):
		# batch_xs, batch_ys = mnist.train.next_batch(batch_size)
		image, label = sess.run(iterator.get_next())

		batch_xs = image.reshape(batch_size,784)
		batch_ys = tf.one_hot(label, depth=num_classes).eval(session=sess)
		# print(batch_ys)

		a, cost_val = sess.run([optimizer, cost], feed_dict={X: batch_xs, Y: batch_ys, keep_prob: 0.8})
		total_cost += cost_val

		if i % 10 == 0:
			print('batch:', '%04d' % (i*batch_size), 'cost =', '{:.8f}'.format(cost_val))

	print('Epoch:', '%04d' % (epoch+1), 'Avg. cost =', '{:.3f}'.format(total_cost/total_batch))

print('learning finished!!')

 

- total_batch = 60,000 / batch_size(500) = 120

- num_epoch=2이기 때문에 60,000개의 데이터가 2번 학습된다.

- 매 epoch마다 total_cost 및 average_cost를 계산하기 위해 total_cost를 0으로 설정한다.

- iterator를 정의하고 sess.run(iterator.initializer)를 실행하면 데이터가 shuffle된다. 위의 코드에서는 매 epoch마다 shuffle을 진행한다.

- sess.run(iterator.get_next())의 출력값으로 image와 label에 batch_size(500개)만큼의 이미지와 이에 상응하는 라벨값들이 저장된다.

-  [batch_size, 28, 28]의 shape을 가지고 있는 image를 입력의 모양이 [batch_size, 784]인 model에 넣기 위해 shape을 바꿔서 batch_xs에 넣어준다. 

- 0,1,2,...,8,9로 저장되어 있는 라벨값을 one_hot_vector(정답의 index는 1, 나머지 index는 모두 0)를 만들기 위해 tf.ont_hot 함수를 이용하여 ont hot encoding을 한다.

- batch_xs와 batch_ys를 feed_dick을 이용하여 model에 넣고 sess.run으로 optimizer와 cost를 실행한다. dropout의 비율은 0.8로 설정하였고, cost_val를 출력하여 cost가 얼마나 줄어드는지 10번의 batch만큼(i%10==0) 학습이 진행될 때마다 확인한다.

- epoch이 끝날때마다 매 opoch의 평균 cost를 계산하여 출력한다.

 

 

8. Testset을 이용하여 Accuracy 확인

 

iterator_test = dataset_test.make_initializable_iterator()
sess.run(iterator_test.initializer) # Shuffle이 실행됨
image_test, label_test = sess.run(iterator_test.get_next())

batch_xs_test = image_test.reshape(batch_size,784)
batch_ys_test = tf.one_hot(label_test, depth=num_classes).eval(session=sess)

is_correct = tf.equal(tf.argmax(model, 1), tf.argmax(Y,1))
accuracy = tf.reduce_mean(tf.cast(is_correct, tf.float32))
print('accuracy: ', sess.run(accuracy, feed_dict={X: batch_xs_test, Y: batch_ys_test, keep_prob: 1}))

sess.close()

 

- training set에서 진행했던 것처럼 testset을 불러와서 batch_xs_test와 batch_ys_test에 batch_size 크기만큼 저장한다. 모든 testset를 이용해서 Accuracy를 계산하려면 batch_size의 크기를 testset의 크기(10,000)으로 조절한다.

- model에서 inference한 값과 이에 상응하는 y값이 일치하면 True, 일치하지 않으면 False를 출력하는데 이를 float32값으로 바꿔 accuracy를 계산한다. 

- accuracy를 계산할때는 학습할때와 달리 keep_prob를 1로 설정하여 dropout없이 모든 weight를 사용한다. 

- accuracy까지 모두 계산하면 Session을 종료한다.

 

반응형