퐈니썬's LIfe - 잘 실패하자 RSS 태그 관리 글쓰기 방명록
MNIST (1)
2021-03-03 13:17:38
728x90
반응형

01. Keras

01. Keras란?

케라스는 딥러닝 모델을 간편하게 만들고, 훈련시킬 수 있는 파이썬을 위한 딥러닝 프레임워크로, 백엔드 엔진에서 제공하는 최적화된 텐서 라이브러리를 사용합니다.

케라스는 모듈 구조로 구성되어 있어 하나의 텐서 라이브러리에 국한하여 구현되어 있지 않고, 여러 가지 백엔드 엔진과 매끄럽게 연동됩니다.

현재는 TensorFlow, Theano, CNTK 3개를 백엔드 엔진으로 사용할 수 있습니다. (백엔드 엔진 변경하는 방법; https://keras.io/api/utils/backend_utils/)

 

02. Keras workflow

케라스를 사용하는 대부분의 작업 흐름은 다음과 같습니다.

  1. 입력 텐서와 타겟 텐서로 이루어진 훈련 데이터를 정의
  1. 입력과 타겟을 맵핑하는 층으로 이루어진 네트워크(모델)를 정의
  1. 손실함수, 옵티마이저, 모니터링하기 위한 측정지표를 선택하여 학습
  1. 훈련 데이터에 대해 모델의 fit() 메서드를 반복적으로 호출

 

02. Keras를 이용하여 MNIST 학습하기

01. 데이터 호출

가장 기본적인 예제인 MNIST 데이터셋을 이용하여 손글씨 데이터를 분류 예측하는 모델 제작.

케라스에서 MNIST 데이터셋을 numpy배열 형태로 호출이 가능하다.

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
# 노말라이즈를 하는, 0~1의 이미지를 기준으로 한다. (왜그런지 보쟈)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

02. 훈련, 테스트 데이터 설정

 

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels) #범주형이라고하고, 원핫인코딩 필수적인 작업
#원핫 인코딩 왜하냐 알아보기.
test_labels = to_categorical(test_labels)

03. 모델 정의

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,))) 512개의 perceptron

model.add(layers.Dense(10, activation='softmax'))
model.add(layers.Dense(len(train_labels[0]), activation='softmax'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

04. 모델 훈련

# fit() 메서드로 모델 훈련 시키기
model.fit(train_images, train_labels, epochs=5, batch_size=128)

05. 정확도 측정

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels)
print('test_acc: ', test_acc)

06. 결과 보기

Epoch 1/5
469/469 [==============================] - 1s 2ms/step - loss: 0.4283 - accuracy: 0.8745
Epoch 2/5
469/469 [==============================] - 1s 2ms/step - loss: 0.1105 - accuracy: 0.9669
Epoch 3/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0683 - accuracy: 0.9800
Epoch 4/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0469 - accuracy: 0.9867
Epoch 5/5
469/469 [==============================] - 1s 2ms/step - loss: 0.0355 - accuracy: 0.9891
313/313 [==============================] - 0s 576us/step - loss: 0.0662 - accuracy: 0.9811
test_acc:  0.9811000227928162

03. 코드내용 학습하기

01. MNIST 데이터 셋에 대하여

01. MNIST 데이터 셋?

National Institute of Standards and Technology의 줄임말로, 미국 국립표준기술연구소의 손으로 쓴 글자 데이터셋에서 숫자만 따로 뽑아낸 데이터 셋.

0~255사이의 값을 가지는 흑백 이미지이며 28x28(784) 사이즈를 지니며 7만 개의 이미지(6만 개 트레이닝 셋, 1만 개 테스트 셋)으로 구성되어있다.

02. MNIST 데이터 셋 살펴보기

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

------------------------------------------------------------------------------
test_image : shape : (10000,28,28) 28x28 이미지 10000장
test_label : shape : 10000 10000장 이미지 대한 0~9까지의 라벨
train_image : shape : (60000,28,28) 28x28 이미지 60000장
train_label : shape : 60000 60000장 이미지 대한 0~9까지의 라벨

* 각 한장에 28x28 배열이며 각 배열의 값들은 0~255의 값을 가지고 이미지로 보았을때 
0~9까지의 형상을 가진다

03. MNIST 데이터 셋 PLOT 해보기

import matplotlib.pyplot as plt
#train image의 5번째 이미지 추출
image = train_images[4]  #reshape전의 이미지

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])
#실행결과 Console: train_image 4번째 라벨은 9 

04. 모델구조 파악하기

모델을 정의하는 방법은 두 가지로, Sequential 클래스함수형 API를 사용한다.

1) Sequential 클래스 : 가장 자주 사용하는 구조로, 층을 순서대로 쌓아 올린 네트워크

2) 함수형 API : 완전히 임의의 구조를 만들 수 있는 비순환 유향 그래프(DAG) 만듬 ( 공부가 필요)

 

해당 코드에서는, Sequential 클래스 형태로 모델화하였다.

모델은 2개의 Dense 층으로 되어있고, 각각 "relu", "softmax"의 활성함수를 가진다.

마지막 층은 10개의 확률 점수가 들어 있는 배열을 반환하는 소프트맥스층이며, 각 점수는 현재 숫자 이미지가 10개의 숫자 클래스 중 하나에 속할 확률을 나타낸다(?)

#model.summary() 통해 전체적인 구조
Model: "sequential"
_________________________________________________________________
Layer (type)                 Output Shape              Param #   
=================================================================
dense (Dense)                (None, 512)               401920    
_________________________________________________________________
dense_1 (Dense)              (None, 10)                5130      
=================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
_________________________________________________________________

05. 결과 파악하기

학습된 모델이 Test 모델을 판별할때, 98.34%로 MNIST의 숫자를 맞춘다는 의미이다.

즉, 테스트 데이터 10000개 중에서 200장 가량 틀렸다는 것으로 볼 수 있다.

Test loss: 0.08414454758167267
Test accuracy: 0.9817000031471252

 

 

예측 라벨과 실제 테스트라벨이 다른 결과들 16개를 랜덤하게 선정하여 보았을때, 실제로 사람이 보아도 판별하기 쉽이낳는 것들이 있는 것을 확인 할 수 있다.

04. 전체코드

01. 학습하기

 

# 필요한 라이브러리 불러오기
from keras.datasets import mnist
from keras import models
from keras import layers
from keras.utils import to_categorical
import matplotlib.pyplot as plt
from keras.utils import plot_model

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

# 이미지 데이터 준비하기 (모델에 맞는 크기로 바꾸고 0과 1사이로 스케일링)
train_images = train_images.reshape((60000, 28 * 28))
train_images = train_images.astype('float32') / 255
test_images = test_images.reshape((10000, 28 * 28))
test_images = test_images.astype('float32') / 255

# 레이블을 범주형으로 인코딩
train_labels = to_categorical(train_labels)
test_labels = to_categorical(test_labels)

# 모델 정의하기 (여기에서는 Sequential 클래스 사용)
model = models.Sequential()
model.add(layers.Dense(512, activation='relu', input_shape=(28 * 28,)))
model.add(layers.Dense(10, activation='softmax'))
model.summary()

# 구 조확인
from IPython.display import SVG
from keras.utils import model_to_dot

# SVG(model_to_dot(model, show_shapes=True).create(prog='dot',format='svg'))

# 모델 컴파일 하기
model.compile(optimizer='rmsprop',
                loss='categorical_crossentropy',
                metrics=['accuracy'])

# fit() 메서드로 모델 훈련 시키기
history=model.fit(train_images, train_labels,epochs=10, batch_size=64, verbose=1)
# batch size가 높을수록, 속도빠르고, 정화도가 낮아.

# 테스트 데이터로 정확도 측정하기
test_loss, test_acc = model.evaluate(test_images, test_labels, verbose=0)

print('Test loss:', test_loss)
print('Test accuracy:', test_acc)
# 학습 정확성 값과 검증 정확성 값을 플롯팅 합니다.

#결과파악.

import random
import numpy as np
predicted_result = model.predict(test_images)
predicted_labels = np.argmax(predicted_result, axis=1)

test_label = np.argmax(test_labels, axis=1)

wrong_result = []

for n in range(0, len(test_label)):
    if predicted_labels[n] != test_label[n]:
        wrong_result.append(n)

samples = random.choices(population=wrong_result, k=16)

count = 0
nrows = ncols = 4

plt.figure(figsize=(12,8))

for n in samples:
    count += 1
    plt.subplot(nrows, ncols, count)
    plt.imshow(test_images[n].reshape(28, 28), cmap='Greys', interpolation='nearest')
    tmp = "Label:" + str(test_label[n]) + ", Prediction:" + str(predicted_labels[n])
    plt.title(tmp)

plt.tight_layout()
plt.show()

02. 결과보기

from keras.datasets import mnist

# MNIST 데이터셋 불러오기
(train_images, train_labels), (test_images, test_labels) = mnist.load_data()

import matplotlib.pyplot as plt
#train image의 4번째 이미지 추출
image = train_images[4]

#plot the sample
fig = plt.figure
plt.imshow(image, cmap='gray')
plt.show()
print("train_image 4번째 라벨은", train_labels[4])

num = 10
images = train_images[:num]
labels = train_labels[:num]

num_row = 2
num_col = 5

#plot images
fig, axes = plt.subplots(num_row, num_col, figsize=(1.5*num_col, 2*num_row))
for i in range(num):
    ax = axes[i//num_col, i%num_col]
    print(i//num_col, i%num_col)
    ax.imshow(images[i], cmap='gray')
    ax.set_title('Label: {}'.format(labels[i]))
plt.tight_layout()
plt.show()
728x90
반응형