합성곱 신경망을 사용한 이미지 분류

In [1]:
# 실행마다 동일한 결과를 얻기 위해 케라스에 랜덤 시드를 사용하고 텐서플로 연산을 결정적으로 만듭니다. 
import tensorflow as tf

tf.keras.utils.set_random_seed(42)
tf.config.experimental.enable_op_determinism()

패션 MNIST 데이터 불러오기

In [2]:
from tensorflow import keras
from sklearn.model_selection import train_test_split

(train_input, train_target), (test_input, test_target) = \
    keras.datasets.fashion_mnist.load_data()

train_scaled = train_input.reshape(-1, 28, 28, 1) / 255.0

train_scaled, val_scaled, train_target, val_target = train_test_split(
    train_scaled, train_target, test_size=0.2, random_state=42)

합성곱 신경망 만들기

In [3]:
model = keras.Sequential()
2022-05-19 01:08:58.768953: I tensorflow/core/platform/cpu_feature_guard.cc:193] This TensorFlow binary is optimized with oneAPI Deep Neural Network Library (oneDNN) to use the following CPU instructions in performance-critical operations:  AVX2 AVX512F FMA
To enable them in other operations, rebuild TensorFlow with the appropriate compiler flags.
In [4]:
model.add(keras.layers.Conv2D(32, kernel_size=3, activation='relu', 
                              padding='same', input_shape=(28,28,1)))
In [5]:
model.add(keras.layers.MaxPooling2D(2))
In [6]:
model.add(keras.layers.Conv2D(64, kernel_size=(3,3), activation='relu', 
                              padding='same'))
model.add(keras.layers.MaxPooling2D(2))
In [7]:
model.add(keras.layers.Flatten())
model.add(keras.layers.Dense(100, activation='relu'))
model.add(keras.layers.Dropout(0.4))
model.add(keras.layers.Dense(10, activation='softmax'))
In [8]:
model.summary()
Model: "sequential"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 conv2d (Conv2D)             (None, 28, 28, 32)        320       
                                                                 
 max_pooling2d (MaxPooling2D  (None, 14, 14, 32)       0         
 )                                                               
                                                                 
 conv2d_1 (Conv2D)           (None, 14, 14, 64)        18496     
                                                                 
 max_pooling2d_1 (MaxPooling  (None, 7, 7, 64)         0         
 2D)                                                             
                                                                 
 flatten (Flatten)           (None, 3136)              0         
                                                                 
 dense (Dense)               (None, 100)               313700    
                                                                 
 dropout (Dropout)           (None, 100)               0         
                                                                 
 dense_1 (Dense)             (None, 10)                1010      
                                                                 
=================================================================
Total params: 333,526
Trainable params: 333,526
Non-trainable params: 0
_________________________________________________________________
In [9]:
keras.utils.plot_model(model)
Out[9]:
In [10]:
keras.utils.plot_model(model, show_shapes=True, to_file='cnn-architecture.png', dpi=300)
Out[10]:

모델 컴파일과 훈련

In [11]:
model.compile(optimizer='adam', loss='sparse_categorical_crossentropy', 
              metrics='accuracy')

checkpoint_cb = keras.callbacks.ModelCheckpoint('best-cnn-model.h5', 
                                                save_best_only=True)
early_stopping_cb = keras.callbacks.EarlyStopping(patience=2,
                                                  restore_best_weights=True)

history = model.fit(train_scaled, train_target, epochs=20,
                    validation_data=(val_scaled, val_target),
                    callbacks=[checkpoint_cb, early_stopping_cb])
Epoch 1/20
1500/1500 [==============================] - 64s 42ms/step - loss: 0.5421 - accuracy: 0.8064 - val_loss: 0.3392 - val_accuracy: 0.8733
Epoch 2/20
1500/1500 [==============================] - 62s 41ms/step - loss: 0.3595 - accuracy: 0.8713 - val_loss: 0.2821 - val_accuracy: 0.8951
Epoch 3/20
1500/1500 [==============================] - 45s 30ms/step - loss: 0.3068 - accuracy: 0.8885 - val_loss: 0.2593 - val_accuracy: 0.9038
Epoch 4/20
1500/1500 [==============================] - 45s 30ms/step - loss: 0.2745 - accuracy: 0.9011 - val_loss: 0.2433 - val_accuracy: 0.9095
Epoch 5/20
1500/1500 [==============================] - 45s 30ms/step - loss: 0.2463 - accuracy: 0.9098 - val_loss: 0.2476 - val_accuracy: 0.9109
Epoch 6/20
1500/1500 [==============================] - 45s 30ms/step - loss: 0.2292 - accuracy: 0.9174 - val_loss: 0.2184 - val_accuracy: 0.9205
Epoch 7/20
1500/1500 [==============================] - 45s 30ms/step - loss: 0.2118 - accuracy: 0.9224 - val_loss: 0.2276 - val_accuracy: 0.9172
Epoch 8/20
1500/1500 [==============================] - 44s 30ms/step - loss: 0.1946 - accuracy: 0.9284 - val_loss: 0.2184 - val_accuracy: 0.9233
In [12]:
import matplotlib.pyplot as plt
In [13]:
plt.plot(history.history['loss'])
plt.plot(history.history['val_loss'])
plt.xlabel('epoch')
plt.ylabel('loss')
plt.legend(['train', 'val'])
plt.show()
In [14]:
model.evaluate(val_scaled, val_target)
375/375 [==============================] - 3s 8ms/step - loss: 0.2184 - accuracy: 0.9205
Out[14]:
[0.21837739646434784, 0.9204999804496765]
In [15]:
plt.imshow(val_scaled[0].reshape(28, 28), cmap='gray_r')
plt.show()
In [16]:
preds = model.predict(val_scaled[0:1])
print(preds)
1/1 [==============================] - 0s 138ms/step
[[6.7846774e-12 8.1426743e-22 8.9696543e-16 7.7117090e-15 6.6757140e-14
  1.4335832e-13 3.7601382e-14 3.6749163e-12 1.0000000e+00 1.8052020e-13]]
In [17]:
plt.bar(range(1, 11), preds[0])
plt.xlabel('class')
plt.ylabel('prob.')
plt.show()
In [18]:
classes = ['티셔츠', '바지', '스웨터', '드레스', '코트',
           '샌달', '셔츠', '스니커즈', '가방', '앵클 부츠']
In [19]:
import numpy as np
print(classes[np.argmax(preds)])
가방
In [20]:
test_scaled = test_input.reshape(-1, 28, 28, 1) / 255.0
In [21]:
model.evaluate(test_scaled, test_target)
313/313 [==============================] - 3s 9ms/step - loss: 0.2423 - accuracy: 0.9156
Out[21]:
[0.24227263033390045, 0.9156000018119812]