실습 · 연습문제 2개
conv2d를 NumPy로 구현하기 conv2d-forward
딥러닝 라이브러리의 2차원 합성곱(정확히는 상호상관)을 직접 구현한다. 입력 x의 shape은 (C_in, H, W), kernel w의 shape은 (C_out, C_in, kH, kW), bias b의 shape은 (C_out,)이다. 출력 y의 원소는
이다. 는 높이·너비 양쪽에 padding칸씩 0을 덧붙인 입력, 는 stride다(높이와 너비에 같은 값을 쓴다). kernel을 뒤집지 않는다는 점에 주의한다.
함수 conv2d(x, w, b, stride=1, padding=0)를 완성해 y를 반환한다. 출력 shape은 (C_out, H_out, W_out)이고
이다(도 같다).
테스트는 다음을 확인한다.
- 여러
stride·padding·직사각형 kernel에서 출력 shape이 공식과 같다. - 출력값이 원소 정의를 그대로 계산한 값과 같다.
- stride 1, padding 0, 채널 1개일 때
scipy.signal.correlate2d(..., mode="valid")와 같다.
힌트: 출력 위치 (i, j)마다 입력에서 (C_in, kH, kW) 조각을 잘라 w와 곱해 더한다. np.einsum("chw,ochw->o", patch, w)가 채널과 kernel 축을 한 번에 축약한다.
receptive field 계산하기 receptive-field-calc
1차원 합성곱 층을 입력 쪽부터 차례로 쌓는다. 층 은 kernel 크기 , stride , dilation 을 가진다. 마지막 층 출력 한 칸이 영향을 받을 수 있는 입력의 범위(이론 receptive field)의 길이 과, 마지막 층 출력에서 한 칸 옆으로 갈 때 입력에서 이동하는 칸 수(jump) 를 구한다.
함수 receptive_field(layers)를 완성해 (r, J)를 반환한다. layers는 (k, s, d) 튜플의 리스트이고, 비어 있으면 (1, 1)이다.
테스트는 다음을 확인한다.
- 3×1 합성곱 다섯 층(stride 1)은 , 이다.
- dilation 1, 2, 4, 8인 kernel 2 causal 층 네 개는 이다(시계열 TCN의 전형적인 구성).
- 무작위로 만든 층 구성에서, 입력 칸 하나를 바꿔 보며 출력 한 칸이 영향을 받는 입력 범위를 직접 센 값과 같다.
힌트: 앞 층들의 stride 곱을 누적하는 변수를 두고, 층마다 그 값에 를 곱해 에 더한다. 누적 stride는 이 층의 를 더한 뒤에 갱신한다.