CNN에서 Convolution 연산은 3차원의 feature map과 3차원의 filter의 곱입니다. 컴퓨터는 2차원인 행렬을 계산하는데 최적화 되어 있습니다. 그렇다면 Convolution연산은 어떻게 구현되어 있을까요?
Convolution 연산의 구현
일단 이미지와 Batch형태로 4차원 입력데이터(batch, channel, x, y)가 들어오면 2차원으로 변형합니다. 하나하나 뜯어 줄세우는 것입니다. 정확히는 필터를 적용할 영역(3차원)을 1줄로 펼쳐서 이것을 합친 것이 2차원이 되는 것입니다. (아래 그림 참조)
위와 같이 필터(3차원)도 1줄로 만듭니다. 보통 필터가 여러개니까 Concat하면 행렬이 됩니다. 이렇게 변형한 입력데이터(2차원), 필터(2차원)의 곱을 하면 효율적으로 Convolution 연산을 할 수 있게 됩니다.
보통 CNN은 필터가 Sliding Window방식으로 중첩돼서 연산을 합니다. 따라서 필터가 적용되는 영역을 2차원 행렬로 변형하면서 중복으로 인해 메모리는 더 많이 사용하는 단점이 있습니다.
부록 – Pooling layer는 어떻게 구현할까?
Convolution layer는 컴퓨터가 연산하기 좋은 2차원인 행렬로 바꾸어 연산한다는 것을 알게되었습니다. 그렇다면 Pooling layer는 어떤 방식으로 연산할까요? 예상하셨겠지만 Pooling도 2차원으로 변환해서 연산합니다.
아래그림은 2×2 Pooling layer, Stride = 2, 인 계층을 행렬로 변환해서 Max Pool 하는 것 입니다.
위 그림에서 전개 후 최댓값을 찾을 때 numpy로 효율적으로 최댓값을 찾을 수 있습니다.
numpy에서는 원소에 접근할 때 for문을 최대한 돌리지 않는 것이 바람직하므로 아래와 같은 방식을 사용합니다.
out = np.max(col, axis =1)
#col은 전개 후 나온 행렬입니다. np.max(col, axis =1)는 1번째 차원 축마다 최댓값을 구합니다.
# axis = 0 이면 행방향, axis = 1이면 열방향 입니다.