Eggs Sunny Side Up
본문 바로가기
Computer Engineering/딥러닝

mlp_손글씨숫자 이미지_다중분류

by guswn100059 2023. 6. 29.
# ex05_mlp_손글씨숫자 이미지_다중분류

### 목표
  - 신경망을 활용해서 다중분류에 필요한 keras의 기능을 활용해보자
  - 이미지 데이터를 다루는 방법을 이해해보자
  - 직접 손으로 쓴 글씨를 인식하는 것까지 연결해보자

# 환경셋팅
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

# 손글씨 숫자 데이터 불러오기
from tensorflow.keras.datasets import mnist

# 불러오기
data = mnist.load_data()
data

(X_train, y_train), (X_test, y_test) = mnist.load_data()
# 크기확인
print(X_train.shape, y_train.shape)
print(X_test.shape, y_test.shape)

# 1. 이미지 1장 확인
# or 여러장 그림 출력해서 확인

# 2. 클래스 답 데이터 확인(중복없이 클래스 개수 확인, 클래스별로 몇개가 담겼는지 확인)

# 3. 답 데이터 전처리(원핫인코딩)

# 4. mlp 모델 생성, 학습

# 이미지 1장 확인
X_train[1].max()
plt.imshow(X_train[1])
plt.show()

# 답 데이터 확인
# 출력층 클래스 10개
np.unique(y_train, return_counts=True)
np.unique(y_train).size

# 답 데이터 전처리(원핫인코딩)
y_train_oh = pd.get_dummies(y_train)
y_test_oh = pd.get_dummies(y_test)

y_train_oh.shape, y_test_oh.shape

# 뼈대 구축하는 도구
from tensorflow.keras import Sequential
# 층 내용 정의, 2차원->1차원
from tensorflow.keras.layers import Dense, Flatten
# 최적화함수 불러와서 매개변수 값 설정하는 도구
from tensorflow.keras.optimizers import SGD, Adam

# mlp 모델 생성
# 뼈대 구축
model = Sequential()
# 입력층
model.add(Flatten(input_shape=(28, 28)))
# 중간층
model.add(Dense(200, activation='relu'))
model.add(Dense(100, activation='relu'))
model.add(Dense(50, activation='relu'))
# 출력층
model.add(Dense(10, activation='softmax'))
# compile
model.compile(loss='categorical_crossentropy',
                optimizer = 'Adam',
                metrics=['accuracy'])
# ★ 답데이터 원핫인코딩 안했을 때 사용하는 다중분류
# 'sparse_categorical_crossentropy' 

# train_test_split import
from sklearn.model_selection import train_test_split
X_train, X_val, y_train, y_val = train_test_split(X_train, y_train,
                                                 test_size=0.3,
                                                 random_state=2)
print(X_train.shape, y_train.shape)
print(X_val.shape, y_val.shape)

# 모델 학습
from tensorflow.keras.callbacks import EarlyStopping

# 조기 학습 중단
f_early = EarlyStopping(monitor='val_accuracy',
                        # monitor의 값의 개선을 몇 번이나 기다려 줄 것인지 설정
                        patience=5)

# => 모델 학습시 val_accuracy가 5번의 반복을 진행할 동안 개선이 되지 않으면
# 학습을 중단시키겠음!

h = model.fit(X_train, y_train_oh,
              epochs=20,
              # validation_split=0.3,
              # 검증 데이터가 있을 시에는 validation_data 사용가능
              validation_data = (X_val, y_val),
              batch_size=64)
h

model.evaluate(X_test, y_test_oh)

h.history['accuracy']

plt.figure(figsize=(10,3))
plt.plot(range(1, 21), h.history['accuracy'], label='relu+Adam')
plt.plot(range(1, 21), h.history['val_accuracy'], label='relu+Adam')
plt.legend()
plt.show()

X_test[[1]]

# 예측
# 1장에 대해서 예측하게 만들기
# 1번째 이미지

X_test[1].max()
plt.imshow(X_test[1])
plt.show()

pred = model.predict(X_test[[1]])
print(pred)
# np.argmax() == pred.argmax()
print('예측한 숫자 : ', pred.argmax())
print('실제 숫자 : ', y_test[1])

### 직접 쓴 숫자를 인식시켜보자
  - gradio 실시간으로 서버와 모델을 연동하는 모듈(gradio, streamlit도 많이 활용
  - 편리한 인터페이스를 제공하기 때문에 활용해보자

!pip install gradio

import gradio as gr
def recognition(img):
  # 이미지 크기 변환
  img = img.reshape(-1, 784) # 행 1, 열 784
  pred = model.predict(img)
  #확률 정보에서 가장 값이 큰 인덱스 번호 -> 클래스 값
  result = pred.argmax()
  return f'{result}'

gr.Interface(fn=recognition, inputs=gr.Sketchpad(brush_radius=0.5), 
             outputs='label').launch()

댓글