본문 바로가기
Computer Science/Deep Learning

[비전공자용] CNN (합성곱 신경망)에서 필터를 적용한다는 것의 의미 이해하기

by 롱일스 2020. 7. 29.
반응형

이번 포스트에서는 합성곱 신경망에서 필터가 어떻게 작용하는지 이해하기 쉽게 설명해보려 한다.

신경망 학습을 통해서 loss손실을 줄이는 방향으로 이 가중치가 변화하게 된다.
먼저 그 변화를 자세히 살펴보자.

 

1. 처음에 가중치를 설정할 때는 랜덤으로(무작위로) 값을 정하기 때문에 의미없는 값들로 이루어져 있다. 

 아무 규칙이 없다는 말이다.

2. 학습을 거치면서 필터는 규칙성 있는 형태로 변화한다.

3. 학습된 필터 몇 개를 선택해서 입력받은 이미지에 합성곱 처리(Test)를 해보면

4. 각각의 필터 특징에 맞게 어떤 특징이 부각되어 이미지를 출력한다.

 

이해를 돕기 위해 예를 들어보자.

CNN을 구성하는 한 합성곱 계층의 가중치가 (30, 1, 5, 5)의 형상을 가지고 있다고 하자.

☞ 통상적으로 필터 30개, 채널 1개, 5X5 크기를 가지는 가중치를 말한다.

☞ 채널이 1개라는 것은 이 필터를 1채널의 회색조 이미지로 시각화할 수 있다는 뜻이다.

 

이전 포스트에서 정의한 SimpleConvNet 클래스를 이용해서 CNN 학습을 시켜보고
필터학습 전후에 어떻게 달라지는지 보자.

학습 전 1번째 층 합성곱 계층 가중치

학습 후 1번째 층 합성곱 계층 가중치

학습 전후의 가중치 변화를 보면 

1. 이전에는 규칙없이 그냥 흰색 검은색 회색으로 이뤄진 이미지였는데

2. 이후에는 뭔가 흰색과 검은색이 구분되어 보이고, 덩어리(Blob)가 진 필터가 생겼으며
규칙을 가지는 필터가 몇 개 보이네요. 

(참고) 가중치의 원소는 실수로 이뤄져있고, 이미지에서 '0'은 검은색, '255'는 흰색을 의미하도록 정규화하여 표시한다.

 흰색에서 검은색으로 그라데이션이 진 것 같아보이는 규칙성 있는 필터는 이미지를 어떻게 만들어줄까요? 

필터마다 어떤 특징을 가지는 건지 시각적으로 한 번 이해해보도록 합시다.

그렇게 하기 위해서는 위에서 언급했던 3, 4번 단계로 넘어가야 합니다.

학습시킨 필터 16개로 아래 흑백 사진을 처리하면 어떻게 될까요?

lena_gray.png

 

16개의 필터를 적용한 레나씨의 사진

이렇게 봐도 정확히 어떤 필터가 어떤 효과를 주는 지 잘 보이지 않죠? 

가장 극단적으로 변한 맨오른쪽 아래의 필터로인한 레나씨 사진 변화를 확대해서 봐봅시다.

필터 자체가 대각선을 경계로 흰색에서 검은색으로 나뉘어져있죠?

오른쪽 레나씨 사진을 보면 대각선 방향의 에지(색상이 바뀐 경계선)에 반응해서
대각선/세로 방향의 선을 추출하는 걸 볼 수 있습니다. 

하나 더 볼까요?

이번에는 필터가 가로방향의 에지를 기준으로 색상이 나뉘어있네요.
그래서인지 레나씨 사진도 갑자기 눈썹과 눈꺼풀이 부각돼 보이고 가로 방향의 모자의 깃털이 부각돼 보이네요.

이렇게 합성곱 계층의 필터는 에지나 블롭 등의 원시적인 정보를 추출할 수 있습니다. 이렇게 추출한 정보를 다음 층에 전달하면서 더 깊은 수준의 정보를 추출하게 되겠죠.

합성곱 계층을 여러 겹 쌓고 층이 깊어지면 깊어질수록 더 복잡하고 추상화된 정보가 추출됩니다. 

처음 층은 단순한 에지에 반응하고, 그 다음은 텍스쳐, 그 다음은 복잡한 사물의 일부에 반응하는 등 층을 깊게 거칠수록 정보가 고급정보로 점점 변화합니다.

 

지금까지 필터를 적용한다는 것의 의미가 뭔지 이미지 예시를 통해 알아보았습니다. 

추가로 학습을 위해 썼던 파이썬 코드를 첨부합니다. ([출처] Deep Learning from Scratch, ゼロ から作る)

# 처음 예제 - 필터 학습시키는 예제
# coding: utf-8
import numpy as np
import matplotlib.pyplot as plt
from simple_convnet import SimpleConvNet

def filter_show(filters, nx=8, margin=3, scale=10):
    """
    c.f. https://gist.github.com/aidiary/07d530d5e08011832b12#file-draw_weight-py
    """
    FN, C, FH, FW = filters.shape
    ny = int(np.ceil(FN / nx))

    fig = plt.figure()
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

    for i in range(FN):
        ax = fig.add_subplot(ny, nx, i+1, xticks=[], yticks=[])
        ax.imshow(filters[i, 0], cmap=plt.cm.gray_r, interpolation='nearest')
    plt.show()


network = SimpleConvNet()
# 무작위(랜덤) 초기화 후의 가중치
filter_show(network.params['W1'])

# 학습된 가중치
network.load_params("params.pkl")
filter_show(network.params['W1'])
# 필터로 테스트하는 예제 - 레나씨 이미지 예제
# coding: utf-8
import sys, os
sys.path.append(os.pardir)  # 부모 디렉터리의 파일을 가져올 수 있도록 설정
import numpy as np
import matplotlib.pyplot as plt
from simple_convnet import SimpleConvNet
from matplotlib.image import imread
from common.layers import Convolution

def filter_show(filters, nx=4, show_num=16):
    """
    c.f. https://gist.github.com/aidiary/07d530d5e08011832b12#file-draw_weight-py
    """
    FN, C, FH, FW = filters.shape
    ny = int(np.ceil(show_num / nx))

    fig = plt.figure()
    fig.subplots_adjust(left=0, right=1, bottom=0, top=1, hspace=0.05, wspace=0.05)

    for i in range(show_num):
        ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])
        ax.imshow(filters[i, 0], cmap=plt.cm.gray_r, interpolation='nearest')


network = SimpleConvNet(input_dim=(1,28,28), 
                        conv_param = {'filter_num':30, 'filter_size':5, 'pad':0, 'stride':1},
                        hidden_size=100, output_size=10, weight_init_std=0.01)

# 학습된 가중치
network.load_params("params.pkl")

filter_show(network.params['W1'], 16)

img = imread('../dataset/lena_gray.png')
img = img.reshape(1, 1, *img.shape)

fig = plt.figure()

w_idx = 1

for i in range(16):
    w = network.params['W1'][i]
    b = 0  # network.params['b1'][i]

    w = w.reshape(1, *w.shape)
    #b = b.reshape(1, *b.shape)
    conv_layer = Convolution(w, b) 
    out = conv_layer.forward(img)
    out = out.reshape(out.shape[2], out.shape[3])
    
    ax = fig.add_subplot(4, 4, i+1, xticks=[], yticks=[])
    ax.imshow(out, cmap=plt.cm.gray_r, interpolation='nearest')

plt.show()

 

차근차근 지치지 말고 꾸준히 달려가봅시다~~!

 

CNN 합성곱 신경망을 파이썬으로 구현하는 방법에 대해 공부하실 분들은 아래 포스트를 확인해보세요~

2020/07/28 - [Computer Science/Deep Learning] - [비전공자용] [Python] CNN 합성곱 신경망 구현하기

 

[비전공자용] [Python] CNN 합성곱 신경망 구현하기

자자 이제 지금까지 공부했던 합성곱 계층과 풀링 계층을 이용해서 손글씨 숫자를 인식하는 CNN 합성곱 신경망을 본격적으로 구현해보도록 하겠습니다!!!!!! 아래 구조의 계층으로 구성되어 있는

huangdi.tistory.com

2020/07/28 - [Computer Science/Deep Learning] - [비전공자용] [Python] CNN(합성곱 신경망) - 풀링 계층 구현

 

[비전공자용] [Python] CNN(합성곱 신경망) - 풀링 계층 구현

이번 포스트에서는 지난 포스트(CNN-합성곱 계층 구현)에 이어서 CNN에서의 풀링 계층을 Python으로 구현해보려 합니다. 2. 풀링 계층 구현 합성곱 계층과 마찬가지로 풀링 계층에서도 im2col 함수를 �

huangdi.tistory.com

2020/07/28 - [Computer Science/Deep Learning] - [비전공자용] [Python] CNN(합성곱 신경망) - 합성곱 계층 구현

 

[비전공자용] [Python] CNN(합성곱 신경망) - 합성곱 계층 구현

이전 포스트에서 합성곱 계층과 풀링 계층에 대해 이론적으로 살펴보았습니다. 지금부터 두 계층을 직접 Python 코드로 구현하고자 합니다. 1. 합성곱 계층 구현 합성곱 계층에서는 image to column (��

huangdi.tistory.com

[출처] Deep Learning from Scratch, ゼロ から作る

728x90
반응형