224×224 픽셀 하나가 1000개의 확률로 바뀌기까지, 8개의 층에서 벌어지는 일을 직접 돌려보면서 따라갑니다. 이 페이지의 필터·이미지·수치는 원논문과 2012년 원본 소스코드에서 그대로 가져왔습니다.
모든 데모는 브라우저에서 실제로 계산됩니다. 애니메이션이 아니라 연산 결과입니다.
파라미터·뉴런·곱셈 횟수는 원본 layers-145.cfg의 설정값을 cuda-convnet의
출력 크기 공식으로 직접 계산한 값입니다. 논문의 “약 6000만 파라미터, 약 65만 뉴런”과 일치합니다.
가로 폭은 공간 해상도(224→55→27→13→6), 세로 높이는 채널 수를 나타냅니다. 해상도를 줄이고 채널을 늘리는 것 — 이것이 CNN이 “픽셀”을 “의미”로 바꾸는 방식입니다. 블록을 눌러 각 층에서 벌어지는 일을 확인하세요.
AlexNet 설명을 읽다 보면 입력이 224냐 227이냐로 늘 논쟁이 붙습니다.
보통 쓰는 공식 ⌊(224−11)/4⌋+1 = 54로는 논문의 55가 안 나오기 때문입니다.
원본 코드를 열어보면 답이 있습니다. cuda-convnet은 내림이 아니라 올림을 씁니다.
# 1004행 — ceil 이 224 입력에서 55 를 만들어낸다 dic['modulesX'] = 1 + int(ceil((2 * padding + imgSize - filterSize) / float(stride)))
올림을 쓰면 필터가 이미지 오른쪽·아래 경계를 살짝 넘어가는 위치까지 계산합니다(넘어간 부분은 0으로 처리). 그래서 224 입력 그대로 55×55가 나옵니다. 227이라는 숫자는 나중에 다른 프레임워크의 내림 공식에 맞추려고 역산해 만든 값이지, 원본 코드가 쓴 값이 아닙니다.
conv1은 11×11×3 크기의 필터를 4픽셀씩 건너뛰며 이미지 위를 미끄러집니다. 각 위치에서 하는 일은 딱 하나 — 필터와 그 자리 픽셀의 내적. 그 값 하나가 오른쪽 55×55 지도의 점 하나가 됩니다. 아래는 논문 Figure 4의 실제 테스트 이미지에 논문 Figure 3의 실제 커널을 적용한 결과입니다.
출력 지도에서 분홍은 양수(필터 모양과 잘 맞음), 파랑은 음수(반대 모양), 회색은 0입니다. 같은 필터 하나가 3,025개 위치 전부에 똑같이 쓰입니다 — 이것이 CNN의 파라미터를 획기적으로 줄이고, 물체가 어디에 있든 알아보게 만드는 이유입니다.
아무도 “가로선 검출기를 만들어라”라고 알려주지 않았습니다. 경사하강법만으로 96개 필터가 스스로 방향과 주파수를 나눠 가졌습니다. 더 놀라운 건 그 다음입니다 — 위쪽 48개(GPU 1)는 색을 거의 무시하는 흑백 엣지 검출기가, 아래쪽 48개(GPU 2)는 색 덩어리 검출기가 되었습니다. 두 GPU가 서로 통신하지 않는 층에서 역할 분담이 저절로 생긴 것이고, 논문은 이 현상이 매 학습마다 반복된다고 적었습니다.
같은 사진 한 장이 필터에 따라 전혀 다르게 보입니다. 가로 엣지 필터는 가로 줄무늬만, 세로 엣지 필터는 세로 윤곽만, 색상 필터는 색 경계만 밝게 남깁니다 (ReLU를 적용해 음수는 0으로 잘랐습니다). AlexNet은 이런 지도를 96장 만든 뒤, 다음 층에서 그것들을 다시 조합합니다. 위에서 이미지를 바꾸면 여기도 함께 바뀝니다.
2012년 이전의 표준은 sigmoid와 tanh였습니다. 문제는 양끝이 평평하다는 것. 평평한 곳에서는 기울기가 0에 가까워지고, 그 0에 가까운 값이 층을 거슬러 올라가며 곱해지면 앞쪽 층은 학습 신호를 거의 받지 못합니다. 이것이 “깊은 망은 훈련이 안 된다”는 정설의 실체였습니다.
__device__ inline float operator()(float x) const { return x < 0.0f ? 0.0f : x; }
양수 구간에서 기울기가 정확히 1이라서, 층을 아무리 쌓아도 신호가 줄지 않습니다. 논문은 CIFAR-10에서 같은 4층 CNN이 학습 오류 25%에 도달하는 데 ReLU가 tanh보다 6배 적은 반복을 썼다고 보고합니다. 그리고 이렇게 덧붙입니다 — “포화형 뉴런을 썼다면 이 규모의 실험 자체가 불가능했다.”
3×3 창에서 가장 큰 값만 남기고 2픽셀씩 이동합니다. 창 크기(3)가 이동 폭(2)보다 크므로 창이 서로 겹칩니다. 당시 관행은 겹치지 않는 2×2/스트라이드 2였는데, AlexNet은 겹치게 만들어 top-5 오류를 0.3%p 더 낮췄고 과적합도 덜하다고 관찰했습니다.
AlexNet의 pool3(13×13 → 6×6)을 그대로 재현했습니다. 밝은 칸이 큰 값입니다. 풀링은 파라미터가 0이지만, 위치가 조금 흔들려도 같은 답을 내게 만드는 이동 불변성을 줍니다.
같은 위치의 이웃 채널들끼리 서로를 억누르게 하는 정규화입니다. 뇌의 측면 억제(lateral inhibition)에서 따왔고, 혼자 크게 튀는 필터만 살아남게 해서 반응을 더 선명하게 만듭니다. 효과는 top-1 1.4%p, top-5 1.2%p 개선 — 작지만 실재했습니다.
α를 키우면 주변에 강한 이웃이 많은 채널일수록 더 눌립니다. 혼자 튀는 값은 상대적으로 살아남습니다. LRN은 2015년 배치 정규화가 등장하면서 사실상 사라졌습니다. AlexNet에서도 결정적 요소는 아니었지만, “정규화가 학습을 돕는다”는 아이디어의 출발점이었습니다.
파라미터 6,096만 개 중 96%가 완전연결층 세 개에 몰려 있습니다. 이미지는 120만 장뿐. 그냥 두면 외워버립니다. AlexNet은 학습할 때마다 FC6·FC7 뉴런의 절반을 무작위로 꺼버리는 방법을 썼습니다. 힌턴의 비유대로, 공범을 찾으려면 용의자들을 따로따로 심문해야 하니까요.
[hs1a] # fc2048a 뒤 type=hs keep=0.5 inputs=fc2048a
학습 때마다 매번 다른 “가늘어진 망”을 뽑아 쓰는 셈이라, 사실상 지수적으로 많은 모델의 앙상블이 됩니다. 대가는 시간 — 논문은 수렴에 필요한 반복 횟수가 대략 두 배가 된다고 적었습니다. 그래도 드롭아웃 없이는 “심각한 과적합”이 일어났습니다.
256×256 이미지에서 224×224를 무작위로 잘라내고, 절반은 좌우로 뒤집습니다. 잘라낼 수 있는 위치가 32×32 = 1,024가지, 뒤집기까지 하면 2,048배. 여기에 RGB의 주성분 방향으로 색을 흔들어 조명 변화까지 흉내 냅니다. 비용은 거의 0 — GPU가 이전 배치를 학습하는 동안 CPU가 파이썬으로 만들어냈습니다.
추론할 때는 네 모서리 + 가운데 = 5개 크롭과 그 좌우 반전, 총 10장의 예측을 평균냅니다. 이 10-크롭 평균만으로도 top-5 오류가 18.3% → 17.0%로 내려갔습니다.
GTX 580의 메모리는 3GB. 망이 들어가지 않았습니다. 그래서 각 층의 필터를 절반씩 두 GPU에 나눠 싣고, 통신은 꼭 필요한 층에서만 하도록 설계했습니다. conv2·conv4·conv5는 자기 GPU 안에서만 연결되고, conv3와 완전연결층에서만 양쪽이 만납니다. 제약에서 나온 설계였지만 top-1 1.7%p, top-5 1.2%p를 벌어줬습니다.
[conv3a] type=conv inputs=pool2a,pool2b # ← 두 GPU의 출력을 모두 받음 filters=192,192 filterSize=3,3 gpu=0 [conv4a] type=conv inputs=conv3a # ← 자기 GPU 안에서만 filters=192 gpu=(상속)
옵티마이저는 화려하지 않습니다. 미니배치 128, 모멘텀 0.9, 가중치 감쇠 0.0005. 학습률은 0.01에서 시작해 검증 오류가 더 안 내려가면 사람이 손으로 10으로 나눴고, 학습이 끝날 때까지 세 번 그렇게 했습니다.
| 항목 | 값 | 원본 코드에서 |
|---|---|---|
| 미니배치 | 128 | --minibatch-size |
| 모멘텀 | 0.9 | momW=0.9 |
| 가중치 감쇠 | 0.0005 | wc=0.0005 |
| 학습률 초기값 | 0.01 | epsW=0.01 |
| 학습률 최종값 | 0.00001 | epsW=0.00001 — 10으로 세 번 나눈 값 |
| 가중치 초기화 | N(0, 0.01²) | initW=0.01 |
| 편향 초기화 | 1 또는 0 | initB=1 — conv2·4·5와 FC층 |
| 에폭 | 약 90 | --epochs=95 |
같은 망인데 “무게”와 “일”이 정확히 반대편에 몰려 있습니다. 합성곱층은 전체 파라미터의 3.8%뿐이지만 곱셈의 92%를 합니다. 완전연결층은 파라미터의 96%를 차지하면서 계산은 8%만 합니다. 이 불균형을 읽어낸 것이 이후 VGG·GoogLeNet·ResNet의 설계 방향을 결정했습니다.
| 층 | 출력 | 파라미터 | 곱셈(MAC) |
|---|
conv1은 파라미터가 3만 5천 개(전체의 0.06%)뿐인데 곱셈은 1억 500만 번을 합니다. 필터 한 장을 3,025개 위치에 재사용하기 때문입니다. 반대로 FC6은 가중치 3,775만 개를 딱 한 번씩만 씁니다.
컴퓨터역사박물관이 2024년에 공개한 2012년 원본 코드를 읽으면,
논문 설명과 미묘하게 다르거나 논문에 아예 없는 것들이 보입니다.
모두 layers/layers-145.cfg, layer.py, src/에서 직접 확인한 내용입니다.
저장소에는 이런 설정 파일이 150개 넘게 들어 있습니다. 번호가 붙은 실험 로그들 —
layers-100부터 layers-184-4gpu까지. 논문 한 편 뒤에
얼마나 많은 시도가 있었는지 파일 이름만으로도 보입니다.
2010·2011년의 우승자는 SIFT 같은 손으로 설계한 특징 + SVM이었고, 성능은 정체돼 있었습니다. 2012년 AlexNet은 대회에 나온 유일한 신경망이었고 오류율을 절반으로 잘랐습니다. 이듬해 참가 팀은 24개로 늘었고, 거의 전부가 CNN이었습니다.
2010–2011은 SIFT·Fisher vector 계열, 2012년부터는 전부 CNN입니다. 2015년 ResNet이 3.57%로 사람의 오류율(약 5%)을 넘어섰고, 2017년에는 참가 팀의 76%가 top-5 정확도 95%를 넘기며 벤치마크가 포화됐습니다.
| 연도 | top-5 오류율 | 방식 |
|---|