### 2021.12.17
MNIST 손글씨 이미지 데이터셋
MNIST 데이터셋은 위 그림과 같이 0에서 9까지 10가지로 분류될 수 있는 손글씨 숫자 이미지 70,000개로 이루어져 있습니다.
각 이미지는 28×28 픽셀로 구성되고 각 픽셀은 아래와 같이 0~255 사이의 숫자 행렬로 표현됩니다.
이러한 60,000개의 이미지는 인공 신경망의 훈련 (Training)에 사용되고, 10,000개의 이미지는 테스트 (Test)에 사용됩니다.
이번 페이지에서는 Dense 층들로 구성되는 완전 연결된 인공신경망 (Fully-Connected Neural Network)을 이용해서 MNIST 데이터셋을 분류해 보겠습니다.
예제
import tensorflow as tf
# 1. MNIST 데이터셋 임포트
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
# 2. 데이터 전처리
x_train, x_test = x_train/255.0, x_test/255.0
# 3. 모델 구성
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
# 4. 모델 컴파일
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
# 5. 모델 훈련
model.fit(x_train, y_train, epochs=5)
# 6. 정확도 평가
test_loss, test_acc = model.evaluate(x_test, y_test)
print('테스트 정확도:', test_acc)
model.save('my_model1.h5')
#Out[]
Epoch 1/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.2026 - accuracy: 0.9408
Epoch 2/5
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0808 - accuracy: 0.9753
Epoch 3/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0514 - accuracy: 0.9837
Epoch 4/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0376 - accuracy: 0.9880
Epoch 5/5
1875/1875 [==============================] - 7s 4ms/step - loss: 0.0266 - accuracy: 0.9916
313/313 [==============================] - 1s 2ms/step - loss: 0.0643 - accuracy: 0.9811
테스트 정확도: 0.9811000227928162
설명
0. tensorflow 불러오기
#tensorflow 라이브러리를 불러옵니다.
import tensorflow as tf
1. MNIST 데이터셋 임포트
mnist = tf.keras.datasets.mnist
(x_train, y_train), (x_test, y_test) = mnist.load_data()
tensorflow에서 직접 MNIST 손글씨 이미지 데이터셋을 불러와서 사용합니다.
load_data() 함수는 x_train, y_train, x_test, y_test 네 개의 NumPy 어레이를 반환합니다.
x_train, x_test는 28×28 픽셀의 각 손글씨 이미지 데이터이고, y_train, y_test는 분류에 사용되는 0~9 사이의 레이블 값을 갖습니다.
#In[1]
print("x_train 데이터 형태 :", x_train.shape)
print("x_train[0] 데이터 형태 :", x_train[0].shape)
print("y_train 데이터 형태 :", y_train.shape)
#Out[1]
x_train 데이터 형태 : (60000, 28, 28)
x_train[0] 데이터 형태 : (28, 28)
y_train 데이터 형태 : (60000,)
#In[2]
num = x_train[0]
for i in range(28):
for j in range(28):
print("{:4d}".format(num[i][j]), end="")
print()
#Out[2]
각 이미지는 28×28 픽셀로 구성되고 각 픽셀은 아래와 같이 0~255 사이의 숫자 행렬로 표현됩니다.
이러한 60,000개의 이미지는 인공 신경망의 훈련 (Training)에 사용되고, 10,000개의 이미지는 테스트 (Test)에 사용됩니다.
이번 페이지에서는 Dense 층들로 구성되는 완전 연결된 인공신경망 (Fully-Connected Neural Network)을 이용해서 MNIST 데이터셋을 분류해 보겠습니다.
2. 데이터 전처리
# 0 ~ 255.0 사이의 값을 갖는 픽셀값들을 0~1.0 사이의 값을 갖도록 변환합니다.
x_train, x_test = x_train/255.0, x_test/255.0
3. 모델 구성
model = tf.keras.models.Sequential([
tf.keras.layers.Flatten(input_shape=(28, 28)),
tf.keras.layers.Dense(512, activation=tf.nn.relu),
tf.keras.layers.Dense(10, activation=tf.nn.softmax)
])
tf.keras.models.Sequential()을 이용해서 인공신경망 모델을 구성합니다.
입력층 (Input layer)에서 Flatten()을 이용해서 28×28 픽셀의 값을 784개의 1차원 배열로 변환합니다.
다음 두 개의 뉴런 층 (Neuron layer)은 Dense()를 이용해서 완전 연결된 층 (Fully-connected layer)를 구성합니다.
각 층은 512개와 10개의 인공 뉴런 노드를 갖고 활성화 함수 (activation function)로는 각각 ReLU (tf.nn.relu)와 소프트맥스 (tf.nn.softmax)를 사용합니다.
4. 모델 컴파일
model.compile(optimizer='adam',
loss='sparse_categorical_crossentropy',
metrics=['accuracy'])
다음은 모델 컴파일 단계입니다. 학습 과정에서 손실 함수 (Loss function)를 줄이기 위해 사용되는 optimizer로는 Adam (Adaptive Momentum estimation)을 사용합니다.
손실 함수는 ‘sparse_categorical_crossentropy’를 지정하고, 평가 지표로는 정확도 (accuracy)를 사용합니다.
정확도는 테스트 이미지 중 올바르게 분류한 비율을 의미합니다.
5. 모델 훈련
#In[]
model.fit(x_train, y_train, epochs=5)
#Out[]
Epoch 1/5
1875/1875 [==============================] - 10s 5ms/step - loss: 0.1985 - accuracy: 0.9413
Epoch 2/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0806 - accuracy: 0.9743
Epoch 3/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0526 - accuracy: 0.9835
Epoch 4/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0373 - accuracy: 0.9881
Epoch 5/5
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0275 - accuracy: 0.9911
<tensorflow.python.keras.callbacks.History at 0x7fcb10ae1d90>
학습 과정은 위와 같이 이루어지며, 학습 데이터에 대한 정확도가 출력됩니다.
model.fit() 메서드에 학습 데이터와, 레이블, 에포크를 순서대로 입력하면, 학습이 이루어집니다.
에포크(epoch)는 60,000개의 전체 학습 데이터를 몇 번 반복해서 학습할지를 의미합니다.
model.save('my_model2.h5')
6. 정확도 평가
#In[]
test_loss, test_acc = model.evaluate(x_test, y_test)
print('테스트 정확도:', test_acc)
#Out[]
313/313 [==============================] - 1s 3ms/step - loss: 0.0707 - accuracy: 0.9785
테스트 정확도: 0.9785000085830688
결과는 위와 같습니다.
model.evaluate()를 이용해서 10,000개의 테스트 샘플에 대해 손실 (loss)과 정확도 (accuracy)를 평가합니다.
간단한 인공신경망과 다섯 번 에포크의 학습만으로 98.02%의 정확도로 MNIST 이미지를 분류할 수 있음을 알 수 있습니다.
Matplotlib을 이용해서 에포크에 따른 정확도 (accuracy)와 손실 (loss) 값을 확인할 수 있습니다.
#In[]
loss, accuracy = [], []
for i in range(10):
model.fit(x_train, y_train, epochs=1)
loss.append(model.evaluate(x_test, y_test)[0])
accuracy.append(model.evaluate(x_test, y_test)[1])
print(accuracy)
#Out[]
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0202 - accuracy: 0.9933
313/313 [==============================] - 1s 2ms/step - loss: 0.0603 - accuracy: 0.9814
313/313 [==============================] - 1s 2ms/step - loss: 0.0603 - accuracy: 0.9814
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0168 - accuracy: 0.9942
313/313 [==============================] - 1s 2ms/step - loss: 0.0819 - accuracy: 0.9775
313/313 [==============================] - 1s 2ms/step - loss: 0.0819 - accuracy: 0.9775
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0148 - accuracy: 0.9950
313/313 [==============================] - 1s 3ms/step - loss: 0.0738 - accuracy: 0.9806
313/313 [==============================] - 1s 3ms/step - loss: 0.0738 - accuracy: 0.9806
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0134 - accuracy: 0.9955
313/313 [==============================] - 1s 3ms/step - loss: 0.0662 - accuracy: 0.9833
313/313 [==============================] - 1s 2ms/step - loss: 0.0662 - accuracy: 0.9833
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0101 - accuracy: 0.9965
313/313 [==============================] - 1s 2ms/step - loss: 0.0771 - accuracy: 0.9820
313/313 [==============================] - 1s 2ms/step - loss: 0.0771 - accuracy: 0.9820
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0112 - accuracy: 0.9964
313/313 [==============================] - 1s 2ms/step - loss: 0.0744 - accuracy: 0.9821
313/313 [==============================] - 1s 2ms/step - loss: 0.0744 - accuracy: 0.9821
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0075 - accuracy: 0.9974
313/313 [==============================] - 1s 2ms/step - loss: 0.0820 - accuracy: 0.9828
313/313 [==============================] - 1s 2ms/step - loss: 0.0820 - accuracy: 0.9828
1875/1875 [==============================] - 8s 4ms/step - loss: 0.0104 - accuracy: 0.9968
313/313 [==============================] - 1s 3ms/step - loss: 0.1053 - accuracy: 0.9808
313/313 [==============================] - 1s 2ms/step - loss: 0.1053 - accuracy: 0.9808
1875/1875 [==============================] - 10s 5ms/step - loss: 0.0066 - accuracy: 0.9979
313/313 [==============================] - 1s 2ms/step - loss: 0.0901 - accuracy: 0.9814
313/313 [==============================] - 1s 2ms/step - loss: 0.0901 - accuracy: 0.9814
1875/1875 [==============================] - 9s 5ms/step - loss: 0.0084 - accuracy: 0.9975
313/313 [==============================] - 1s 3ms/step - loss: 0.0798 - accuracy: 0.9840
313/313 [==============================] - 1s 2ms/step - loss: 0.0798 - accuracy: 0.9840
[0.9814000129699707, 0.9775000214576721, 0.9805999994277954, 0.983299970626831, 0.9819999933242798, 0.9821000099182129, 0.9828000068664551, 0.9807999730110168, 0.9814000129699707, 0.984000027179718]
1회의 에포크마다 model.evaluate()의 loss, accuracy 값을 저장합니다.
결과는 아래와 같습니다.
model.save('my_model3.h5')
## Ex 10-6. MNIST 손글씨 인식 프로그램.
import sys
from PyQt5.QtWidgets import *
from PyQt5.QtGui import *
from PyQt5.QtCore import *
import numpy as np
import tensorflow as tf
class MyApp(QMainWindow):
def __init__(self):
super().__init__()
self.image = QImage(QSize(400, 400), QImage.Format_RGB32)
self.image.fill(Qt.white)
self.drawing = False
self.brush_size = 30
self.brush_color = Qt.black
self.last_point = QPoint()
self.loaded_model = None
self.initUI()
def initUI(self):
menubar = self.menuBar()
menubar.setNativeMenuBar(False)
filemenu = menubar.addMenu('File')
load_model_action = QAction('Load model', self)
load_model_action.setShortcut('Ctrl+L')
load_model_action.triggered.connect(self.load_model)
save_action = QAction('Save', self)
save_action.setShortcut('Ctrl+S')
save_action.triggered.connect(self.save)
clear_action = QAction('Clear', self)
clear_action.setShortcut('Ctrl+C')
clear_action.triggered.connect(self.clear)
filemenu.addAction(load_model_action)
filemenu.addAction(save_action)
filemenu.addAction(clear_action)
self.statusbar = self.statusBar()
self.setWindowTitle('MNIST Classifier')
self.setGeometry(300, 300, 400, 400)
self.show()
def paintEvent(self, e):
canvas = QPainter(self)
canvas.drawImage(self.rect(), self.image, self.image.rect())
def mousePressEvent(self, e):
if e.button() == Qt.LeftButton:
self.drawing = True
self.last_point = e.pos()
def mouseMoveEvent(self, e):
if (e.buttons() & Qt.LeftButton) & self.drawing:
painter = QPainter(self.image)
painter.setPen(QPen(self.brush_color, self.brush_size, Qt.SolidLine, Qt.RoundCap))
painter.drawLine(self.last_point, e.pos())
self.last_point = e.pos()
self.update()
def mouseReleaseEvent(self, e):
if e.button() == Qt.LeftButton:
self.drawing = False
arr = np.zeros((28, 28))
for i in range(28):
for j in range(28):
arr[j, i] = 1 - self.image.scaled(28, 28).pixelColor(i, j).getRgb()[0] / 255.0
arr = arr.reshape(-1, 28, 28)
if self.loaded_model:
pred = self.loaded_model.predict(arr)[0]
pred_num = str(np.argmax(pred))
self.statusbar.showMessage('숫자 ' + pred_num + '입니다.')
def load_model(self):
fname, _ = QFileDialog.getOpenFileName(self, 'Load Model', '')
if fname:
self.loaded_model = tf.keras.models.load_model(fname)
self.statusbar.showMessage('Model loaded.')
def save(self):
fpath, _ = QFileDialog.getSaveFileName(self, 'Save Image', '', "PNG(*.png);;JPEG(*.jpg *.jpeg);;All Files(*.*) ")
if fpath:
self.image.scaled(28, 28).save(fpath)
def clear(self):
self.image.fill(Qt.white)
self.update()
self.statusbar.clearMessage()
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = MyApp()
sys.exit(app.exec_())
'K-디지털트레이닝 > 인공지능' 카테고리의 다른 글
[인공지능] #7 뉴런층의 출력 확인하기 (0) | 2021.12.17 |
---|---|
[인공지능] #6 뉴런층의 속성 확인하기 (0) | 2021.12.17 |
[인공지능] #5 AND 로직 연산 학습하기 (0) | 2021.12.16 |
[인공지능] #4 Optimizer 사용하기 (0) | 2021.12.16 |
[인공지능] #3 손실 함수 살펴보기 (0) | 2021.12.16 |