개요
22편에서 CNN이 사진을 보는 방식을 봤다. 이번 글은 그 부품들로 사람들이 실제로 무엇을 만들었는지다.
모델 이름을 외우는 글이 아니다. 나는 이 계보가 네 번의 질문과 네 번의 대답이라고 생각한다.
| 연도 | 모델 | 던진 질문 | 대답 |
|---|---|---|---|
| 2012 | AlexNet | 깊은 CNN이 진짜 되나? | 된다, GPU만 있으면 |
| 2014 | VGG | 어떻게 쌓는 게 좋은가? | 작은 필터를 깊게 |
| 2015 | ResNet | 더 깊게는 왜 안 되나? | 지름길을 내면 된다 |
| 2017 | MobileNet | 꼭 이렇게 비싸야 하나? | 쪼개면 9배 싸진다 |
교육 자료는 대외비라 슬라이드 이미지나 예제 데이터는 싣지 않는다. 개념 흐름만 내가 이해한 방식으로 재구성했고, 그림은 전부 생성했다.
1. 판이 갈린 순간
2010~2011년은 에러율 25~28%짜리 얕은 모델의 시대였다. 그러다 2012년 AlexNet이 16.4%로 뚝 떨어뜨린다. 그 뒤로는 전부 딥러닝이고, 2015년 ResNet이 3.6%로 사람의 오차(5.1%)를 넘는다.
그래프에서 눈여겨볼 건 에러율보다 층수 표시다. 8층 → 19층 → 22층 → 152층. 성능이 좋아진 방향과 깊어진 방향이 정확히 같다. 하지만 곧 보겠지만 “깊게만 하면 된다”는 건 사실이 아니었고, 그 벽을 뚫는 게 ResNet의 이야기다.
2. AlexNet — 되는 걸 증명한 모델
구조 자체는 지금 보면 소박하다.
합성곱 5개 + 완전연결 3개 = 8층, ReLU 활성화, 맥스 풀링, 입력 3×227×227
논문 그림에는 224로 되어 있지만 계산이 맞지 않아 227로 정정된 것으로 본다. 그리고 당시 GPU(GTX 580)의 메모리가 3GB밖에 안 돼서 GPU 두 장에 채널을 반씩 나눠 돌렸다. 지금 RTX 3090이 24GB, H100이 80GB인 걸 생각하면 격세지감이다.
인용 수 이야기가 재미있었다. AlexNet 논문 인용 수가 16만 회를 넘는다. 참고로 다윈 『종의 기원』이 약 6.5만, 섀넌의 정보이론 논문이 약 15.7만이다.
계산을 손으로 따라가 보자 — Conv1
말로만 넘어가면 감이 안 온다. 첫 번째 합성곱층 하나만 직접 계산해 보자.
주어진 값
| 항목 | 값 |
|---|---|
| 입력 | 3채널 × 227 × 227 |
| 필터 | 96개, 크기 11×11 |
| 스트라이드 | 4 |
| 패딩 | 0 |
① 출력 크기
$$ W’ = \frac{227 - 11 + 2\times 0}{4} + 1 = 55 $$
출력 채널은 필터 개수 그대로 96. 즉 출력은 96 × 55 × 55다.
② 메모리
출력값 개수는 96 × 55 × 55 = 290,400개. 각 값을 float32(4바이트)로 저장하면
$$ 290{,}400 \times 4 = 1{,}161{,}600\ \text{Byte} \approx 1{,}134\ \text{KB} $$
③ 파라미터 개수
필터 하나가 가지는 값은 (입력 채널 × 커널 크기²) = 3 × 11 × 11. 이게 96개고, 여기에 편향 96개를 더한다.
$$ 96 \times 3 \times 11 \times 11 + 96 = 34{,}944 \approx 34.9\text{K} $$
④ 연산량(FLOPs)
출력 한 칸을 만들려면 3 × 11 × 11번의 곱셈과 그만큼의 덧셈이 필요하다. 출력 칸은 55 × 55 × 96개다.
$$ (55 \times 55) \times (3 \times 11 \times 11 \times 96) \times 2 = 105{,}415{,}200 \approx 105.4\text{M} $$
층 하나가 1억 번이다. 이런 층이 여덟 개다.
이 계산이 왜 중요한가
층별로 다 계산해 보면 아주 흥미로운 그림이 나온다.
| 자원 | 어디에 몰리나 | 왜 |
|---|---|---|
| 메모리 | 앞쪽 합성곱층 | 해상도가 커서 특징 맵 자체가 크다 (Conv1 = 1,134KB) |
| 파라미터 | 완전연결층 | FC1 하나가 37,753K, 전체의 절반이 넘는다 |
| 연산량 | 합성곱층 | Conv2 하나가 448M FLOPs |
이 세 줄이 이번 편에서 가장 실무적인 부분이라고 생각한다. “모델이 무겁다”는 말은 사실 세 가지 다른 문제를 뭉뚱그린 말이다.
- 학습 중 OOM이 난다 → 앞쪽 해상도를 줄이거나 배치를 줄여야 한다
- 모델 파일이 너무 크다 → 완전연결층을 손봐야 한다
- 추론이 느리다 → 합성곱층을 줄여야 한다
엉뚱한 곳을 깎으면 아무것도 안 나아진다. 이후 모델들이 완전연결층을 없애고(전역 평균 풀링), 합성곱을 쪼개는(MobileNet) 방향으로 간 이유가 여기 다 들어 있다.
3. VGG — 설계에 규칙을 준 모델
VGG의 기여는 성능(7.3%)보다도 규칙이다. 자료에 나온 디자인 룰이 딱 세 줄이다.
- 3×3 합성곱 / 스트라이드 1 / 패딩 1을 반복한다
- 2×2 맥스 풀링으로 크기를 절반으로 줄인다
- 풀링 후에는 채널 수를 2배로 늘린다
이 규칙만 알면 VGG-16이든 VGG-19든 종이에 그릴 수 있다. 그전까지 모델 설계는 감이었는데, VGG 이후로는 블록을 반복하는 문법이 됐다.
왜 하필 3×3인가
3×3을 두 번 연달아 쓰면 수용영역이 5×5가 된다. 22편에서 본 그 계산이다. 그런데 비용은 다르다.
| 방식 | 파라미터 | FLOPs | 비선형 |
|---|---|---|---|
| 5×5 한 층 | 25C² | 25C²HW | 1번 |
| 3×3 두 층 | 18C² | 18C²HW | 2번 |
같은 시야를 28% 싼값에, 게다가 비선형은 두 번 넣으면서 확보한다. 손해 볼 이유가 없다. 그래서 지금도 대부분의 CNN이 3×3을 기본으로 쓴다.
그런데 VGG는 거대하다
| 비교 | AlexNet | VGG-16 | 배수 |
|---|---|---|---|
| 메모리 | 1.9MB | 48.6MB | 약 25배 |
| 파라미터 | 61M | 138M | 약 2.3배 |
| 연산량 | 0.7 GFLOPs | 13.6 GFLOPs | 약 19.4배 |
성능은 확실히 좋아졌지만 연산량이 20배다. VGG의 세 번째 규칙(“풀링 후 채널 2배”)은 층별 연산량 편차를 줄여주긴 하는데, 총량 자체는 어쩔 수 없다.
정리하면 VGG는 단순함과 깊이로 성능을 낸 모델이고, 구조가 단순해서 해석과 전이학습의 기준선(baseline)으로 오래 쓰였다. 대신 비싸다.
4. ResNet — “깊게 하면 좋다”가 깨진 자리
여기가 이 계보에서 가장 흥미로운 대목이다.
배치 정규화 같은 기법 덕분에 10층 이상도 학습이 가능해졌다. 그래서 사람들은 당연히 생각했다. 더 깊게 하면 더 좋겠지. 그런데 20층 모델과 56층 모델을 비교했더니 결과가 이랬다.
56층 모델이 훈련 오차조차 더 높았다
이걸 처음 봤을 때 “아 과적합이네” 하고 넘어가기 쉽다. 그런데 아니다. 과적합이면 훈련 오차는 낮고 검증 오차만 높아야 한다. 여기서는 훈련 오차부터 높다. 즉 모델이 답을 외우는 데조차 실패한 것이다.
이걸 퇴화(Degradation) 문제라고 부른다.
논리적으로 이상한 상황
생각해보면 이건 말이 안 된다. 56층 모델은 앞의 20층을 그대로 쓰고 나머지 36층이 아무것도 안 하면(항등 함수) 최소한 20층 모델과 똑같은 성능이 나와야 한다. 그런데 실제로는 더 나쁘다.
즉 문제는 표현력이 아니라 “아무것도 안 하기”조차 학습으로 배우기 어렵다는 데 있었다.
그러면 배우게 하지 말고 그냥 주자
잔차 블록의 아이디어가 이거다.
$$ \text{출력} = F(x) + x $$
입력 x를 두 갈래로 보낸다. 하나는 합성곱을 통과하고(F(x)), 하나는 아무 계산 없이 그대로 간다(지름길, shortcut). 마지막에 둘을 더한다.
이러면 “아무것도 안 하기”가 공짜다. F(x)가 0이 되기만 하면 출력이 x 그대로다. 실제로 잔차 블록의 마지막 합성곱 가중치를 0으로 초기화하면 처음부터 얕은 모델과 똑같은 예측에서 시작한다.
더 쉬운 비유로
계단 100개짜리 건물이 있다. 한 층씩 손으로 짐을 옮기라고 하면, 층이 많을수록 중간에 짐이 상하거나 잃어버릴 확률이 커진다. 그래서 엘리베이터(지름길)를 놨다. 급하면 그냥 짐을 그대로 올려보내면 되고, 필요한 층에서만 짐을 손질한다. 손질을 잘 못하는 층이 있어도 최소한 원래 짐은 도착한다.
기울기 관점에서도 같다. 덧셈 경로가 있어서 기울기가 깊은 층까지 끊기지 않고 내려간다. 10편에서 LSTM이 셀 상태를 덧셈으로 전달해 기울기 소실을 막았던 것과 정확히 같은 발상이다. 데이터 종류만 다르지 방법은 같다.
보틀넥 — 더 깊게, 더 싸게
ResNet-50 이상은 잔차 블록 안을 이렇게 바꾼다.
1×1로 채널을 줄이고 → 3×3 하고 → 1×1로 되돌린다
핵심은 1×1 합성곱이다. 공간(가로·세로)은 건드리지 않고 채널만 섞는 연산이라, 채널 수를 조절하는 밸브 역할을 한다. 256채널을 64로 줄여놓고 비싼 3×3을 시킨 다음 다시 256으로 되돌린다.
FLOPs는 18HWC² → 17HWC². 숫자만 보면 별거 아닌 것 같은데, 층이 3배로 늘어난 대가로 비용이 오히려 줄었다는 게 요점이다.
ResNet의 나머지 재료
| 요소 | 내용 |
|---|---|
| 스템(Stem) | 초반에 입력 해상도를 1/4로 줄이고 시작 (비싼 초반부를 아낌) |
| 전역 평균 풀링 | 완전연결층 여러 개 대신 채널별 평균 하나 → 마지막 FC 1개만 |
| 배치 정규화 | 모든 합성곱 뒤에 적용 |
| He 초기화 | ReLU와 궁합이 맞는 초기화 (25편에서 자세히) |
전역 평균 풀링이 특히 중요하다. AlexNet의 파라미터 절반을 잡아먹던 FC1을 통째로 없애버린 셈이니까.
성능 비교
| 모델 | 구조 | Top-5 에러 | GFLOPs |
|---|---|---|---|
| ResNet-18 | 18층, 기본 블록 | 10.92% | 1.8 |
| ResNet-34 | 34층, 기본 블록 | 8.58% | 3.6 |
| ResNet-50 | 50층, 보틀넥 | 7.13% | 3.8 |
| VGG-16 | 16층, 일반 CNN | 9.62% | 13.6 |
ResNet-34를 보라. VGG-16보다 정확하면서 연산량은 4분의 1이다. 좋은 구조가 무엇인지 이보다 명확한 표가 없다.
5. MobileNet — 휴대폰 안으로
여기서 질문이 바뀐다. 정확도가 아니라 “이걸 서버 없이 돌릴 수 있나”다.
문제 진단은 이랬다.
기존 합성곱은 공간(H×W)과 채널(C)을 한 번에 처리한다. 그래서 비싸다.
MobileNet은 이걸 두 단계로 쪼갠다.
- 깊이별 합성곱(Depthwise) — 채널마다 따로 3×3을 돌린다. 공간만 담당
- 화소별 합성곱(Pointwise) — 1×1로 채널을 섞는다. 채널만 담당
절감 비율을 직접 계산해보면
| 방식 | 연산량 |
|---|---|
| 일반 합성곱 | 9C²HW |
| 깊이별 + 화소별 | 9CHW + C²HW |
비율을 구해보자.
$$ \frac{9C^2HW}{9CHW + C^2HW} = \frac{9C}{9+C} $$
여기서 채널 C를 키우면 어떻게 되는가. C가 64, 128, 256처럼 커질수록 분모의 9는 무시할 만해지고, 값은 9에 수렴한다.
$$ \lim_{C \to \infty} \frac{9C}{9+C} = 9 $$
즉 연산량이 약 9분의 1. 이 한 줄이 딥러닝을 서버 밖으로 꺼냈다.
더 쉬운 비유로
빨래를 한다고 하자. 원래는 세탁기 한 대에 전부 넣고 한 번에 돌렸다. 그런데 MobileNet은 색깔별로 따로 빨고(깊이별), 마지막에 한 번 모아서 정리한다(화소별). 일을 두 번 하는 것 같은데, 각 단계가 훨씬 단순해져서 총 시간은 훨씬 짧다.
이 구조는 이후 거의 모든 경량 모델의 표준 부품이 됐다.
6. 계보를 한 줄로 다시 보면
각 모델이 CNN의 한계를 하나씩 걷어낸 순서다.
| 모델 | 걷어낸 한계 | 남긴 유산 |
|---|---|---|
| AlexNet (2012) | “깊은 CNN은 안 된다” | ReLU, 드롭아웃, GPU 학습 |
| VGG (2014) | “설계는 감으로 한다” | 3×3 반복, 블록 문법 |
| GoogLeNet (2014) | “층이 넓으면 비싸다” | 인셉션 모듈, 1×1 차원 축소 |
| ResNet (2015) | “깊으면 학습이 안 된다” | 잔차 연결, 전역 평균 풀링 |
| MobileNet (2017) | “무거워서 못 쓴다” | 깊이별·화소별 분리 |
확인 문제로 자주 나오는 순서도 이거다. AlexNet → VGG → GoogLeNet → ResNet → MobileNet.
그리고 개인적으로 오래 남는 감각은 이쪽이다. 이 계보는 새로운 수학이 나와서 뚫린 게 아니다. “쌓아봤더니 안 되네” 하고 관찰한 사람이, 왜 안 되는지 정확히 짚고, 가장 단순한 우회로를 낸 것이다. 잔차 연결은 덧셈 하나고, 보틀넥은 1×1이고, MobileNet은 나눗셈이다. 다 초등학교 산수다.
정리
- ImageNet 에러율은 28% → 3.6%로 떨어졌고, 그 방향은 깊이가 늘어난 방향과 같다
-
AlexNet — 8층. 메모리는 앞쪽 합성곱, 파라미터는 완전연결층, 연산량은 합성곱층에 몰린다
- Conv1 계산: 출력 55×55×96, 파라미터 34.9K, 연산량 105.4M FLOPs
- VGG — 3×3 반복 / 2×2 풀링 / 풀링 후 채널 2배. 3×3 두 층 = 5×5 시야를 18C²에
-
ResNet — 퇴화 문제는 과적합이 아니다. 지름길로 최소 성능을 보장하고 100층 이상을 열었다
- 보틀넥(1×1 → 3×3 → 1×1)으로 더 깊게, 더 싸게
- MobileNet — 공간과 채널을 분리해 연산량 약 9분의 1
- “모델이 무겁다”는 말은 메모리·파라미터·연산량 중 무엇인지 먼저 물어야 한다
참고 자료
한줄 평
- 퇴화 문제를 보면서 제일 놀란 건 “깊게 했더니 나빠졌다”가 아니라, 그걸 과적합으로 착각하지 않고 끝까지 파고든 사람이 있었다는 사실이다.