상세 컨텐츠

본문 제목

[Deep Learning - 딥러닝]MNIST Classification - 손글씨 분류기 소스 구현

Artificial Intelligence

by [성운] 2019. 9. 14. 12:58

본문

이번 포스팅은 MNIST 구현에 대해서 알아보겠습니다. MNIST 정의는 https://ynebula.tistory.com/43 포스팅을 참고바랍니다.

 

MNIST 구현을 위해 다음 라이브러리 임포트가 필요합니다.

Source-1

 

MNIST 데이터는 텐서플로에서 제공합니다. 그래서 따로 다운로드 필요 없이 임포트해 사용하면 됩니다.

Source-2

 

하지만 텐서플로 1.7.0 버전에서부터는 샘플 데이터를 다운로드 하는 기능이 제외될 예정이라는 경고가 발생합니다. 대신 케라스(Keras) 사용하여 MNIST 데이터를 다운받기를 권장해 드립니다.

Source-3

 

데이터 셋의 구성을 확인해보겠습니다. training 데이터는 (60000, 784) 되어 있습니다. 첫 번째 차원은 각 이미지에 대한 인덱스이며 두 번째 차원은 이미지 안의 픽셀 수를 나타냅니다. 이미지 크기가 가로 28, 세로 28픽셀로 되어있어 28*28=784 가 됩니다.

정답 데이터는 one-hot encoding 방식으로 예를 들어 2이미지의 벡터는[0, 1, 0, ., 0]입니다.

Source-4

 

배치 데이터를 만들기 위해 파이썬 제너레이터 함수를 정의합니다.

Source-5

 

가중치 텐서와 바이어스 텐서를 만듭니다. tf.Variable 함수를 사용하여 생성되었고 초기 값을 가집니다. 여기서는 모두 초기 값을 0으로 이루어진 상수 텐서를 생성하였습니다.

Source-6

 

훈련 이미지 데이터를 넣을 플레이스홀더를 2차원 텐서로 만듭니다. 텐서 x MNIST 이미지를 784픽셀을 실수로 저장하는 벡터로 사용됩니다. None이라고 지정한 것은 어떤 크기나 가능하다는 뜻으로서, 여기에서는 학습 과정에 사용될 이미지의 개수가 것입니다.

Source-7

 

텐서를 만들었으니 모델을 만들 차례입니다. tf.nn.softmax() 함수는 소프트맥스 함수를 텐서플로로 구현한 것입니다.

Source-8

 

비용함수는 교차 엔트로피를 이용하였습니다. 그리고 가중치(W) 편향(b) 조정을 위해 역전파를 사용하였습니다. 교차 엔트로피 비용함수와 경사하강법을 사용하면, 매 루프마다 오차를 줄이기 위해서는 주어진 상황에서 얼마만큼 매개변수를 변경해야할지를 계산할 수 있습니다.

비용함수 교차 엔트로피를 구현하기 위해서는 실제 레이블을 담고 있는 새로운 플레이스홀더가 하나 더 필요합니다. 이 플레시스홀더를 이용해 다음 코드처럼 크로스 엔트로피 비용함수를 구현할 수 있습니다. 먼저 텐서플로 내장 함수인 tf.log()를 사용해 y의 각 원소 로그 값을 구합니다. 그러고 나서 y_의 각 원소와 곱합니다. 마지막으로 tf.reduce_sum() 함수를 사용하여 텐서의 모든 원소를 더합니다.

나중에 다룰 이미지는 여러 개이므로 교차 엔트로피의 값은 하나의 이미지에 대한 것이 아니라 이미지 묶음 y에 대응하여 나옵니다. 

참고로 비용함수는 여러 가지 있습니다(평균제곱오차, 유클리드 제곱거리, 교차 엔트로피). 비용함수는  https://ynebula.tistory.com/28 참고바랍니다. 

실제 레이블을 담기 위한 텐서와 교차 엔트로피 방식을 이용하는 그래디언트디센트 방식을 선택합니다.

Source-9

 

학습률은 0.01로 설정하겠습니다. 학습률은 tf.train.GradientDescentOptimizer() 매개변수로 전달합니다. 경사하강법 함수는 미분을 자동으로 연산해 줍니다. , 학습 과정에서 가중치와 편향 조정을 위한 필요한 미분 연산을 텐서플로가 자동으로 처리합니다.

minimize() 메서드가 실행될 때 텐서플로 손실함수(loss function), 즉 비용함수에 연관된 변수들을 알아서 인식하고 각각에 대해 기울기를 계산합니다.

텐서플로 사용자는 예측 모델의 계산 구조를 정의하고 목표함수(y=W*x+b)와 연결한 후 데이터만 넣어주면 됩니다.

Source-10

 

알고리즘을 모두 작성했으니, tf.Session()으로 시스템에서 사용 가능한 디바이스(CPU or GPU)에서 텐서플로의 연산을 실행합니다. 모든 변수를 초기화하고 세션을 시작합니다.

Source-11

 

여기서부터 모델 훈련을 시작합니다. train_step에서 산출된 매개변수는 경사하강법 알고리즘에 다시 참여하게 됩니다. 따라서 모델을 훈련시키려면 train_step을 반복적으로 실행해야 합니다. 한번 train_step 1000번 실행해보겠습니다. 루프 내 첫 번째 라인은 훈련 데이터 셋으로부터 무작위로 100개 추출합니다. 루프를 반복할 때마다 전체 데이터를 모두 사용할 수도 있지만, 예제를 더 편리하게 실습하기 위해 작은 표본 데이터를 이용하는 방법을 택했습니다. 그 다음 라인에서는 플레이스홀더를 사용하여 이 100개의 샘플 데이터를 주입니다. 

생성된 학습 모델이 좋은 모델인지 판단하기 위해서 모델평가를 수행해야 합니다. tf.argmax(y,1)은 입력 이미지에 대해 가장 높은 확률을 가진 레이블을 리턴 합니다. tf.argmax(y_,1)은 실제 레이블 입니다. tf.equal() 함수를 사용하여 예측 값과 실제 레이블을 다음과 같이 비교할 수 있습니다. 

위 코드는 불리언으로 이루어진 리스트를 리턴 합니다. 예측한 것이 얼만큼 맞았는지를 확인하려면 불리언을 수치 값으로 다음과 같이 변경합니다. 예를 들어 [True, False, True, True] [1, 0, 1, 1]로 바뀔 테고, 그 평균은 0.75가 나올 것입니다. 이것이 바로 정확도(accuracy)의 퍼센트를 나타냅니다. 이제 feed_dict 매개변수로 mnist.test를 전달하여 테스트 데이터 셋에 대한 정확도를 계산해봅시다. 1000의 반복을 수행하고 결과를 출력합니다.

Source-12

 

Source

다음 링크를 참고하시면 전체 소스 확인할 수 있습니다.

https://github.com/ynebula/First-Contact-with-Books/blob/master/Tensorflow/MNIST.ipynb

 

글이 도움되셨다면 공감 부탁 드립니다.

감사합니다.

 

[Reference]

텐서플로 첫걸음

 

관련글 더보기

댓글 영역