개요

22편에서 CNN이 사진을 보는 방식을 봤다. 이번 글은 그 부품들로 사람들이 실제로 무엇을 만들었는지다.

모델 이름을 외우는 글이 아니다. 나는 이 계보가 네 번의 질문과 네 번의 대답이라고 생각한다.

연도 모델 던진 질문 대답
2012 AlexNet 깊은 CNN이 진짜 되나? 된다, GPU만 있으면
2014 VGG 어떻게 쌓는 게 좋은가? 작은 필터를 깊게
2015 ResNet 더 깊게는 왜 안 되나? 지름길을 내면 된다
2017 MobileNet 꼭 이렇게 비싸야 하나? 쪼개면 9배 싸진다

교육 자료는 대외비라 슬라이드 이미지나 예제 데이터는 싣지 않는다. 개념 흐름만 내가 이해한 방식으로 재구성했고, 그림은 전부 생성했다.


1. 판이 갈린 순간

ImageNet 에러율 변화

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억 번이다. 이런 층이 여덟 개다.

이 계산이 왜 중요한가

층별로 다 계산해 보면 아주 흥미로운 그림이 나온다.

AlexNet의 층별 비용 분포

자원 어디에 몰리나
메모리 앞쪽 합성곱층 해상도가 커서 특징 맵 자체가 크다 (Conv1 = 1,134KB)
파라미터 완전연결층 FC1 하나가 37,753K, 전체의 절반이 넘는다
연산량 합성곱층 Conv2 하나가 448M FLOPs

이 세 줄이 이번 편에서 가장 실무적인 부분이라고 생각한다. “모델이 무겁다”는 말은 사실 세 가지 다른 문제를 뭉뚱그린 말이다.

  • 학습 중 OOM이 난다 → 앞쪽 해상도를 줄이거나 배치를 줄여야 한다
  • 모델 파일이 너무 크다 → 완전연결층을 손봐야 한다
  • 추론이 느리다 → 합성곱층을 줄여야 한다

엉뚱한 곳을 깎으면 아무것도 안 나아진다. 이후 모델들이 완전연결층을 없애고(전역 평균 풀링), 합성곱을 쪼개는(MobileNet) 방향으로 간 이유가 여기 다 들어 있다.


3. VGG — 설계에 규칙을 준 모델

VGG의 기여는 성능(7.3%)보다도 규칙이다. 자료에 나온 디자인 룰이 딱 세 줄이다.

  1. 3×3 합성곱 / 스트라이드 1 / 패딩 1을 반복한다
  2. 2×2 맥스 풀링으로 크기를 절반으로 줄인다
  3. 풀링 후에는 채널 수를 2배로 늘린다

이 규칙만 알면 VGG-16이든 VGG-19든 종이에 그릴 수 있다. 그전까지 모델 설계는 감이었는데, VGG 이후로는 블록을 반복하는 문법이 됐다.

왜 하필 3×3인가

3x3 두 층과 5x5 한 층 비교

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은 이걸 두 단계로 쪼갠다.

  1. 깊이별 합성곱(Depthwise) — 채널마다 따로 3×3을 돌린다. 공간만 담당
  2. 화소별 합성곱(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
  • “모델이 무겁다”는 말은 메모리·파라미터·연산량 중 무엇인지 먼저 물어야 한다

참고 자료

한줄 평

  • 퇴화 문제를 보면서 제일 놀란 건 “깊게 했더니 나빠졌다”가 아니라, 그걸 과적합으로 착각하지 않고 끝까지 파고든 사람이 있었다는 사실이다.