3 분 소요

특징 맵 추출 방법

모델 생성 후 모델의 입력과 특징 맵을 추출하고 싶은 레이어의 출력으로 특징 맵을 추출하는 모델 생성

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

데이터셋 준비

데이터셋: 패션 MNIST

fashion_mnist = tf.keras.datasets.fashion_mnist

(train_images, train_labels), (test_images, test_labels) = fashion_mnist.load_data()
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-labels-idx1-ubyte.gz
32768/29515 [=================================] - 0s 0us/step
40960/29515 [=========================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/train-images-idx3-ubyte.gz
26427392/26421880 [==============================] - 0s 0us/step
26435584/26421880 [==============================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-labels-idx1-ubyte.gz
16384/5148 [===============================================================================================] - 0s 0us/step
Downloading data from https://storage.googleapis.com/tensorflow/tf-keras-datasets/t10k-images-idx3-ubyte.gz
4423680/4422102 [==============================] - 0s 0us/step
4431872/4422102 [==============================] - 0s 0us/step
class_names = ['T-shirt/top', 'Trouser', 'Pullover', 'Dress', 'Coat',
               'Sandal', 'Shirt', 'Sneaker', 'Bag', 'Ankle boot']
train_images.shape
(60000, 28, 28)
train_labels
array([9, 0, 0, ..., 3, 0, 5], dtype=uint8)
plt.figure()
plt.imshow(train_images[0], cmap="gray")
plt.colorbar()
plt.show()

픽셀 값을 0~1사이로 조정

train_images = train_images / 255.0

test_images = test_images / 255.0
plt.figure(figsize=(10,10))
for i in range(25):
    plt.subplot(5,5,i+1)
    plt.xticks([])
    plt.yticks([])
    plt.imshow(train_images[i], cmap=plt.cm.binary)
    plt.xlabel(class_names[train_labels[i]])
plt.show()

모델 생성

inputs = tf.keras.layers.Input(shape=(28,28,1))

x = tf.keras.layers.Conv2D(32, kernel_size=3, strides=1, padding='same', activation='relu')(inputs)
x = tf.keras.layers.Conv2D(64, kernel_size=3, strides=2, padding='same', activation='relu')(x)
x = tf.keras.layers.Conv2D(128, kernel_size=3, strides=2, padding='same', activation='relu')(x)

x = tf.keras.layers.Flatten()(x)

x =  tf.keras.layers.Dense(10, activation='softmax')(x)

model = tf.keras.models.Model(inputs, x)
model.summary()
Model: "model_3"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_8 (InputLayer)        [(None, 28, 28, 1)]       0         
                                                                 
 conv2d_21 (Conv2D)          (None, 28, 28, 32)        320       
                                                                 
 conv2d_22 (Conv2D)          (None, 14, 14, 64)        18496     
                                                                 
 conv2d_23 (Conv2D)          (None, 7, 7, 128)         73856     
                                                                 
 flatten_7 (Flatten)         (None, 6272)              0         
                                                                 
 dense_6 (Dense)             (None, 10)                62730     
                                                                 
=================================================================
Total params: 155,402
Trainable params: 155,402
Non-trainable params: 0
_________________________________________________________________
model.compile(optimizer='adam',
              loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=True),
              metrics=['accuracy'])

모델 훈련

model.fit(train_images, train_labels, epochs=10)
Epoch 1/10
/usr/local/lib/python3.7/dist-packages/tensorflow/python/util/dispatch.py:1082: UserWarning: "`sparse_categorical_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?"
  return dispatch_target(*args, **kwargs)
1875/1875 [==============================] - 84s 45ms/step - loss: 0.3981 - accuracy: 0.8581
Epoch 2/10
1875/1875 [==============================] - 87s 46ms/step - loss: 0.2638 - accuracy: 0.9048
Epoch 3/10
1875/1875 [==============================] - 87s 46ms/step - loss: 0.2181 - accuracy: 0.9207
Epoch 4/10
1875/1875 [==============================] - 81s 43ms/step - loss: 0.1803 - accuracy: 0.9332
Epoch 5/10
1875/1875 [==============================] - 84s 45ms/step - loss: 0.1542 - accuracy: 0.9443
Epoch 6/10
1875/1875 [==============================] - 88s 47ms/step - loss: 0.1271 - accuracy: 0.9544
Epoch 7/10
1875/1875 [==============================] - 89s 47ms/step - loss: 0.1047 - accuracy: 0.9618
Epoch 8/10
1875/1875 [==============================] - 82s 44ms/step - loss: 0.0882 - accuracy: 0.9682
Epoch 9/10
1875/1875 [==============================] - 84s 45ms/step - loss: 0.0739 - accuracy: 0.9737
Epoch 10/10
1875/1875 [==============================] - 90s 48ms/step - loss: 0.0653 - accuracy: 0.9766
<keras.callbacks.History at 0x7fb3dde86a90>
test_loss, test_acc = model.evaluate(test_images,  test_labels, verbose=2)

print('\nTest accuracy:', test_acc)
/usr/local/lib/python3.7/dist-packages/tensorflow/python/util/dispatch.py:1082: UserWarning: "`sparse_categorical_crossentropy` received `from_logits=True`, but the `output` argument was produced by a sigmoid or softmax activation and thus does not represent logits. Was this intended?"
  return dispatch_target(*args, **kwargs)
313/313 - 4s - loss: 0.3365 - accuracy: 0.9140 - 4s/epoch - 13ms/step

Test accuracy: 0.9139999747276306

특징맵 모델 생성

ins = model.inputs
outs = model.layers[1].output

feature_map = tf.keras.models.Model(ins, outs)

feature_map.summary()
Model: "model_5"
_________________________________________________________________
 Layer (type)                Output Shape              Param #   
=================================================================
 input_8 (InputLayer)        [(None, 28, 28, 1)]       0         
                                                                 
 conv2d_21 (Conv2D)          (None, 28, 28, 32)        320       
                                                                 
=================================================================
Total params: 320
Trainable params: 320
Non-trainable params: 0
_________________________________________________________________
plt.figure()
plt.imshow(train_images[5], cmap="gray")
plt.colorbar()
plt.show()

input_img = np.expand_dims(train_images[5], axis=0)
feature = feature_map.predict(input_img)
print(feature.shape)

plt.figure(figsize=(25,25))
for i in range(16):
  plt.subplot(4,4,i+1)
  plt.imshow(feature[0,:,:,i], cmap="gray")

plt.show()
(1, 28, 28, 32)

특징 맵을 보면 첫번째 레이어는 옷의 선 같은 표면을 잘 학습한 것으로 보입니다.

모든 레이어 특징 맵 확인

def check_feature(num_layer, input_img):
  ins = model.inputs
  outs = model.layers[num_layer].output

  feature_map = tf.keras.models.Model(ins, outs)
  input_img = np.expand_dims(input_img, axis=0)

  feature = feature_map.predict(input_img)
  print(feature.shape)

  plt.figure(figsize=(15,10))
  for i in range(6):
    plt.subplot(1,6, i+1)
    plt.imshow(feature[0,:,:,i], cmap="gray")

  plt.show()
plt.figure()
plt.imshow(train_images[600], cmap="gray")
plt.colorbar()
plt.show()

for i in range(1, 4):
  check_feature(i, train_images[600])
(1, 28, 28, 32)

(1, 14, 14, 64)

(1, 7, 7, 128)

출력층에 가까울수록 원래 형태는 찾아볼 수 없고, 이미지 특징들만 전달되는 것을 확인할 수 있습니다.


태그:

카테고리:

업데이트:

댓글남기기