Machine Learning/TensorFlow

[Machine Learning] Neural Network MNIST 데이터 처리

데이터 세상 2021. 3. 4. 22:41
728x90
반응형

MNIST Dataset

  • 미국 국립표준기술원(NIST)이 고등학생과 인구조사국 직원 7만명이 쓴 숫자를 이용해 만든 데이터
  • 60,000개의 트레이닝 셋과 10,000개의 테스트 셋으로 이루어짐
  • 숫자는 0~1까지 값을 갖는 고정 크기 이미지(28x28 픽셀)
  • 각 픽셀은 밝기 정도에 따라 0부터 255값으로 표현

Data Normalization

  • 데이터의 폭이 클 때 적절한 값으로 분산의 정돌르 바꿔주는 과정
  • (요소값 - 최소값) / (최대값-최소값),  요소 값 / 최대 값

import tensorflow as tf
import matplotlib.pyplot as plt
import numpy
import os

# MNIST 데이터 불러오기
(X_train, Y_train), (X_test, Y_test) = tf.keras.datasets.mnist.load_data()
## X_train shape : ( 이미지 장수, 이미지 가로 , 이미지 세로 )
## Y_train : (정답 갯수, ) - > [ 0 ,1, 2, 4 ,5, 5, ....  ]

## X_train shape : ( 이미지 장수, 가로 , 세로 ) 이차원 이어서 
## Neural Network(=Multi Layer Perceptron ) 입력 차원인 1차원으로 변경
## reshape 사용하여 차원 변형, 28x28= 784
X_train = X_train.reshape(X_train.shape[0], 784).astype('float32')
X_test = X_test.reshape(X_test.shape[0], 784).astype('float32')

##  [ 0 ,1, 2, 4 ,5, 5, ....  ] -> [ [1 0 0 0 0 0 0 0], [0 1 0 0 0 0 0.. ] , ] 원핫인코딩
Y_train = tf.keras.utils.to_categorical(Y_train)
Y_test =  tf.keras.utils.to_categorical(Y_test)

# 모델 설계
# method 1
input_Layer = tf.keras.layers.Input(shape=(784,)) ## 데이터 입력
x = tf.keras.layers.Dense(512, activation='relu')(input_Layer) # hidden layer1
x = tf.keras.layers.Dense(512, activation='relu')(x)
## out은 task를 수행.
## 10개의 class를 분류해야 함
## 분류해야하는 class  0~ 9: 10개 그래서 아웃풋 perceptron 10개
## 각각의 perceptron이 출력값을 가지면 -> 상관관계가 없음.
## 출력을 확률처럼 맵핑 하고자 softmax 를 사용하면 출력이 확률처럼나오게 된다. 
## 때문에 멀티 클레스피케이션에서 softmax를 쓰는게 일반적.

## 분류해야하는 class  0~ 9: 10개 그래서 아웃풋 perceptron 10개
Out_Layer= tf.keras.layers.Dense(10, activation='softmax')(x)

model = tf.keras.Model(inputs=[input_Layer], outputs=[Out_Layer])
model.summary()

# 모델 컴파일
loss=tf.keras.losses.categorical_crossentropy
optimizer = tf.keras.optimizers.Adam(learning_rate=0.001)
metric=tf.keras.metrics.categorical_accuracy
model.compile(loss=loss,
             optimizer=optimizer,
             metrics=[metric])

# 베스트 모델 저장을 위한 디렉토리 선언
MODEL_DIR = './MNIST_model/'
if not os.path.exists(MODEL_DIR):
    os.mkdir(MODEL_DIR)

## 저장한 모델의 주소와 이름.
modelpath="./MNIST_model/{epoch:02d}-{val_loss:.4f}.hdf5"

## 사용할 callback 함수 선언.
callback_list=[tf.keras.callbacks.ModelCheckpoint(filepath=modelpath, monitor='val_loss', verbose=1, save_best_only=True),
               tf.keras.callbacks.EarlyStopping(monitor='val_loss', patience=10)]

# 모델의 실행
# validation_data 옵션으로 테스트 데이터만 넣어주어서 검증 데이터 분류가 가능
history = model.fit(X_train, Y_train, validation_split=0.2, epochs=30, batch_size=1000, verbose=1, callbacks=callback_list)
print(history.history.keys())

# 테스트 정확도 출력
print("\n Test Accuracy: %.4f" % (model.evaluate(X_test, Y_test)[1]))
# 테스트 셋의 오차
val_loss = history.history['val_loss']

# 학습셋의 오차
loss = history.history['loss']

# 그래프로 표현
x_len = numpy.arange(len(val_loss))
plt.plot(x_len, val_loss, marker='.', c="red", label='Testset_loss')
plt.plot(x_len, loss, marker='.', c="blue", label='Trainset_loss')

# 그래프에 그리드를 주고 레이블을 표시
plt.legend(loc='upper right')
# plt.axis([0, 20, 0, 0.35])
plt.grid()
plt.xlabel('epoch')
plt.ylabel('loss')
plt.show()

 

Solution #2

  • 한 이미지의 입력 데이터는 784개의 속성 값을 가지므로 입력 노드는 784개
  • 은닉층은 3개 이상 구성, 노드는 오버피팅이 발생되기 전까지 노드 수를 늘림
  • 여러 개의 은닉층을 사용하므로 은닉층의 활성화 함수는 LeRU 사용
  • 분류 모델이므로 출력층의 활성화 함수는 Softmax 사용
  • 출력은 0~9 숫자를 구분해야 하므로 출력 노드수는 10개
  • 출력층 활성화 함수는 Softmax를 사용했기 때문에 오차 함수는 cross entropy를 사용
  • 학습을 용이하게 하기 위해 각 weight 값을 xavier로 초기화
from tensorflow.keras.datasets import mnist
from tensorflow.keras.utils import  to_categorical
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Dense
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf


np.random.seed(3)
tf.random.set_seed(3)

(x_train, y_train), (x_test, y_test) = mnist.load_data()
x_train = x_train.reshape(x_train.shape[0], 784).astype(float)/255
x_test = x_test.reshape(x_test.shape[0], 784).astype(float)/255

y_train = to_categorical(y_train, 10)
y_test = to_categorical(y_test, 10)


model = Sequential()
model.add(Dense(512, input_dim=784, activation='relu'))
model.add(Dense(256, activation='relu'))
model.add(Dense(10, activation='softmax'))

model.compile(loss='categorical_crossentropy',
              optimizer='adam',
              metrics=['accuracy'])

'''
verbose 0: silence
verbose 1: progressbar
verbose 2: oneline acc, loss
'''
result = model.fit(x_train, y_train,
                   validation_split=0.3,
                   epochs=20,
                   batch_size=200,
                   verbose=2)
print('accuracy:', model.evaluate(x_test, y_test)[1])
y_vloss = result.history['val_loss']
y_loss = result.history['loss']
x_len = np.arange((len(y_loss)))
plt.plot(x_len, y_vloss, '.', c='red', label='validation loss')
plt.plot(x_len, y_loss, '.', c='blue', label='train loss')
plt.legend(loc='best')
plt.show()
728x90
반응형