NeuroWhAI의 잡블로그

[Keras] Autoencoder로 MNIST 학습하기 본문

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

[Keras] Autoencoder로 MNIST 학습하기

NeuroWhAI 2018. 3. 20. 18:53


※ 이 글은 '코딩셰프의 3분 딥러닝 케라스맛'이라는 책을 보고 실습한걸 기록한 글입니다.


입력과 똑같은 출력을 내도록 학습하면서 데이터의 특징을 스스로 압축(추출)하는 오토인코더로 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
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
from keras import layers, models
from keras.datasets import mnist
import matplotlib.pyplot as plt
import numpy as np
 
class AE(models.Model):
  def __init__(self, x_nodes=784, z_dim=36):
    x = layers.Input(shape=(x_nodes,))
    z = layers.Dense(z_dim, activation='relu')(x)
    y = layers.Dense(x_nodes, activation='sigmoid')(z)
    
    super().__init__(x, y)
    
    self.x = x
    self.z = z
    self.z_dim = z_dim
    
    self.compile(optimizer='adadelta', loss='binary_crossentropy',
                metrics=['accuracy'])
    
  def get_encoder(self):
    return models.Model(self.x, self.z)
  
  def get_decoder(self):
    z = layers.Input(shape=(self.z_dim,))
    y = self.layers[-1](z)
    return models.Model(z, y)
  
 
(x_train, _), (x_test, _) = mnist.load_data()
 
x_train = x_train.astype('float32'/ 255.0
x_test = x_test.astype('float32'/ 255.0
x_train = x_train.reshape(x_train.shape[0], -1)
x_test = x_test.reshape(x_test.shape[0], -1)
print(x_train.shape)
print(x_test.shape)
 
def show_ae(ae, sample_size=10):
  encoder = ae.get_encoder()
  decoder = ae.get_decoder()
  
  encoded = encoder.predict(x_test, batch_size=sample_size)
  decoded = decoder.predict(encoded)
  
  plt.figure(figsize=(206))
  
  for i in range(sample_size):
    ax = plt.subplot(3, sample_size, i+1)
    plt.imshow(x_test[i].reshape(2828))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    
    ax = plt.subplot(3, sample_size, i+1+sample_size)
    plt.stem(encoded[i].reshape(-1))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    
    ax = plt.subplot(3, sample_size, i+1+sample_size*2)
    plt.imshow(decoded[i].reshape(2828))
    plt.gray()
    ax.get_xaxis().set_visible(False)
    ax.get_yaxis().set_visible(False)
    
  plt.show()
 
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():
  x_nodes = 784
  z_dim = 36
  
  autoencoder = AE(x_nodes, z_dim)
  
  history = autoencoder.fit(x_train, x_train, epochs=100, batch_size=256,
                           shuffle=True, validation_data=(x_test, x_test),
                           verbose=2)
  
  plot_acc(history)
  plt.show()
  plot_loss(history)
  plt.show()
  
  show_ae(autoencoder)
  
if __name__ == '__main__':
  main()
cs


결과:
(60000, 784)
(10000, 784)
Train on 60000 samples, validate on 10000 samples
Epoch 1/100
 - 1s - loss: 0.3568 - acc: 0.7549 - val_loss: 0.2708 - val_acc: 0.7961
Epoch 2/100
 - 1s - loss: 0.2628 - acc: 0.7978 - val_loss: 0.2510 - val_acc: 0.7980
(중략)
Epoch 99/100
 - 1s - loss: 0.0920 - acc: 0.8143 - val_loss: 0.0906 - val_acc: 0.8134
Epoch 100/100
 - 1s - loss: 0.0919 - acc: 0.8143 - val_loss: 0.0905 - val_acc: 0.8134




(이번 예시는 Google의 Colaboratory에서 돌려봤는데 정말 만족스럽습니다 ㅎㅎ)

마지막 사진을 보시면 첫째 줄을 입력으로 받아서 두번째 줄의 데이터로 압축했고
이 압축된 데이터(특징)로 다시 원래 이미지로 복원한게 세번째 줄입니다.
보시면 숫자 1 이미지는 두 번 나왔는데 압축된 결과를 보시면 비슷비슷 합니다.
즉, 특징을 잘 추출했다는 말이죠.

다음은 코드에서 제가 몰랐던 부분 설명.

Model.layers 속성으로 모델에 등록한 레이어 목록에 접근할 수 있는 것 같습니다.
Decoder를 만들때 self.layers[-1]로 출력 레이어를 선택한것을 볼 수 있습니다.

데이터를 전처리하는 부분은 책이랑 코드가 조금 다른데
numpy의 prod(product) 함수를 사용해서 reshape할 모양을 계산했길래 저는 그냥 귀찮아서 -1로 적었지만 똑같습니다.

fit 메소드로 모델을 학습할때 shuffle 파라미터를 설정해줬는데 예상대로 학습 데이터를 섞을지 말지 정하는 겁니다.

그리고 계속 이해가 안됬던데 matplotlib의 subplot인데 아래 글 보고 이해됬습니다 ㅎ


끝!




Comments