일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- coursera
- 플러터
- 디지털컨텐츠과
- WebHacking
- 대나무숲
- 우분투
- graphql
- 웹프로그래밍과
- 코로나19
- 학생
- 일상
- 디미고
- 워게임
- 시스템해킹
- 웹개발
- 디미고특별전형
- 딥러닝
- Flutter
- 머신러닝
- 이비즈니스과
- pwnable.kr
- 인공지능
- 중3
- 해킹방어과
- 풀스택
- 디미고입학
- 특별전형
- TensorFlow
- 등교개학
- apollo
- Today
- Total
꿈이 너무 많은 한 대학생의 공간
7-1 향상된 숫자 인식 모델 제작하기 본문
이전 과정에서는, 우리는 MNIST 데이터셋을 이용해 숫자를 인식하는 모델을 훈련시켰습니다. 우리는 98%의 정확도를 달성할 수 있었지만, 안드로이드 앱에서 테스트할때는 아마 문제점을 느꼈을 것 입니다. 비록 앱이 그려진 숫자를 인식할 수 있어도, 정확도는 아마도 98%보다 낮을 것 입니다.
이번 과정에서는, 정확도 하락의 문제점과 확대된 데이터를 사용해 정확도를 향상시켜 볼 것입니다.
준비
Tensorflow 와 기타 라이브러리를 설치하는 것으로 시작해 봅시다.
import tensorflow as tf
from tensorflow import keras
import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import random
print(tf.__version__)
MNIST 데이터셋을 가져와 봅시다.
mnist = keras.datasets.mnist
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()
# 입력된 이미지의 각각의 픽셀값을 일반화해봅시다.
train_images = train_images / 255.0
test_images = test_images / 255.0
# 나중에 Keras의 확대된 데이터셋을 끌어내기 위해 train 데이터셋과 validate 데이터셋의
# 이미지들의 컬러 차원(color dimension)을 추가해봅시다.
train_images = np.expand_dims(train_images, axis=3)
test_images = np.expand_dims(test_images, axis=3)
처리 과정에서 쓰일 함수를 정의하면서 나중에 비교할때 쓰일 모델 구조를 가진 다중 모델을 빠르게 제작할 수 있습니다.
def create_model():
model = keras.Sequential([
keras.layers.InputLayer(input_shape=(28, 28, 1)),
keras.layers.Conv2D(filters=32, kernel_size=(3, 3), activation=tf.nn.relu),
keras.layers.Conv2D(filters=64, kernel_size=(3, 3), activation=tf.nn.relu),
keras.layers.MaxPooling2D(pool_size=(2, 2)),
keras.layers.Dropout(0.25),
keras.layers.Flatten(),
keras.layers.Dense(10, activation=tf.nn.softmax)
])
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
return model
우리의 모델이 MNIST 데이터셋에서는 98% 이상의 정확도를 달성하는 걸 확인합시다.
base_model = create_model()
base_model.fit(
train_images,
train_labels,
epochs=5,
validation_data=(test_images, test_labels)
)
정확도 하락의 문제점 찾기
MNIST 데이터셋의 숫자 이미지를 확인하고 우리가 아까 안드로이드 앱 개발에서 경험했던 정확도 하락의 원인을 추측해봅시다.
# Show the first 25 images in the training dataset.
plt.figure(figsize=(10,10))
for i in range(25):
plt.subplot(5,5,i+1)
plt.xticks([])
plt.yticks([])
plt.grid(False)
plt.imshow(np.squeeze(train_images[i], axis=2), cmap=plt.cm.gray)
plt.xlabel(train_labels[i])
plt.show()
우리는 같은 크기의 숫자 이미지 25개를 가지고 있고, 그들은 모두 이미지 정중앙에 위치해 있습니다.
이 가정이 MNIST 데이터셋에서는 성립할 지 확인해 봅시다.
# 숫자가 어디에 위치하는지 반환하는 유틸리티 함수입니다.
def digit_area(mnist_image):
# 색을 제거합니다.
mnist_image = np.squeeze(mnist_image, axis=2)
# 세로로 숫자로부터의 픽셀값의 리스트를 가져옵니다.
x_nonzero = np.nonzero(np.amax(mnist_image, 0))
x_min = np.min(x_nonzero)
x_max = np.max(x_nonzero)
# 가로로 숫자로부터의 픽셀값의 리스트를 가져옵니다.
y_nonzero = np.nonzero(np.amax(mnist_image, 1))
y_min = np.min(y_nonzero)
y_max = np.max(y_nonzero)
return [x_min, x_max, y_min, y_max]
# MNIST 데이터셋으로부터의 숫자를 포함하는 위치를 계산합니다.
digit_area_rows = []
for image in train_images:
digit_area_row = digit_area(image)
digit_area_rows.append(digit_area_row)
digit_area_df = pd.DataFrame(
digit_area_rows,
columns=['x_min', 'x_max', 'y_min', 'y_max']
)
digit_area_df.hist()
아래와 같은 히스토그램을 통해, MNIST 데이터셋으로부터의 숫자는 이미지 정중앙 확실한 위치에 딱 맞는 것을 확인할 수 있습니다.
하지만, 안드로이드 앱에서 숫자를 그릴 때, 위의 데이터처럼 정확히 정중앙에 그리기 위해 집중하지는 않았을 것입니다. 머신러닝 모델은 그려진 숫자를 제대로 보지 못해 결과가 이상하게 나온 것이고, 특히 정중앙 밖에 숫자를 그렸을 때 정확도가 하락했을 것입니다.
이제 우리의 가정이 맞다는 것을 증명하기 위해 확대된 데이터를 MNIST 데이터셋에 추가합시다.
우리는 회전, 가로와 세로, 기울임, 확대를 추가함으로써 우리의 MNIST 데이터셋을 왜곡할 것입니다.
# 확대된 데이터를 정의합시다.
datagen = keras.preprocessing.image.ImageDataGenerator(
rotation_range=30,
width_shift_range=0.25,
height_shift_range=0.25,
shear_range=0.25,
zoom_range=0.2
)
# MNIST 데이터셋으로부터 확대된 데이터셋을 제작합니다.
train_generator = datagen.flow(train_images, train_labels)
test_generator = datagen.flow(test_images, test_labels)
확대된 데이터셋으로 우리가 아까 훈련시켰던 모델을 평가해보고 정확도가 하락하는지 안하는지를 확인해봅시다.
base_model.evaluate(test_generator)
아마도 확대된 데이터셋에서는 정확도가 상당히 낮아져 40% 이하로 기록된 것을 볼 수 있을 것입니다.
확대된 데이터셋과 정확도 향상시키기
개발 환경에서 더 잘 작동하도록 우리의 확대된 데이터셋을 학습시켜 봅시다.
improved_model = create_model()
improved_model.fit(train_generator, epochs=5, validation_data=test_generator)
우리는 학습시키는 중 더 왜곡된 이미지들을 보고 학습했기 떄문에, 왜곡된 test 이미지들을 학습한 모델의 정확도는 90% 이상으로 향상됨을 알 수 있습니다.
Tensorflow Lite로 변환하기
상향된 모델을 Tensorflow Lite 로 변환하고 안드로이드 앱으로 재배포 해봅시다.
# Keras 모델을 Tensorflow Lite 형식과 양자화된 형식으로 변환
converter = tf.lite.TFLiteConverter.from_keras_model(improved_model)
converter.optimizations = [tf.lite.Optimize.DEFAULT]
tflite_quantized_model = converter.convert()
# 양자화된 모델을 download 디렉토리로 저장
f = open('mnist.tflite', "wb")
f.write(tflite_quantized_model)
f.close()
# 숫자 인식 모델을 다운로드
from google.colab import files
files.download('mnist.tflite')
수고하셨습니다!
본 과정이 다 끝났습니다. 3번째 과정으로 돌아가 안드로이드 앱에 재배포한 뒤 정확도가 올랐는지 안올랐는지 확인해 보세요.
본 강의는 구글의 Codelab 강의 중 "Build a handwritten digit classifier app with Tensorflow Lite" 강의를
번역할 것이며, 제가 직접 번역하였기에 오역과 의역이 있음을 알립니다.
'튜토리얼 번역 > 손글씨 숫자 분류기 만들기' 카테고리의 다른 글
8. 강좌의 끝 (0) | 2020.04.22 |
---|---|
7. 심화: 정확도 향상시키기 (0) | 2020.04.22 |
6. 배포 및 테스트 (0) | 2020.04.22 |
5. Tensorflow Lite 로 숫자 인식하기 (0) | 2020.04.22 |
4. Tensorflow Lite 인터프리터 초기화 (1) | 2020.04.22 |