[딥러닝 Express] Chapter 07. MLP와 케라스 라이브러리 - [Lab: 케라스를 이용한 MNIST 숫자 인식]

배규리·2024년 1월 23일

AI 기초

목록 보기
15/32
post-thumbnail

사실 그냥 미니 소단원인데 나중에 이 코드만 다시 보고 싶을거같아서 하나의 게시물로 작성하는 중이다!

케라스를 이용한 MNIST 숫자 인식

우리가 할 일🤔

우리가 사용할 학습 데이터는 필기체 숫자 이미지이다.
많은 수의 필기체 이미지로 신경망을 학습할 것이다!

결과적으로 맨 마지막에 생성한 모델이 이미지(28x28)가 주어졌을 때 이 이미지가 어떤 숫자인지를 출력해야 한다.

이전에 선형 모델로 MNIST 숫자 인식 모델을 생성한 적이 있었다.

이젠 선형 모델이 아닌 신경망 모델로 구현할 것이다😊

1) 숫자 데이터와 라이브러리 불러오기

import matplotlib.pyplot as plt
import tensorflow as tf

(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

2) 훈련 데이터와 테스트 데이터의 넘파이 배열 형태 확인 및 이미지 출력

print(train_images.shape)
print(train_labels)
print(test_images.shape)

plt.imshow(train_images[0], cmap='Greys')


3) 신경망 모델 구축하기

먼저 Sequential 모델을 생성한다.

이어서 은닉층을 위한 Dense 레이어를 추가했다.
이때 input_shape를 지정해주면 입력 레이어를 따로 만들 필요가 없어진다.
즉 이 Dense 레이어에 입력으로 28x28=784개가 연결된다는 것을 의미한다.
활성화 함수는 ReLU로 지정해주었다.

마지막으로 출력층을 위한 Dense 레이어를 추가해주었다.
출력층에는 10개의 유닛이 있고 각 유닛이 하나의 숫자를 의미한다.
이때 활성화 함수는 Sigmoid로 지정해주었다.

model = tf.keras.models.Sequential()

model.add(tf.keras.layers.Dense(512, activation = 'relu', input_shape = (784, )))
model.add(tf.keras.layers.Dense(10, activation = 'sigmoid'))

4) 모델 컴파일

모델 컴파일 시에 옵티마이저와 손실함수, 지표를 정의를 함께 정의해준다.

  • 옵티마이저(optimizer): 손실 함수를 기반으로 신경망의 파라미터를 최적화하는 알고리즘
  • 손실함수(loss): 신경망의 출력과 정답 간의 오차를 계산하는 함수
  • 지표(metrics): 훈련과 테스트 과정에서 사용되는 척도
model.compile(optimizer = 'rmsprop',
              loss = 'mse',
              metrics = ['accuracy'])

5) 데이터 전처리

데이터를 신경망의 입력과 맞춰주어야 한다.
현재 훈련 데이터는 0~255 사이의 값을 가진 2차원 배열 형태로 되어 있다.
하지만 신경망에서는 0~1사이의 값만 받을 수 있고, 또 현재의 신경망은 1차원 배열 형태만 받을 수 있다.
따라서 28x28 넘파이 배열을 784x1 형태의 넘파이 배열로 reshape해주어야 한다.

train_images = train_images.reshape((60000, 784))
train_images = train_images.astype('float32') / 255.0

test_images = test_images.reshape((10000, 784))
test_images = test_images.astype('float32') / 255.0

이 과정으로 2차원 이미지를 1차원으로 평탄화하였고,
0에서 255까지의 값을 가지는 픽셀 값들을 0.0에서 1.0 사이의 실수값으로 변환하였다.
=> 8장에서 다룰 정규화와 연관되어 있다.

6) 정답 레이블 형태 변경

현재 정답 레이블은 5, 0, 4, ... 이런 꼴이다.
그러나 정답 레이블이 5라면 [0, 0, 0, 0, 0, 1, 0, 0, 0, 0] 이런 꼴이 되어야 한다.
to_categorical() 함수를 사용해준다.

train_labels = tf.keras.utils.to_categorical(train_labels)
test_labels = tf.keras.utils.to_categorical(test_labels)

7) 학습

model.fit(train_images, train_labels, epochs = 5, batch_size = 128)

8) 모델 확인

model.summary()
test_loss, test_acc = model.evaluate(test_images, test_labels)
print("테스트 정확도: ", test_acc)

정확도가 약 98% 정도로 도출되었다.

9) 테스트

실제로 내가 숫자를 그려서 데이터를 집어넣고 확인해봐야겠다!🤔

짠 내가 그린 숫자 7..!

일단 이미지를 불러오기 위해 터미널에서 OpenCV 설치

activate deep
pip install opencv-python

그리고 라이브러리 불러와서 테스트 시작-!

import cv2 as cv
image = cv.imread('7.png', cv.IMREAD_GRAYSCALE)
print(image.shape)
image = cv.resize(image, (28,28))
image = image.astype('float32')
image = image.reshape(1, 784)
image = 255-image
image = image/255.0

pred = model.predict(image.reshape(1, 784), batch_size = 1)
print("추정된 숫자 = ", pred.argmax())

대박...! 맞췄다!


전체 코드

import matplotlib.pyplot as plt
import tensorflow as tf

(train_images, train_labels), (test_images, test_labels) = tf.keras.datasets.mnist.load_data()

print(train_images.shape)
print(train_labels)
print(test_images.shape)

plt.imshow(train_images[0], cmap='Greys')

model = tf.keras.models.Sequential()

model.add(tf.keras.layers.Dense(512, activation = 'relu', input_shape = (784, )))
model.add(tf.keras.layers.Dense(10, activation = 'sigmoid'))

model.compile(optimizer = 'rmsprop',
              loss = 'mse',
              metrics = ['accuracy'])


train_images = train_images.reshape((60000, 784))
train_images = train_images.astype('float32') / 255.0

test_images = test_images.reshape((10000, 784))
test_images = test_images.astype('float32') / 255.0

train_labels = tf.keras.utils.to_categorical(train_labels)
test_labels = tf.keras.utils.to_categorical(test_labels)

model.fit(train_images, train_labels, epochs = 5, batch_size = 128)

model.summary()
test_loss, test_acc = model.evaluate(test_images, test_labels)
print("테스트 정확도: ", test_acc)

import cv2 as cv
image = cv.imread('7.png', cv.IMREAD_GRAYSCALE)
print(image.shape)
image = cv.resize(image, (28,28))
image = image.astype('float32')
image = image.reshape(1, 784)
image = 255-image
image = image/255.0

pred = model.predict(image.reshape(1, 784), batch_size = 1)
print("추정된 숫자 = ", pred.argmax())

뿌듯하다...
역시 AI는 이런 맛에 하는 듯!
정말 간단한 예제지만 너무 흥미로운 것같다🥹

profile
백엔드 개발은 취미인 AI 개발자🥹

0개의 댓글