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