on
딥러닝 손글씨 예측 모델 만들어보기 (feat 데이터정규화)
딥러닝 손글씨 예측 모델 만들어보기 (feat 데이터정규화)
딥러닝 손글씨 인식하기
딥러닝을 공부하면 가장 유명한
도전과제가 손글씨를 인식하는
것이다. 컴퓨터가 사람이 쓴 글을
읽고 의미를 데이터화 하기 위해서
필수적인 과정이다.
손글씨를 이해하기 위해서는 먼저
글씨를 1차 배열로 변경하는 작업이
필요하다.
mnist에서 지원하는 손글씨 데이터는
6000개의 학습셋을 가지고 있다. 각
데이터는 28x28 픽셀크기를 가지고
있다.
1 2 3 4 5 from keras.datasets import mnist (X_train, Y_class_train),(X_test, Y_class_test) = mnist.load_data() print ( "학습셋 이미지 수 : {0} 개" . format (X_train.shape)) print ( "테스트셋 이 수 : {0} 개" . format (X_test.shape)) cs
딥러닝 모델을 학습시키기 위해서는
픽셀데이터를 1차원 배열로 변경해줘야
한다. reshape() 함수는 28x28 2차원
배열을 784길이의 1차원 배열로 변경
해준다.
reshape(총 샘플 갯수, 1차원 속성의 수)
1 X_train = X_train.reshape(X_train.shape[ 0 ], 784 ) cs
keras에서 모델을 학습시키기 위해서는
배열안의 데이터를 0과1의 조합으로 만들
어야 한다. 손글씨 데이터는 0~255 rgb
데이터이므로 전체 픽셀데이터를 255로
나눠주면 된다.
일반 정수를 255로 나누기 위해서는 먼저
픽셀 데이터를 실수형으로 변환시켜줘야
한다.
astype(변환할 데이터 형)
1 X_train = X_train.reshape(X_train.shape[ 0 ], 784 ).astype( 'float64' ) / 255 cs
출력값 또한 레이블이 정수형으로 기재
되어있다. 손글씨의 데이터는 0~9 중
숫자를 선택하는 다항분류문제의 일종이기
때문에, 원-핫 코딩을 사용해야 한다.
to_categorical()함수를 사용해서 일반정수
데이터를 0과1로 이루어진 1차배열로
변환한다.
원 핫 코딩은 아래 글을 참고하길 바란다.
일정한 랜덤데이터를 출력하기 위해서
seed값을 할당하고, 넘파이와 tensorflow에
seed값을 설정한다.
MNIST 데이터셋을 불러와서 각각 학습셋과
테스트셋으로 분류한다. 손글씨를 분류하기
위한 데이터 전처리 작업을 진행한다.
모델을 생성하는 부분은 Sequential() 함수를
사용한다. 첫번째 층은 입력층과 은닉층의 역할을
동시에 한다. 노드수는 512개, 입력데이터는 784개를
설정한다. 기울기 소실 문제를 해결하기 위한 활성화
함수는 ReLU를 사용한다.
출력층에는 10개의 노드를 설정한다. 다항 분류 문제
이기 때문에, 0과 1의 특징을 도드라지게 하는
softmax() 함수를 활성화함수로 사용한다.
아래 예제는 기본적으로 0~9 사이의 숫자를
분류하는 다항분류문제다. 오차함수는
categorical_crossentropy()함수를 사용한다.
만약 이항분류 문제라면 binary_crossentropy()
함수를 사용한다.
최적화 함수는 Adam()을 사용한다.
속도를 증가시키고, 모델 계산의 최적도를
향상시킨다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 from keras.datasets import mnist from keras.utils import np_utils from keras.models import Sequential from keras.layers import Dense from keras.callbacks import ModelCheckpoint, EarlyStopping import matplotlib.pyplot as plt import numpy import os import tensorflow as tf # seed 값 설정합니다. seed = 0 numpy.random.seed(seed) tf.compat.v1.set_random_seed(seed) # MNIST 데이터 불러옵니다. (X_train, Y_train), (X_test, Y_test) = mnist.load_data() X_train = X_train.reshape(X_train.shape[ 0 ], 784 ).astype( 'float32' ) / 255 X_test = X_test.reshape(X_test.shape[ 0 ], 784 ).astype( 'float32' ) / 255 Y_train = np_utils.to_categorical(Y_train, 10 ) Y_test = np_utils.to_categorical(Y_test, 10 ) # 모델 프레임 설정합니다. model = Sequential() model.add(Dense( 512 , input_dim = 784 , activation = 'relu' )) model.add(Dense( 10 , activation = 'softmax' )) # 모델 실행 환경 설정합니다. model.compile(loss = 'categorical_crossentropy' , optimizer = 'adam' , metrics = [ 'accuracy' ]) Colored by Color Scripter cs
최적화된 모델을 출력한다.
ModelCheckpoint() 함수를 사용해서,
테스트셋의 오차를 기준으로 val_loss
모델의 성능을 판단하고, 성능이 개선될
때 모델을 저장한다.
만약 성능이 개선되지 않으면,
EarlyStopping()함수를 사용해서,
학습을 중단하고, 10번 더 학습을
진행한다.
MoelCheckpoint()함수와 EarlyStopping()함수에
대해서는 아래 글을 참고하길 바란다.
모델 학습을 진행한다.
에포크는 30번을 반복하고,
batch_size는 2000개씩 넣어서
딥러닝을 진행한다.
출력결과를 확인하면 98.12%의 정확도로
결과를 예측하고 있는 것을 확인할 수 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 # 모델을 실행합니다. model.fit(X_train, Y_train, epochs = 30 , batch_size = 2000 , verbose = 0 ) # 테스트 정확도를 출력합니다. print ( "
Test Accuracy : %.4f" %(model.evaluate(X_test, Y_test)[ 1 ])) Colored by Color Scripter cs
딥러닝을 학습하면서, 더 이상 정확도가
개선되지 않으면 학습을 중단하기 위해서는
EarlyStopping()함수를 사용한다.
테스트셋 오차 val_loss를 구하기 위해서는
model.fit() 모델을 실행하는 함수에 인자로
validation_data에 테스트 셋 값을 넣어줘야
한다.
monitoring 값은 테스트셋의 오차 val_loss로
설정한다. 케라스에서는 테스트셋 오차를
val_loss에 저장한다. 결과값을 테스트셋
오차와 학습셋 오차로 구분하여 그래프를 출력해본다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 early_stopping_callback = EarlyStopping(monitor = 'val_loss' , patience = 10 ) # 모델을 실행합니다.
history = model.fit(X_train, Y_train, validation_data=(X_test, Y_test), epochs =10 0 , batch_size = 2000 , verbose = 1 , callbacks = [early_stopping_callback]) # 테스트 정확도를 출력합니다. print ( "
Test Accuracy : %.4f" %(model.evaluate(X_test, Y_test)[ 1 ])) # 테스트셋의 오차 y_vloss = history.history[ 'val_loss' ] # 학습셋의 오차 y_loss = history.history[ 'loss' ] # 그래프로 표현합니다. x_len = numpy.arange( len (y_loss)) plt.plot(x_len, y_vloss, marker = '.' , c = "red" , label = "Testset_loss" ) plt.plot(x_len, y_loss, marker = '.' , c = "blue" , label = "Trainset_loss" ) # 그래프에 그리드를 주고 레이블을 표시합니다. plt.legend(loc = 'best' ) plt.grid() plt.xlabel( 'epoch' ) plt.ylabel( 'loss' ) plt.show() Colored by Color Scripter cs
결과값을 확인해보면,
EarlyStopping() 함수 모니터링 기준값이
val_loss였다. 즉, val_loss 값이 더이상
개선이 되지 않으면, 학습을 중단하게 된다.
에포크가 100번 반복하게 되어 있었지만,
41번째를 실행했을 때 더 이상 오차값이
개선이 되지 않았고, EarlyStopping()함수가
작동한다. 개선이 되지 않아도 10번은 추가로
학습을 진행하게 된다.
만약 추가로 진행한 학습에도 오차값이 개선되면
학습은 계속 진행된다. 실행된 에포크 로그들을
보면 오차값 6.43%가 반복적으로 나오고 있으나,
이 이상 개선이 되지 않았기 때문에 학습이
100번의 에포크를 채우지 않고 종료되었다.
학습량이 많다고 해서 정확도가 개선되지 않는다.
개선되지 않는 학습을 계속할 이유가 없기 때문에,
케라스에서 지원하는 함수가 굉장히 효율적이다.
빨간색은 테스트 데이터고, 파란색은 학습 데이터다.
그래프로 봐도 6.43% 이상으로 오차율이 개선되지
않는 모습을 볼 수 있다.
from http://incomeplus.tistory.com/248 by ccl(A) rewrite - 2021-12-16 18:26:54