[CS300 #270] 합성곱 신경망 — 작은 필터를 미끄러뜨려 본다
컴퓨터공학 300 주제 시리즈의 270번째 글이다. 전체 지도는 여기.
한 줄 요약
합성곱 신경망(CNN)은 작은 필터 하나를 이미지 전체에 미끄러뜨리며 같은 가중치로 국소 패턴을 찾고(가중치 공유), 층을 쌓아 가며 가장자리 → 무늬 → 부품 → 물체로 점점 큰 패턴을 인식한다.
왜 필요한가
224×224 컬러 이미지는 숫자 15만 개(224·224·3)다. 이것을 완전연결층에 넣고 은닉 뉴런 1,000개를 두면 첫 층의 가중치만 1억 5천만 개다. 학습도 어렵고 과적합도 심하다.
더 근본적인 문제는 완전연결층이 이미지의 성질을 모른다는 것이다. 고양이가 왼쪽 위에 있든 오른쪽 아래에 있든 고양이다. 그리고 픽셀의 의미는 이웃 픽셀과의 관계에서 나온다. CNN 은 이 두 가지 가정, 국소성과 이동 등변성을 구조에 넣어 파라미터를 극적으로 줄인다.
핵심 개념
합성곱 연산
입력 (6x6) 필터 (3x3) 출력 (4x4)
┌─────────────┐ ┌────────┐
│ ▓▓▓ . . . │ │-1 0 1│ 각 위치에서
│ ▓▓▓ . . . │ ⊛ │-2 0 2│ = 필터와 겹친 9칸의
│ ▓▓▓ . . . │ │-1 0 1│ 원소별 곱의 합
│ . . . . . . │ └────────┘
└─────────────┘
필터를 한 칸씩 옮기며 겹친 영역과 원소별 곱의 합을 구한다. 엄밀히는 필터를 뒤집지 않으므로 수학의 합성곱이 아니라 교차상관이지만, 딥러닝에서는 관례상 합성곱이라 부른다. 필터 값은 학습으로 정해지므로 뒤집든 안 뒤집든 결과는 같다.
출력 크기
입력 크기 N, 필터 크기 K, 패딩 P, 보폭(stride) S 이면
출력 크기 = ⌊(N + 2P − K) / S⌋ + 1
- 패딩: 가장자리에 0 을 둘러 크기를 유지한다. K=3, P=1, S=1 이면 입력과 출력 크기가 같다(“same”).
- 보폭: 2 칸씩 건너뛰면 출력이 절반으로 준다.
채널과 파라미터 수
실제 입력은 여러 채널(RGB 면 3)이다. 필터 하나는 K×K×C_in 크기이고, 이런 필터를 C_out 개 두면 출력 채널이 C_out 개다.
파라미터 수 = (K · K · C_in + 1) · C_out (+1 은 필터마다 편향)
3×3, 입력 64채널, 출력 128채널이면 (9·64+1)·128 = 73,856 개. 입력 이미지의 크기와 무관하다. 이것이 가중치 공유의 힘이다.
풀링
2×2 최대 풀링은 2×2 칸마다 최댓값 하나만 남긴다. 크기를 줄여 계산을 아끼고, 패턴의 위치가 조금 흔들려도 같은 출력을 낸다. 최근 구조는 풀링 대신 보폭 2 합성곱을 쓰기도 한다.
수용 영역과 계층적 특징
3×3 합성곱을 두 번 쌓으면 출력 한 칸이 입력의 5×5 를 본다. 세 번이면 7×7. 층이 깊어질수록 한 뉴런이 보는 영역(수용 영역)이 넓어진다. 그래서 앞 층은 가장자리·색 변화를, 뒤 층은 눈·바퀴 같은 부품을 감지하게 된다.
대표 구조의 흐름
| 구조 | 핵심 아이디어 |
|---|---|
| LeNet-5 (LeCun 외, 1998) | 합성곱-풀링-완전연결의 원형. 손글씨 숫자 |
| AlexNet (2012) | GPU 학습, ReLU, 드롭아웃으로 대규모 이미지 분류 |
| VGG | 3×3 합성곱만 깊게 |
| ResNet (He 외, 2015) | 잔차 연결 y = F(x) + x 로 매우 깊은 망 학습 |
잔차 연결은 이후 트랜스포머에도 그대로 쓰인다. 기울기가 덧셈 경로를 따라 깊은 층까지 줄지 않고 흐르게 해 준다.
직접 해 보기
왼쪽은 0, 오른쪽은 1 인 6×6 이미지에 세로 경계를 찾는 소벨 필터를 직접 합성곱한다.
import numpy as np
img = np.zeros((6, 6)); img[:, 3:] = 1.0 # 왼쪽 어둡고 오른쪽 밝은 그림
k = np.array([[-1, 0, 1],
[-2, 0, 2],
[-1, 0, 1]], float) # 소벨 x: 세로 경계 검출
def conv2d(x, k, stride=1, pad=0):
x = np.pad(x, pad)
kh, kw = k.shape
oh = (x.shape[0] - kh) // stride + 1
ow = (x.shape[1] - kw) // stride + 1
out = np.empty((oh, ow))
for i in range(oh):
for j in range(ow):
out[i, j] = np.sum(x[i*stride:i*stride+kh, j*stride:j*stride+kw] * k)
return out
fm = conv2d(img, k)
print("특징 맵", fm.shape); print(fm.astype(int))
relu = np.maximum(fm, 0)
pool = relu.reshape(2, 2, 2, 2).max(axis=(1, 3)) # 2x2 최대 풀링
print("ReLU + 2x2 maxpool:"); print(pool.astype(int))
print("pad=1 출력 크기:", conv2d(img, k, pad=1).shape, " stride=2:", conv2d(img, k, stride=2).shape)
print("파라미터 수: 3x3 합성곱 1채널->1채널 =", 3*3+1, ", 같은 입출력 완전연결 =", 36*16+16)
실행 결과:
특징 맵 (4, 4)
[[0 4 4 0]
[0 4 4 0]
[0 4 4 0]
[0 4 4 0]]
ReLU + 2x2 maxpool:
[[4 4]
[4 4]]
pad=1 출력 크기: (6, 6) stride=2: (2, 2)
파라미터 수: 3x3 합성곱 1채널->1채널 = 10 , 같은 입출력 완전연결 = 592
밝기가 바뀌는 세로 경계(가운데 두 열)에서만 값 4 가 나오고, 평평한 영역은 0 이다. 필터 하나가 “여기에 세로 경계가 있다”는 지도를 만든 것이다. 그리고 이 필터는 이미지의 어느 위치에서든 같은 경계를 똑같이 찾는다.
출력 크기도 공식대로다. (6 − 3)/1 + 1 = 4, 패딩 1 이면 6, 보폭 2 면 ⌊3/2⌋ + 1 = 2. 마지막 줄은 같은 입출력 크기를 완전연결층으로 만들 때 592 개 파라미터가 드는 데 비해 합성곱은 10 개면 된다는 것을 보여 준다. 실제 CNN 에서는 이 필터 값을 사람이 정하지 않고 학습한다. 학습된 첫 층 필터를 시각화하면 이런 경계 검출기와 비슷한 모양이 많이 나온다.
현업에서는
- 전이 학습이 기본이다. 대규모 데이터로 미리 학습한 CNN 의 앞부분을 가져오고, 마지막 층만 내 데이터로 다시 학습한다. 데이터가 수백 장이어도 쓸 만한 분류기를 만들 수 있다.
- 비전 외에도 쓰인다. 1차원 합성곱은 시계열·음성·로그 신호의 국소 패턴 검출에 쓴다.
- 트랜스포머와의 관계: 이미지에도 트랜스포머(ViT)가 쓰이지만, 데이터가 적을 때는 국소성 가정을 가진 CNN 이 여전히 효율적이다. 에지 장치에서 돌아가는 경량 모델도 대부분 합성곱 기반이다.
- 추론 비용: 합성곱의 계산량은 출력 크기 × 필터 크기 × 채널 수에 비례한다. CPU 만 있는 작은 서버에서 이미지 모델을 돌릴 때는 입력 해상도를 줄이는 것이 가장 큰 효과를 낸다.
확인 문제
- 입력 32×32, 필터 5×5, 패딩 0, 보폭 1 일 때 출력 크기는?
- 3×3 필터, 입력 3채널, 출력 16채널 합성곱층의 파라미터 수(편향 포함)는?
- CNN 이 완전연결층보다 파라미터가 훨씬 적은 이유는?
- 3×3 합성곱(보폭 1)을 세 번 쌓았을 때 출력 한 칸의 수용 영역은?
- ResNet 의 잔차 연결이 깊은 망 학습을 돕는 이유는?
풀이
- (32 − 5)/1 + 1 = 28, 즉 28×28.
- (3·3·3 + 1)·16 = 448.
- 국소 영역만 연결하고(희소 연결), 같은 필터를 모든 위치에서 공유하기 때문이다.
- 7×7.
- y = F(x) + x 에서 덧셈 경로의 미분이 1 이라 기울기가 층을 거치며 사라지지 않고 앞쪽까지 전달된다. 층이 항등 함수를 쉽게 배울 수 있어 깊게 쌓아도 성능이 나빠지지 않는다.
더 읽을거리 (References)
- Stanford CS231n 강의 노트, Convolutional Neural Networks
- PyTorch 공식 문서, torch.nn.Conv2d (출력 크기 공식 포함)
- K. He, X. Zhang, S. Ren, J. Sun, “Deep Residual Learning for Image Recognition”, 2015. arXiv:1512.03385
- Y. LeCun, L. Bottou, Y. Bengio, P. Haffner, “Gradient-Based Learning Applied to Document Recognition”, Proceedings of the IEEE 86(11), 1998. (서지 정보)