7.4.1 4차원 배열
CNN에서 데이터는 4차원이다. 만약 (10, 1, 28, 28) 이라면 10개의 데이터, 1개의 채널(색상), 28 height와 28 width이다.
x = np.random.rand(10,1,28,28)
x.shape
Out[3]: (10, 1, 28, 28)
x[0].shape
Out[4]: (1, 28, 28)
x[1].shape
Out[5]: (1, 28, 28)
다음과 같이 형태를 확인할 수 있다. 그리고 만약 첫 번째 데이터의 첫 채널 공간 데이터에 접근하는 방법은 다음과 같다.
x[0, 0]
합성곱의 연산은 im2col을 이용하여 간단?하게 이루어진다.
7.4.2 im2col로 데이터 전개하기
일반적으로 n차원 데이터를 그대로 계산하려면 nested loop 즉 중첩 반복문을 사용해야 할 것이다. 하지만 이는 성능에 굉장한 하락을 가져온다. 이를 해결하기 위해서 im2col 이라는 함수를 사용한다.
im2col은 입력 데이터를 가중치 계산(filtering)하기 좋게 전개하는 함수이다.
즉 3차원 입력 데이터에 im2col을 적용하면 2차원 행렬로 바꿀 수 있으며, 4차원 역시 2차원으로 만들 수 있다.

im2col은 필터링하기 좋게 입력 데이터를 전개한다. 3차원 블록을 한 줄로 늘어놓는다.
##im2col은 image to column의 약자이다.
im2col로 입력 데이터를 전개한 다음, 합성곱 계층의 필터를 1열로 전개하고, 두 행렬의 내적을 계산한다.

출력을 2차원으로 저장하고, 이를 다시 4차원으로 reshape한다.
7.4.3 합성곱 계층 구현하기
im2col의 인터페이스
im2col(input_data, filter_h, filter_w, stride=1, pad=0)
사용예
import sys, os
sys.path.append(os.pardir)
from common.util import im2col
x1 = np.random.rand(1,3,7,7)
col1 = im2col(x1, 5, 5, stride=1, pad=0)
print(col1.shape) #(9, 75)
x2 = np.random.rand(10,3,7,7)
col2 = im2col(x2,5,5,stride=1,pad=0)
print(col2.shape) #(90, 75)
채널 3개, 높이 너비가 7x7인 데이터를 im2col을 이용해서 바꾸어주었다. 3x5x5 짜리인 필터와 내적하기 위해서 다음과 같이 변하였다. 필터 역시 3차원에서 2차원 행렬로 변하기 때문에, col1의 shape는 (9, 75)가 되었다. ( ∵ 필터가 2차원이 되는데, 한 블럭이 한 줄이 되는 꼴이기 때문에 3x5x5=75개의 원소가 된다.)
x2는 단순히 데이터 갯수가 10배이기 때문에, 행렬 역시 (90, 75)의 꼴을 가지게 된다.
Convolution class
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 #filter
N,C,H,W = x.shape #input data
out_h = int(1 + (H + 2*self.pad - FH) / self.stride)
out_w = int(1 + (H + 2*self.pad - FW) / self.stride)
col = im2col(x,FH,FW,self.stride,self.pad)
col_W = self.W.reshape(FH,-1).T #필터 전개
out = np.dot(col, col_W) + self.b
out = out.reshape(N, out_h, out_w, -1).transpose(0,3,1,2)
return out
W는 filter 이고, x 는 input_data이다. 입력 데이터와 필터를 적절하게 2차원으로 바꾸어주고, 내적한다. 코드가 순서대로의 과정이기 때문에, 크게 어려울 것은 없으나 transpose 부분은 한 번 볼 필요가 있다.

transpose와 함께 나오는 정수는 인덱스를 의미한다. 그리고 그 인덱스 순서로 변환해주는 transposing을 해준다.
'머신 러닝 및 파이썬 > 밑바닥부터 시작하는 딥러닝' 카테고리의 다른 글
| Ch.7 합성곱 신경망(CNN)/ 7.4 풀링 계층 구현하기 (0) | 2020.03.15 |
|---|---|
| Ch.7 합성곱 신경망(CNN)/ 7.2 합성곱 계층 (0) | 2020.03.12 |
| Ch.6 학습 관련 기술들/ 6.5 적절한 하이퍼파라미터 값 찾기 (0) | 2020.03.12 |
| Ch.6 학습 관련 기술들/ 6.4.3 드롭아웃 (0) | 2020.03.11 |
| Ch.6 학습 관련 기술들/ 6.4.1 오버피팅 (0) | 2020.03.11 |