keras Conv2D

  • Convolution의 기초 명령어 Conv2D 예시입니다.
  • 딥러닝의 일부로서가 아닌 명령어 자체 기능을 봅니다.
  • 무엇을 받아서 무엇으로 바꾸는지 살펴봅니다.

1. 2D Convolution

pyimagesearch: Keras Conv2D and Convolutional Layers

  • convolution, 또는 합성곱 연산은 CNN(Convolution Neural Network)이라는 이름으로 접하신 분이 많을테지만 image processing을 비롯한 signal processing에서 사용되어 온 연산 기법입니다.

  • 다음 두 가지 특징이 있습니다.

    1. 인접 데이터끼리 연산 (localization)
    2. 동일 연산을 전체 데이터에 적용 (weight sharing)

      convolution 연산 과정. 출처=pyimagesearch

2. Keras의 Conv2D

2.1. 기본 문법

tf.keras.layers.Conv2D

  • 공식 홈페이지에 따르면 입출력은 다음과 같습니다.

    • 입력 형식 : 4차원 이상의 텐서.
      data_format='channel_first'일 때: batch_shape + (channels, rows, cols),
      data_format='channel_last'일 때: batch_shape + (rows, cols, channels),
    • 출력 형식 : 4차원 이상의 텐서.
      data_format='channel_first'일 때: batch_shape + (filters, rows, cols),
      data_format='channel_last'일 때: batch_shape + (rows, cols, filters),
  • 텐서를 받아 텐서를 출력합니다.

  • 입력의 channel 자리가 출력의 filter 자리로 바뀝니다.

  • 또한, rows와 columns는 padding, strides 등에 따라 달라질 수 있습니다.

  • 텐서를 입력으로 받기 때문에 일반 이미지는 텐서로 변환하여 넣어야 합니다.

2.2. 이미지 입력

  • 텐서플로와 케라스의 버전을 확인합니다.
1
2
3
4
5
6
7
8
9
10
%matplotlib inline

import tensorflow as tf
from tensorflow.keras import layers

import numpy as np
import matplotlib.pyplot as plt

print(tf.__version__)
print(tf.keras.__version__)
  • 실행결과: tensorflow v2.3.1, tf.keras v2.4.0 입니다.
1
2
'2.3.1'
'2.4.0'
  • 예제 이미지를 읽어옵니다.
1
2
3
4
img = plt.imread("./1-conv2d_1.jpg")
print(type(img))
print(img.shape)
plt.imshow(img)
  • 실행결과 : numpy array 형식, 1080 x 1080 3 channel(RGB) 이미지입니다.
1
2
<class 'numpy.ndarray'>
(1080, 1080, 3)

2.3. Conv2D 적용 (1) 1 filter

tf.convert_to_tensor

  • 이미지를 텐서로 변환합니다.
1
2
3
4
img_tf = tf.convert_to_tensor([img], dtype="float32")
print(type(img_tf))
print(img_tf.shape)
print(img_tf.dtype)
  • 실행결과 : numpy array가 EagerTensor로 변환되었습니다.
    3차원을 4차원으로 만들어주기 위해 []를 씌웠습니다.
1
2
3
<class 'tensorflow.python.framework.ops.EagerTensor'>
(1, 1080, 1080, 3)
<dtype: 'float32'>
  • Convolution을 수행합니다.
1
2
3
4
conv_1 = layers.Conv2D(1, 3, padding="same")(img_tf)
print(type(conv_1))
print(conv_1.shape)
print(conv_1.dtype)
  • 실행결과 : 1 channel EagerTensor가 출력되었습니다.
1
2
3
<class 'tensorflow.python.framework.ops.EagerTensor'>
(1, 1080, 1080, 1)
<dtype: 'float32'>
  • matplotlib에서 출력하기 위해 다시 numpy로 변환합니다.
  • 연산 범위가 0~1을 넘어갈 수 있으므로 normalize 처리를 합니다.
1
2
conv_1_np = conv_1.numpy()
plt.imshow((conv_1_np[0]-conv_1_np[0].min())/(conv_1_np[0].max()-conv_1_np[0].min()), cmap="gist_gray")
  • 실행결과 : convolution이 적용되어 그림 모양이 바뀌었습니다.

  • 그림이 어떻게 바뀔지는 예측할 수 없습니다.

  • kernel_initializer 기본값이 glorot_uniform으로, 랜덤이기 때문입니다.

2.3. Conv2D 적용 (2) 1 filter x 8회

  • 랜덤한 커널의 영향을 확인해 보겠습니다.
  • Conv2D를 반복해서 실행하며 결과가 바뀌는지 확인합니다.
1
2
3
4
5
6
7
8
9
10
fig, axes = plt.subplots(ncols=4, nrows=2, figsize=(13, 6))
axs = axes.ravel()

for i, ax in enumerate(axs):
conv_1 = layers.Conv2D(1, 3, padding="same")(img_tf)
conv_1_np = conv_1.numpy()
ax.imshow(conv_1_np[0], cmap="gist_gray")
ax.set_title(f"try {i}")

fig.tight_layout()
  • 실행결과 : 실행할때마다 다른 그림이 나옵니다.

2.3. Conv2D 적용 (3) 16 filter

  • 필터의 수를 지정하면 반복된 결과물이 channel로 쌓입니다.
1
2
3
4
conv_16 = layers.Conv2D(16, 3, padding="same")(img_tf)
print(type(conv_16))
print(conv_16.shape)
print(conv_16.dtype)
  • 실행결과 : 16 channel이 출력됩니다.
1
2
3
<class 'tensorflow.python.framework.ops.EagerTensor'>
(1, 1080, 1080, 16)
<dtype: 'float32'>
  • 각각의 채널을 출력합니다.
1
2
3
4
5
6
7
8
9
10
11
conv_16_np = conv_16.numpy()
conv_16_norm = (conv_16_np[0]-conv_16_np.min())/(conv_16_np.max()-conv_16_np.min())

fig, axes = plt.subplots(ncols=4, nrows=4, figsize=(13, 13))
axs = axes.ravel()

for i, ax in enumerate(axs):
ax.imshow(conv_16_norm[:,:,i], cmap="gist_gray")
ax.set_title(f"Channel {i}")

fig.tight_layout()
  • 실행결과 : 랜덤 커널 적용 결과 16개가 나왔습니다.

  • CNN 학습은 커널의 가중치를 목적에 맞도록 조정하는 과정입니다.


도움이 되셨나요? 카페인을 투입하시면 다음 포스팅으로 변환됩니다

Share