반응형

케라스, MNIST 손글씨 딥러닝 예제 분석

 

<참조> 유튜브 [토크ON세미나] 딥러닝 입문에서 활용까지 케라스(Keras)  

           https://www.youtube.com/watch?v=IPR2bYFa6Rw

 

글. 오상문 sualchi@daum.net

 

다음 예제는 숫자 0~9 숫자에 대한 MNIST 손글씨 데이터(그레이스케일 이미지 데이터와 숫자 결과)를 이용하여 딥러닝 후에 테스트 결과를 확인하는 예제이다. 예제에 설명을 달았으니 참고하기 바란다.

 

MNIST 데이터는 손글씨 이미지(28*28 = 784바이트 크기) 샘플 7만개와 정답을 담아놓은 데이터셋이다. 이 중에서 6만개는 학습 데이터셋으로 사용하고, 나머지 1만개는 테스트 데이터로 사용할 것이다.

 

[참고] 케라스2 사용자는 예제 일부에서 경고 메시지가 나타날 수 있다(실행은 됨).

-----------------------------------------------

다음처럼 케라스2 방식으로 수정하면 경고문이 사라진다.

 

# relu 선형함수를 이용하여 28*28(784) 클래스 크기를 64 크기로 바꾼다.
model.add(Dense(output_dim=64, input_dim=28*28, activation='relu'))

수정 --> model.add(Dense(input_dim=784, activation="relu", units=64)) 

             #  28*28이나 784는 아무 것이나 써도 됨


# softmax 다중분류 함수를 이용하여 클래스 10개 구조로 바꾼다(원핫 인코딩 구조).
model.add(Dense(output_dim=10, activation='softmax'))

 

수정 --> model.add(Dense(activation="softmax", units=10))

 

model.fit(X_train, Y_train, nb_epoch=5, batch_size=32)

 

수정 --> model.fit(X_train, Y_train, epochs=5, batch_size=32)

--------------------------------------------------------------

 

 

다음은 설명이 달린 예제 소스 코드이다.


#-------------------------------------------------

# 모듈 임포트 (MNIST 딥러닝을 위해 필요한 기능 모듈을 가져온다)
from keras.utils import np_utils
from keras.datasets import mnist
from keras.models import Sequential
from keras.layers import Dense, Activation

 

#-------------------------------------------------
# mnist 다운로드, 데이터셋 준비 (Download, Reshape & Categorical)

 

#  mnist에서 훈련자료 6만개와 시험자료 1만개를 가져온다.

(X_train, Y_train), (X_test, Y_test) = mnist.load_data()
# (학습 입력값,결과값 ), (테스트 입력값,결과값 )

 

# 구조 변경하여 가져오기

# 총 7만개 중에서 학습용 6만개, 시험용 1만개 샘플을 사용한다.

# 샘플당 크기는 784Byte, 정수 자료이다.
# 참고로, mnist에서 제공하는 손글씨 샘플 하나당 이미지 크기는 28*28(=784)바이트

X_train = X_train.reshape(60000, 784).astype('float32') / 255.0
#                       6만개  샘플크기,    실수형 변환,   0~1.0 크기로 변경

 

X_test = X_test.reshape(10000, 784).astype('float32') / 255.0
#                       1만개  샘플크기 ,   실수형  변환,  0~1.0 크기로 변경

 

# 결과(정답) 값에는 0~9까지 숫자 값이 들어가 있다.
# 각 숫자별로 카테고리 클래스 분류를 한다(원핫 인코딩 방식).

# 결과는 클래스 10개 구조인 자료들이다. (예; [1,0,0,0,0,0,0,0,0,0])

# 이 카테고리 클래스 크기 10은 나중에 모델 구성할 단계에서도 사용된다.
Y_train = np_utils.to_categorical(Y_train)
Y_test = np_utils.to_categorical(Y_test)

 

#-----------------------------------------------------
# 모델 구성 (New Model & Add)


model = Sequential() # 순차적인 다층 구조 모델이 가능한 빈 모델 생성 

                       # 각 층은 한 처리부만 존재하고 다음 층에 처리 결과 전달

                       # 한 층에서 여러 처리부를 사용하려면 Graph() 모델 사용.

                       # 단, Graph() 모델은 층 생성 함수가 다르다.     


# relu 선형함수를 이용하여 28*28(784) 클래스 크기를 64 크기로 바꾼다.
model.add(Dense(output_dim=64, input_dim=28*28, activation='relu'))

                    # 출력 차원=64, 입력 차원=784, 활성함수='relu'


# softmax 다중분류 함수를 이용하여 클래스 10개 구조로 바꾼다(원핫 인코딩 구조).
model.add(Dense(output_dim=10, activation='softmax'))

                    # 출력 차원=10, 입력 차원=자동계산됨(64), 활성함수='softmax'

 

#------------------------------------------------------
# 모델 엮어서 완성 (Compile)
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['accuracy'])
#                     손실 처리=다중분류,      최적화 방법='sgd,   측정 기준=정확도 

#                                                         (sgd: 확률적 경사하강법)

 

#-------------------------------------------------------
# 모델 학습 (Fit)


model.fit(X_train, Y_train, nb_epoch=5, batch_size=32)
#            입력,  정답 , 전체 5회 반복 , 샘플 32개씩 학습/갱신

 

#------------------------------------------------------
# 모델 사용 평가 (Evaluate) 


loss_and_metrics = model.evaluate(X_test, Y_test, batch_size=32)
# 손실, 정확도                      테스트 입력 , 정답 , 샘플 32개씩 작업

 

print("손실 및 정확도:", str(loss_and_metrics ))

 

#------------------------------------------------------
# 완성된 모델을 사용해보자 (Predict)


x = X_test[0:1]               # 테스트의 첫 샘플을 가져와 사용해보자. 
y = model.predict_classes(x)  # 기대값이 가장 높은 결과 값 얻음
print("결과: ")
print(y)
y = model.predict(x)              # 각 클래스(0~9) 기대값 얻음
print("각 숫자에 대한 가능성:")
print(y)

 

----------------------------------------------------------------------------

[실행 결과]

 

Epoch 1/5
60000/60000 [============] - 11s 175us/step - loss: 0.6899 - accuracy: 0.8217
Epoch 2/5
60000/60000 [============] - 11s 177us/step - loss: 0.3512 - accuracy: 0.9014
Epoch 3/5
60000/60000 [============] - 10s 175us/step - loss: 0.3043 - accuracy: 0.9131
Epoch 4/5
60000/60000 [============] - 11s 177us/step - loss: 0.2758 - accuracy: 0.9220
Epoch 5/5
60000/60000 [============] - 11s 178us/step - loss: 0.2540 - accuracy: 0.9280
10000/10000 [============] - 1s 89us/step


결과:

손실 및 정확도: [0.22523144161850214, 0.9363999962806702] <--93.64%
[7]   <-- 정답 7이 나왔다!
각 숫자에 대한 가능성:
[[5.7013971e-05 1.5977866e-07 2.9202469e-04 1.7521917e-03 6.8809072e-06
  5.1784831e-05 2.1408965e-07 9.9701726e-01 4.1261275e-05 7.8119605e-04]]

빨간색 부분이 숫자 7의 기대값(99.7%)이고 가장 높다.

(0,1,2,3,4,5,6,7,8,9 순서)

 

[참고] 손글씨 이미지를 출력하는 내용을 보고싶으면 아래 링크 참조

http://blog.daum.net/sualchi/13720847

 

<이상>

 

 

반응형

+ Recent posts