밑시딥 07

양우민·2022년 5월 17일
0
post-thumbnail

7.3 풀링 계층

풀링(Pooling)?

가로/세로 방향의 공간을 줄이는 연산

최대 풀링(Max Pooling) 처리 순서

최대 풀링은 최댓값을 구하는 연산으로 ' 2 X 2 '는 대상 영역의 크기를 뜻하고 위의 그림과 같이 2 X 2 크기의 영역에서 가장 큰 원소를 하나 꺼낸다.
스트라이드는 이 에에서 2로 설정했으므로 2 X 2 윈도우가 원소 2칸 간격으로 이동하는데 최대 풀링의 경우 대체로 윈도우 크기와 스트라이드 크기는 같은 값으로 설정한다.

만약 윈도우가 3 X 3의 경우는 스트라이드를 3으로 윈도우가 4 X 4인 경우에는 스트라이드를 4로 설정한다.

7.3.1 풀링 계층의 특징

1. 학습해야 할 매개변수가 없다.

  • 풀링 계층은 합성곱 계층과 달리 대상 영역에서 최댓값이나 평균을 취하는 명확한 처리이므로 특별히 학습할 것이 없다.

2. 채널 수가 변하지 않는다.

  • 풀링 연산은 입력 데이터의 채널마다 독립적으로 계산하기 때문에 출력 데이터 그대로 내보낸다.

3. 입력의 변화에 영향을 적게 받는다.(강건하다)

  • 입력 데이터가 조금 변해도 풀링의 결과는 잘 변하지 않는다.
    아래의 예에서 데이터가 오른쪽으로 1칸씩 이동했지만 풀링의 결과는 같은 것을 볼 수 있다.

7.4 합성곱 / 풀링 계층 구현하기

7.4.1 4차원 배열

CNN에서 계층 사이를 흐르는 데이터는 4차원이다.

import numpy as np

x = np.random.rand(10, 1, 28, 28) #무작위로 데이터 생성 (Data, Channel, Height,Width)
x.shape

> (10, 1, 28, 28)
print(x[0].shape) # 첫번째 데이터
print(x[1].shape) # 두번째 데이터
>(1, 28, 28)
>(1, 28, 28)

7.4.2 im2col로 데이터 전개하기

합성곱 연산을 곧이곧대로 구현하려면 for 문을 겹겹이 써야하는데 이는 numpy에서 for 문을 사용하면 성능이 떨어진다는 단점도 존재하여 im2col이라는 편의 함수를 사용해 간단하게 구현한다.

1. im2col은 입력 데이터를 필터링(가중치 계산)하기 좋게 전개하는 함수로 아래의 그림과 같이 3차원 입력 데이터에 im2col을 적용하면 2차원 행렬로 바뀐다.

2. im2col을 좀 더 자세히 보면 입력 데이터에서 필터를 적용하는 영역(3차원 블록)을 한 줄로 늘어놓는다.

위에서는 스트라이드를 크게 잡아 필터의 적용 영역이 겹치지 않도록 했지만 실제 상황에서는 영역이 겹치는 경우가 많다.

3. im2col을 사용하여 구현하면 메모리를 더 많이 소비하는 단점이 있지만 컴퓨터는 큰 행렬을 묶어서 계산하는데 이점을 가지기 때문에 선형 대수 라이브러리를 활용해 효율을 높일 수 있다.

4. im2col을 사용한 합성곱 연산의 필터처리 상세 과정

4-1) 필터를 세로로 1열로 전개
4-2) im2col이 전개한 데이터와 행렬 곱을 계산
4-3) 출력 데이터를 reshape 실행

위와 같이 im2col 방식으로 출력한 결과는 2차원 행렬이므로 CNN 데이터 배열을 맞춰주기 위해 reshape를 통해 4차원으로 변형 시켜준다.

7.4.3 합성곱 계층 구현

1. im2col의 인터페이스

------------------------------------------------------------------
im2col( input_data, filter_h, filter_w, stride = 1, pad = 0)
#input_data = (데이터의 수, 채널 수 높이, 너비)로 이루어진 4차원 데이터
#filter_h : 필터의 높이
#filter_w : 필터의 너비
#stride : 스트라이드
#pad : 패딩
------------------------------------------------------------------

2. 2차원 배열 전개

import sys, os
sys.path.append(os.pardir)
from common.util import im2col

x1 = np.random.rand(1, 3, 7, 7) #(데이터 수 , 채널 수, 높이, 너비) 4차원 데이터 생성
col1 = im2col(x1, 5, 5, stride = 1, pad = 0)
print(col1. shape)
> (9, 75)

x2 = np.random.rand(10, 3, 7, 7) # x1과 같은 데이터 10개 생성
col2 = im2col(x2, 5, 5, stride = 1, pad = 0)
print(col2.shape)
> (90, 75)

x2의 90은 x1에서 9인 원소가 10개 있으므로 90이 되고 2번째 차원은 필터의 크기와 채널 수를 곱한 원소의 개수는 동일하므로 변하지 않는다.

3. 합성곱 계층 구현

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
        N, C, H, W = x.shape
        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)
        col_W = self.W.rehape(FN, -1).T #필터 전개
        #reshape의 두 번째 인수 -1은 reshape의 편의 기능으로 다차원 배열의 원소 수가 변환 후에도 똑같이 유지되도록 적절히 묶어주는 역할을 한다.
        out = np.dot(col, col_W) + self.b
        
        out = out.reshape(N, out_h, out_w, -4).transpose(0, 3, 1, 2)
        #transpose 함수는 다차원 배열의 축 순서를 바꿔주는 함수이다.
        
        return out

3-1) 합성곱 계층은 필터(가중치), 편향, 스트라이드, 패딩을 인수로 받아 초기화되고 필터는 (FN, C, FH, FW)의 4차원 형상이다.

FN : 필터 개수
C : 채널
FH : 필터 높이
FW : 필터 너비

3-2) reshape의 두 번째 인자 예제

(10, 3, 5, 5)의 형상을 한 다차원 배열 W의 원소 수는 총 750개 (10 x 3 x 5 x 5 = 750)
이때 reshape(10, -1)을 호출하면 750개의 원소를 10묶음으로 만들어 (10, 75)인 배열로 만들어준다.

3-3) transpose 예제

변경전변경후
형상(N, H, W, C)(N, C, H, W)
인덱스0, 1, 2, 3(0, 3, 1, 2)

7.4.4 풀링 계층 구현

1. 입력 데이터에 풀링 적용 영역을 전개(ex : 2 x 2)

2. 전개한 행렬에서 행별 최댓값을 구하고 적절한 형상으로 성형

3. 풀링 계층 구현

Class Polling:
	def __init__(self, pool_h, pool_w, stride = 1, pad = 0)
    	self.pool_h = pool_h
        self.pool_w = pool_w
        self.stride = stride
        self.pad = pad
        
    def forward(self, x):
    	N, C, H, W = x.shape
        out_h = int(1+ (H - self.pool_h) / self.stride)
        out_w = int(1+ (W - self.pool_w) / self.stride)
        
    # 전개 (1)
    col = im2col(x, self.pool_h, selfpool_w, self.stride, self.pad)
    col = col.reshape(-1, self.pool_h * self.pool_w)
    
    # 최댓값 (2)
    out = np.max(col, axis = 1)
    
    # 성형 (3)
    out = out.reshape(N, out_h, out_w, C).transpose(0, 3, 1, 2)
    
    return out
profile
이것저것 잡다한 보관소

0개의 댓글