NeuroWhAI의 잡블로그

[Keras] ANN(인공 신경망)으로 손글씨 분류 학습하기 본문

개발 및 공부/라이브러리&프레임워크

[Keras] ANN(인공 신경망)으로 손글씨 분류 학습하기

NeuroWhAI 2018. 2. 27. 19:02


쓰읍... 케라스 책은 오타도 많고 검수를 제대로 안한건지 뭔가 나사 빠진듯한 모습이라 첫인상이 별로 안좋습니다 ㅠㅠ...

간단한 인공 신경망으로 MNIST 이미지 분류를 학습하는 예제입니다.


코드:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
#-*- coding: utf-8 -*-
 
import numpy as np
from keras import layers, models, datasets
from keras.utils import np_utils
import matplotlib.pyplot as plt
 
def ANN_models_func(nIn, nHidden, nOut):
    x = layers.Input(shape=(nIn,))
    h = layers.Activation('relu')(layers.Dense(nHidden)(x))
    y = layers.Activation('softmax')(layers.Dense(nOut)(h))
 
    model = models.Model(x, y)
    model.compile(loss='categorical_crossentropy',
        optimizer='adam', metrics=['accuracy'])
 
    return model
 
def Data_func():
    (x_train, y_train), (x_test, y_test) = datasets.mnist.load_data()
 
    y_train = np_utils.to_categorical(y_train)
    y_test = np_utils.to_categorical(y_test)
 
    L, W, H = x_train.shape
    x_train = x_train.reshape(-1, W * H)
    x_test = x_test.reshape(-1, W * H)
 
    x_train = x_train / 255.0
    x_test = x_test / 255.0
 
    return (x_train, y_train), (x_test, y_test)
 
def plot_loss(history):
    plt.plot(history.history['loss'])
    plt.plot(history.history['val_loss'])
    plt.title('Model Loss')
    plt.ylabel('Loss')
    plt.xlabel('Epoch')
    plt.legend(['Train''Test'], loc=0)
 
def plot_acc(history):
    plt.plot(history.history['acc'])
    plt.plot(history.history['val_acc'])
    plt.title('Model accuracy')
    plt.ylabel('Accuracy')
    plt.xlabel('Epoch')
    plt.legend(['Train''Test'], loc=0)
 
def main():
    nIn = 784
    nHidden = 100
    nClass = 10
    nOut = nClass
 
    model = ANN_models_func(nIn, nHidden, nOut)
    (x_train, y_train), (x_test, y_test) = Data_func()
 
    history = model.fit(x_train, y_train, epochs=15,
        batch_size=100, validation_split=0.2)
    performance_test = model.evaluate(x_test, y_test, batch_size=100)
    print('Test Loss and Accuracy ->', performance_test)
 
    plot_loss(history)
    plt.show()
    plot_acc(history)
    plt.show()
 
if __name__ == '__main__':
    main()
cs

결과:
11493376/11490434 [==============================] - 17s 1us/step
Train on 48000 samples, validate on 12000 samples
Epoch 1/15
48000/48000 [==============================] - 5s 104us/step - loss: 0.3935 - acc: 0.8908 - val_loss: 0.2118 - val_acc: 0.9420
Epoch 2/15
48000/48000 [==============================] - 3s 72us/step - loss: 0.1829 - acc: 0.9473 - val_loss: 0.1563 - val_acc: 0.9571
(중략)
Epoch 15/15
48000/48000 [==============================] - 4s 85us/step - loss: 0.0178 - acc: 0.9958 - val_loss: 0.0872 - val_acc: 0.9745
10000/10000 [==============================] - 0s 41us/step
Test Loss and Accuracy -> [0.075362077569880059, 0.97740000724792475]



아주 기초적인 예시지만 케라스에 익숙해진다는게 목적이므로 설명은 케라스 API 위주로 적어보겠습니다.

사실 책의 예제에선 신경망 모델을 만드는걸 4가지 방법으로 설명해주는데 다 적기 귀찮아서 하나만 골랐습니다.
굳이 정리하자면 모델을 만들땐 Model, Sequential를 쓸 수 있고
여기에 각종 Layer들을 생성한뒤 연산을 정의하고
Model이나 Seq에 등록해준다음 컴파일(오차 함수, 최적화기 설정)을 해주면 되는데
이때 Model은 활성화 함수, 레이어 연결을 직접 해주고 등록해야 하지만
Seq는 Layer에 직접 활성화 함수를 설정하고 연결은 등록한 순서대로 된다... 정도로 보시면 될 것 같습니다.
근데 이게 또 무조건 이런 제한이 있는것도 아니라서 그냥 맘 내키는대로 할랍니다.
...

layers.Input은 placeholder랑 비슷한것 같은데 제대로 된 설명을 못찾겠네요.
눈에 띄는건 배치 사이즈는 제외하고 shape을 지정한다는 점?
(batch_shape을 쓰면 배치 사이즈도 지정할 수 있는 듯 합니다)

layers.Activation은 활성화 함수인데 공식 문서에 따르면 저렇게 따로 만들어줄 필요 없이
Dense(nHidden, activation='relu') 이렇게 해도 똑같다는것 같습니다.

models.Model로 모델을 생성할 수 있는데 inputs, outputs 파라미터를 각각 x, y로 설정하고 있습니다.
이렇게 하면 outputs 계산에 필요한 모든 레이어가 자동으로 모델에 포함된다고 합니다.

model.compile은 학습을 위해 모델을 설정하는 메소드 입니다.
loss는 손실함수이고 optimizer는 최적화기, metrics는 학습 및 테스트 중에 계산할 측정 항목 입니다.

keras.datasets에서 mnist 데이터를 얻을 수 있습니다.
np_utils.to_categorical은 데이터를 원 핫 인코딩 해줍니다.
입력 데이터 x를 255로 나누는 이유는 픽셀값을 0~1의 값으로 정규화하는 작업입니다.
텐서플로 예제에선 이런 작업이 없었는데 좀 다르네요.

matplotlib는 넘어가고...

model.fit 메소드로 모델의 학습을 진행할 수 있습니다.
x, y를 주고 epochs로 학습 횟수를 지정하면 됩니다.
validation_split은 주어진 데이터에서 몇 %를 검증용 데이터로 쓸건지 정합니다.
검증은 매 epoch 학습 이후에 이루어지며 검증용 데이터는 학습 데이터에서 제외됩니다.

model.evaluate 메소드로 테스트 데이터를 사용해 모델의 성능을 최종적으로 측정할 수 있습니다.
입력 데이터 x, 목표 데이터 y를 넣고 돌리면 기본적으로 Loss가 나오는데 모델 compile시 metrics를 지정했다면 이 값도 같이 나옵니다.
그래서 출력을 보시면 Loss랑 Accuracy가 같이 나오는걸 보실 수 있습니다.

설명 완료!




Comments