해당 시리즈는 프로그래밍 언어 중 하나인 줄리아(Julia)로 딥러닝(Deep learning)을 구현하면서 원리를 설명합니다.
이전 글에서는 합성곱과 풀링의 역전파 계산과 그에 사용되는 col2im()
에 대해서 알아보았다. 이번 글에서는 col2im()
을 사용한 합성곱과 풀링 역전파를 직접 코드로 구현할 것이다.
합성곱 with col2im
합성곱이 역전파 알고리즘에서 어떻게 미분되는지에 관해서는 이전 글에서 다뤘기 때문에 이번 글에서는 기술적으로 합성곱이 작동되는 방식에 대해서 논의하고자 한다. 이를 위해 먼저 합성곱 역전파를 구현한 코드를 확인해보자.
1 | function convolution2D_backward(dense ,input, stride, pad) |
이제 위 코드의 작동 과정을 하나씩 살펴보자. 먼저 순전파 계산 과정에서 저장해둔 입력데이터의 크기와 필터의 크기를 불러온다. 코드에서 사용된 dense
는 순전파 계산에서 각 데이터들을 저장해둔 구조체이다. 구조체에 대해 자세히 알고 싶다면 이 페이지을 읽어보면 좋다. 그 다음으로는 미분값의 차원을 변경하고, 2차원의 배열의 형상으로 바꾼다. 여기서 그 2차원의 형상은 아래의 그림과 같다.
위 그림과 같이 미분값은 행은 데이터의 개수, 열은 차원의 개수를 기준으로 2차원 배열로 변경된다. 이를 열을 기준으로 합산하면 편향의 미분값인 db
가 완성된다. 또한 순전파 계산에서 사용되었던 입력데이터에 im2col()
을 적용한 col
변수를 dense
에 저장해두었다가 dw
를 구할 때 불러와 사용한다. dw
는 col
과 dout
을 곱한 후, dense.w
의 형상으로 변경한다. 마지막으로 남은 것은 dx
이다. grads
로 저장되어 이후 가중치와 편향을 갱신할 때 사용되는 dw
, db
와 달리 dx
는 다음 층으로 넘어갈 미분값을 구하는 것이다. 다르게 말하자면, dx
는 다음 계층의 dout
이 되는 것이다. dx
를 구하는 과정에서 col2im()
이 사용된다. 이 모든 과정을 그림으로 나타내면 아래와 같다.
만약 col2im()
이 어떻게 계산되는지 궁금하다면, 이전 글에서 해당 정보를 찾을 수 있다. 합성곱 역전파 계산에 대해서는 이게 전부이다. 이제는 풀링의 역전파에 대해 살펴보자.
최대값 풀링 with col2im
최대값 풀링은 어떠한 사칙연산도 사용되지 않는다. 단순히 지정된 범위에서 최대값을 뽑아 더 작은 크기의 결과값을 도출한다. 그렇다면 이를 되돌린다는 것은 어떤 의미인가? 바로 미분값을 입력 데이터에서의 최대값 위치로 보내주는 것이다. 최대값 풀링의 역전파는 이것이 전부이다. 이 과정을 구현한 코드를 확인해보자.
1 | function Maxpooling_backward(pool,dout,pool_h,pool_w,stride,pad) |
이제 위 코드의 작동 과정을 하나씩 살펴보자. 먼저 dout
을 차원변경한 후, 이 길이에 맞는 dmax
행렬을 생성한다. dmax
최대값을 원래 위치에 할당할 때 사용된다. 위 코드에서 pool
또한 순전파 과정에서 최대값 풀링의 최대값 위치를 표현한 인덱스 모음이다. 이를 사용하여 dout
에 있는 미분값들을 최대값 위치에 할당하는 것이다. 그 후에 col2im
을 사용하여 원래 형태로 변경해준다. for문의 경우에는 Julia의 인덱스 순서 특성으로 인해 추가된 것이다. Julia의 경우, 인덱스를 모두 세로를 기준으로 잡기 때문에 이를 가로로 변경해주어야 한다. 그 과정을 거치면 dmax
가 가로정렬된 인덱스를 가진 dmax_ex
로 변경된다. 이 모든 과정을 그림으로 나타내면 아래와 같다.
지금까지 col2im()
을 사용하여 합성곱과 최대값 풀링의 역전파 과정을 구현하였다. 데이터 4차원을 유지한 채 이를 진행하면 매우 느리지만, col2im()
을 사용하면 매우 빠른 속도로 계산이 가능하다. 다음 글에서는 지금까지 만든 CNN layers을 바탕으로 모델을 구현하고 학습시켜볼 것이다.