본문 바로가기

Study/class note

딥러닝 / 합성곱 convolution계층 설명

cnn층의 가중치는 필터인데 이 필터가 학습이 되면서 점점 원본 이미지를 잘 설명하는 형태로 변경되어감.

그동안 신경망 학습할 때 입력값과 가중치와의 "내적"을 했었는데 이 내적은 무슨 역할인가?

입력 신호와 가중치가 얼마나 유사한지를 나타내는 수치를 출력함

 

 

ㅇconvolution계층에서 일어나는 일 4가지

이미지의 특징을 추출하기 위해서 코드로 어떻게 구현했는가?

 

1. 원본 이미지를 im2col 함수로 2차원 행렬로 변경

2. filter를 넘파이의 reshape의 -1옵션을 이용해서 2차원 행렬로 변경

3. 2개의 2차원 행렬 내적

4. 내적한 결과 2차원 행렬을 다시 4차원으로 변경

 

class Convolution:
    def __init__(self, W, b, stride=1, pad=0):  
        self.W = W  #필터행렬, 학습되면서 이 필터행렬이 원본이미지의 특징을 잘 살릴 수 있도록 변경됨
        self.b = b  #신경망에 흘러가는 값들을 잘 활성화 시키게끔 도와주는 행렬인 바이어스를 셋팅
        self.stride = stride  #원본 이미지를 몇 칸 간격으로 필터가 스캔할 지를 지정
        self.pad = pad  #이미지의 가장자리 정보가 없어지지 않도록 채우는 것
        
    def forward(self, x):  #이미지를 흘려보내서 피처맵을 생성하는 함수(순전파)
        FN, C, FH, FW = self.W.shape  #4차원배열(필터 갯수, 색조, 높이, 가로)
        N, C, H, W = x.shape  #입력 이미지 4차원 배열(입력이미지의 갯수, 색조, 높이, 가로)
        out_h = int(1 + (H + 2*self.pad - FH) / self.stride)  #피처맵의 높이 사이즈 계산
        out_w = int(1 + (W + 2*self.pad - FW) / self.stride)  #피처맵의 가로 사이즈 계산
        
        col = im2col(x, FH, FW, self.stride, self.pad)  #입력이미지를 필터사이즈에 맞춰서 2차원 행렬로 변환
        col_w = self.W.reshape(FN, -1).T  #4차원 가중피(필터)행렬을 2차원으로 변경하고 전치
        out = np.dot(col, col_w) + self.b  #2차원 행렬 2개를 내적하고 바이어스를 더함
                                           #내적계산의 결과값은 입력이미지와 필터의 유사성
        
        out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)  #2차원을 4차원으로 변경
                                                                      #동시에 transpose함
        return out

transpose(0, 3, 1, 2)는 (갯수, 높이, 넓이, 색조) ---> (갯수, 색조, 높이, 넓이)로 변경

 

 

문제177. 28x28의 사진 1개를 생성합니다.

import numpy as np

x1 = np.random.randn(1,3,28,28) #사진 1장 생성
x1

 

문제178. 5x5의 RGB필터 10개와 바이어스를 생성하시오.

ft = np.random.randn(10,3,5,5)
b1 = 1

 

문제179. 위에서 만든 설계도 Convolution을 가지고 conv1이라는 객체를 생성하고 입력값 x1을 넣어 피처맵 10개를 생성하시오.(피처맵은 필터 사이즈만큼 생성됨)

def im2col(input_data, filter_h, filter_w, stride=1, pad=0):
    """다수의 이미지를 입력받아 2차원 배열로 변환한다(평탄화).
    Parameters
    ----------
    input_data : 4차원 배열 형태의 입력 데이터(이미지 수, 채널 수, 높이, 너비)
    filter_h : 필터의 높이
    filter_w : 필터의 너비
    stride : 스트라이드
    pad : 패딩
    Returns
    -------
    col : 2차원 배열
    """
    N, C, H, W = input_data.shape
    out_h = (H + 2 * pad - filter_h) // stride + 1
    out_w = (W + 2 * pad - filter_w) // stride + 1
    img = np.pad(input_data, [(0, 0), (0, 0), (pad, pad), (pad, pad)], 'constant')
    col = np.zeros((N, C, filter_h, filter_w, out_h, out_w))
    for y in range(filter_h):
        y_max = y + stride * out_h
        for x in range(filter_w):
            x_max = x + stride * out_w
            col[:, :, y, x, :, :] = img[:, :, y:y_max:stride, x:x_max:stride]
    col = col.transpose(0, 4, 5, 1, 2, 3).reshape(N * out_h * out_w, -1)
    return col

class Convolution:
    def __init__(self, W, b, stride=1, pad=0):  
        self.W = W  #필터행렬, 학습되면서 이 필터행렬이 원본이미지의 특징을 잘 살릴 수 있도록 변경됨
        self.b = b  #신경망에 흘러가는 값들을 잘 활성화 시키게끔 도와주는 행렬인 바이어스를 셋팅
        self.stride = stride  #원본 이미지를 몇 칸 간격으로 필터가 스캔할 지를 지정
        self.pad = pad  #이미지의 가장자리 정보가 없어지지 않도록 채우는 것
        
    def forward(self, x):  #이미지를 흘려보내서 피처맵을 생성하는 함수(순전파)
        FN, C, FH, FW = self.W.shape  #4차원배열(필터 갯수, 색조, 높이, 가로)
        N, C, H, W = x.shape  #입력 이미지 4차원 배열(입력이미지의 갯수, 색조, 높이, 가로)
        out_h = int(1 + (H + 2*self.pad - FH) / self.stride)  #피처맵의 높이 사이즈 계산
        out_w = int(1 + (W + 2*self.pad - FW) / self.stride)  #피처맵의 가로 사이즈 계산
        
        col = im2col(x, FH, FW, self.stride, self.pad)  #입력이미지를 필터사이즈에 맞춰서 2차원 행렬로 변환
        col_w = self.W.reshape(FN, -1).T  #4차원 가중피(필터)행렬을 2차원으로 변경하고 전치
        out = np.dot(col, col_w) + self.b  #2차원 행렬 2개를 내적하고 바이어스를 더함
                                           #내적계산의 결과값은 입력이미지와 필터의 유사성
        
        out = out.reshape(N, out_h, out_w, -1).transpose(0, 3, 1, 2)  #2차원을 4차원으로 변경
                                                                      #동시에 transpose함
        return out
conv1 = Convolution(ft, b1)

feature_map = conv1.forward(x1)
feature_map.shape  #(1, 10, 24, 24)

원본이미지 (1,3,28,28) ---> 피처맵 10장(1,10,24,24)

 

 

문제180. 이번에는 다른 필터를 생성하는데 필터의 갯수를 100개로 해서 생성하고, 필터사이즈는 5x5로 하세요.

ft2 = np.random.randn(100,3,5,5)

conv2 = Convolution(ft2, b1)

feature_map2 = conv2.forward(x1)
feature_map2.shape  #(1, 100, 24, 24)

 

 

반응형