Stanford cs231n: Deep Learning for Computer Vision 강의 정리 시리즈
챕터 7 - Training Neural Networks, Part II
강의 링크: YouTube
• • •
1. SGD의 한계
6강에서 SGD를 최적화의 기본으로 다뤘는데, 7강은 거기서 시작한다. SGD가 왜 부족한지를 먼저 짚고 나서 더 나은 방법들을 소개하는 흐름이다.
SGD의 업데이트 식은 이렇다.
단순한데, 이게 실전에서 세 가지 골치 아픈 문제를 일으킨다.
문제 1: 방향에 따라 다른 감도 (ill-conditioned curvature)
Loss 함수가 어떤 방향으로는 급격하게 변하고 다른 방향으로는 완만하게 변하는 경우를 생각해 보자. 아래 그림처럼 등고선이 납작한 타원형인 지형에서, 세로 방향은 gradient가 크고 가로 방향은 작다. 그러면 SGD는 세로로는 왔다 갔다 크게 진동하면서 가로로는 거의 못 나아가는 비효율적인 지그재그 경로를 택하게 된다.
▲ ill-conditioned loss surface에서 SGD는 목표를 향해 직진하지 못하고 지그재그를 친다 (출처: cs231n Lecture 7)
수학적으로는 Hessian 행렬의 가장 큰 singular value와 가장 작은 singular value의 비율(condition number)이 클수록 이 현상이 심해진다.
문제 2: 극소점 근처에서 멈춤 (local minima / saddle point)
gradient가 0이 되는 지점이 두 종류다. 하나는 진짜 극소점(local minimum), 다른 하나는 안장점(saddle point)이다. 안장점은 어떤 방향으로는 loss가 올라가고 다른 방향으로는 내려가는 지점인데, gradient 자체는 0이라 SGD가 거기 와서 멈춰버린다.
▲ local minimum과 saddle point. 둘 다 gradient가 0에 가까워지면 SGD는 이 자리에서 사실상 멈춘다 (출처: cs231n Lecture 7)
고차원에서는 모든 방향이 동시에 극소인 local minimum보다, 방향에 따라 오르내리는 saddle point가 압도적으로 많다. 딥러닝에서 local minimum보다 saddle point가 훨씬 더 큰 문제인 이유가 이거다.
문제 3: Minibatch gradient의 노이즈
SGD는 전체 데이터가 아닌 mini-batch로 gradient를 추정한다. 즉 매 스텝마다 진짜 gradient가 아닌 근사값을 쓰는 거다. 아래 그림에서 오른쪽 경로를 보면, 이상적으로는 직선으로 가야 할 길을 지저분하게 돌아가고 있는 게 보인다.
▲ minibatch gradient의 노이즈 때문에 SGD의 실제 경로(검은 선)는 지저분해진다 (출처: cs231n Lecture 7)
이 세 가지를 해결하거나 완화하기 위해 여러 optimizer들이 등장했다.
• • •
2. Fancier Optimization: SGD를 넘어서
SGD + Momentum
물리적으로 생각하면 이해가 쉽다. 공이 경사면을 구를 때 관성이 있어서 방향을 바꾸기 어렵듯이, Momentum은 이전에 이동하던 방향을 velocity로 기억해서 관성처럼 활용한다.
여기서 \(\rho\)는 마찰 계수 같은 역할이다. 보통 0.9나 0.99를 쓴다. 같은 방향으로 gradient가 쌓이면 속도가 붙어서 안장점을 탈출하기 쉽고, 방향이 번갈아 바뀌는 진동은 서로 상쇄되어 감쇠된다.
▲ Momentum(파란선)은 local minimum과 saddle point 모두에서 관성으로 탈출하고, gradient noise도 완화한다 (출처: cs231n Lecture 7)
Nesterov Momentum
Momentum의 살짝 개선된 버전이다. 일반 Momentum은 현재 위치에서 gradient를 계산한 뒤 velocity를 합친다. Nesterov는 순서를 바꿔서, velocity 방향으로 한 발 먼저 가본 다음 거기서 gradient를 계산한다. "지금 어디 있느냐"가 아니라 "어디로 가고 있느냐"를 반영한 gradient를 쓰는 거다.
▲ 일반 Momentum(왼쪽)은 현재 위치의 gradient와 velocity를 합산한다. Nesterov(오른쪽)는 먼저 velocity로 이동한 지점에서 gradient를 계산해 actual step을 구한다 (출처: cs231n Lecture 7)
convex 함수에서 수렴 속도가 이론적으로 더 빠르다는 게 증명돼 있고, 실전에서도 일반 Momentum보다 조금 낫다.
AdaGrad
지금까지는 모든 파라미터에 같은 learning rate를 적용했는데, AdaGrad는 각 파라미터마다 gradient의 누적 제곱합을 트래킹해서 learning rate를 개별적으로 조절한다.
아이디어는 좋은데 치명적인 문제가 있다. gradient 제곱을 계속 더하기만 하니까 분모가 단조롭게 커져서 결국 learning rate가 0에 수렴하고 업데이트가 멈춰버린다. 긴 학습에서는 쓰기 어렵다.
RMSProp
AdaGrad의 "분모가 계속 커지는" 문제를 고친 게 RMSProp이다. 누적 합 대신 지수이동평균을 써서 옛날 gradient는 잊게 만든다. 아래 그림에서 딱 한 줄 차이가 핵심이다.
▲ AdaGrad와 RMSProp의 차이는 grad_squared 업데이트 한 줄뿐이다. 누적합(+=)에서 지수이동평균으로 바꾼 것 (출처: cs231n Lecture 7)
보통 \(\beta = 0.9\)를 쓴다. 덕분에 분모가 무한정 커지지 않고 최근 gradient의 크기에 적응적으로 반응한다.
Adam
딥러닝에서 현재 가장 많이 쓰이는 optimizer다. Momentum(1차 모멘트)과 RMSProp(2차 모멘트)을 합친 것이고, 거기에 초기 bias correction까지 추가됐다. 아래 코드에서 색깔로 각 부분이 표시되어 있다.
▲ Adam 전체 코드. 빨간 박스가 Momentum, 파란 박스가 RMSProp, 초록 박스가 bias correction이다 (출처: cs231n Lecture 7)
초기에 first_moment와 second_moment가 0으로 시작하니까 처음 몇 스텝은 값이 0에 가깝게 편향된다. Bias correction이 이걸 보정해서 학습 초반부터 안정적으로 움직이게 한다.
추천 기본값은 \(\beta_1 = 0.9\), \(\beta_2 = 0.999\), \(\epsilon = 10^{-8}\)이고, learning rate는 1e-3 또는 5e-4가 많은 모델에서 좋은 출발점이다. 아래가 4가지 optimizer의 경로 비교다.
▲ SGD(검정) / SGD+Momentum(파랑) / RMSProp(빨강) / Adam(보라)의 경로 비교 (출처: cs231n Lecture 7)
처음 실험에는 Adam으로 시작하는 게 무난하다. 다만 일부 연구에서는 SGD + Nesterov Momentum을 잘 튜닝하면 Adam보다 일반화 성능이 더 좋은 경우가 있다고 보고한다. 어떤 게 더 좋다고 일반화할 수는 없고, 태스크와 데이터에 따라 다르다.
2차 방법 (Second-Order Methods)
지금까지 본 방법들은 전부 1차 미분(gradient)만 이용한다. 2차 방법은 Hessian(2차 미분)까지 활용해서 "얼마나 굽어 있느냐"까지 고려한다. 뉴턴 방법의 업데이트 식은 이렇다.
learning rate가 필요 없고 이론적으로 훨씬 정확하다. 그런데 파라미터 수가 \(N\)이면 Hessian의 크기가 \(N \times N\)이고, 역행렬 계산이 \(O(N^3)\)이다. 수억 개 파라미터를 가진 딥러닝 모델에서는 그냥 불가능하다. L-BFGS 같은 quasi-Newton 방법이 이걸 근사하지만, 이것도 full batch에서나 의미 있고 mini-batch 환경에는 안 맞는다. 결론적으로 대규모 딥러닝에서 2차 방법은 사실상 쓰이지 않는다.
• • •
3. Learning Rate Schedule
모든 optimizer에서 learning rate는 반드시 있는 hyperparameter다. 근데 학습 중에 이걸 고정으로 유지하는 건 최선이 아니다. 아래 그래프가 잘 보여준다.
▲ 왼쪽: learning rate 크기에 따른 loss curve 패턴. 오른쪽: step decay를 적용하면 평탄해진 구간에서 loss가 다시 확 내려간다 (출처: cs231n Lecture 7)
처음엔 빠르게 탐색해야 하니 큰 learning rate가 유리하고, 수렴 단계에서는 작은 learning rate로 세밀하게 조정해야 한다. 오른쪽 그래프에서 learning rate를 줄인 시점마다 loss가 계단식으로 내려가는 게 보인다.
Step Decay
가장 직관적이다. 일정 epoch마다 learning rate를 고정 비율로 줄인다. 예를 들어 30 epoch마다 0.1배씩 감소. 단순하지만 언제 얼마나 줄일지를 직접 정해야 해서 튜닝이 필요하다. learning rate decay는 Adam보다 SGD+Momentum에서 훨씬 중요하다.
Cosine Annealing
현재 가장 널리 쓰이는 방식이다. Learning rate를 코사인 함수 모양으로 부드럽게 줄여나간다.
처음엔 최대값에서 시작해 학습이 끝날 무렵엔 최소값에 도달한다. "언제 줄일지"를 정할 필요 없이 자연스럽게 감소한다.
Linear Warmup
학습 초반에 파라미터가 아직 불안정한 상태에서 큰 learning rate로 바로 업데이트하면 발산할 수 있다. Warmup은 처음 몇 epoch 동안 learning rate를 0에서부터 목표값까지 선형으로 서서히 올리는 방법이다. 큰 batch size를 쓸 때나 Transformer 계열 모델에서 거의 필수적으로 사용된다.
• • •
4. Regularization
optimization이 training loss를 줄이는 거라면, regularization은 training과 validation 사이의 gap을 줄이는 거다. 아래 그래프가 이 차이를 명확하게 보여준다.
▲ 왼쪽: optimizer를 개선하면 training loss는 잘 내려간다. 오른쪽: 하지만 진짜 문제는 train과 val 사이의 gap이다 (출처: cs231n Lecture 7)
더 좋은 optimizer를 써도 이 gap은 줄지 않는다. Regularization이 필요한 이유다.
Dropout
학습 중에 각 뉴런을 일정 확률 \(p\)로 랜덤하게 꺼버리는 방법이다. 확률 \(p\)는 보통 0.5를 쓴다.
▲ 왼쪽이 full network, 오른쪽이 Dropout 적용 후. 매 forward pass마다 다른 뉴런 조합이 꺼진다 (출처: cs231n Lecture 7)
왜 이게 효과가 있을까. 아래 슬라이드가 직관적인 설명을 준다.
▲ 고양이를 분류할 때 특정 특징에만 의존하면 그 특징이 꺼졌을 때 망한다. Dropout은 모든 특징을 골고루 학습하도록 강제한다 (출처: cs231n Lecture 7)
매번 다른 뉴런 조합을 쓰니까 사실상 exponential하게 많은 서로 다른 부분 네트워크를 학습시키는 셈이고, 테스트 시에는 이 모든 네트워크의 평균을 내는 효과를 얻는다. 앙상블과 같은 원리다.
주의할 점이 있다. 학습 시 \(p\) 확률로 뉴런을 끄면 테스트 시 전체 뉴런이 켜지니까 출력의 기댓값이 달라진다. 이를 맞추는 표준 방법이 inverted dropout인데, 학습 시 출력에 \(\frac{1}{p}\)를 미리 곱해두는 거다. PyTorch의 nn.Dropout이 이 방식을 쓴다.
Data Augmentation
데이터를 변환해서 인위적으로 다양성을 늘리는 방법이다. 가로 뒤집기, 랜덤 crop, 색상 jitter(밝기·채도·색조 변화) 등을 학습 중에 랜덤하게 적용한다. ResNet 기준으로, 학습 시에는 256~480 사이에서 랜덤하게 크기를 정하고 224×224 패치를 잘라낸다. 테스트 시에는 여러 scale에서 여러 crop을 뽑아 평균내는데, 이게 앙상블 효과를 만들어낸다.
Regularization의 공통 패턴
Dropout, Batch Normalization, Data Augmentation, DropConnect, Stochastic Depth 등을 관통하는 공통 패턴이 있다. 학습 시에는 어떤 형태의 랜덤 노이즈를 추가하고, 테스트 시에는 그 랜덤성을 평균화한다. BN이 학습 시 minibatch 통계를 쓰고 테스트 시 고정된 통계를 쓰는 것도 같은 맥락이다.
• • •
5. Model Ensembles
여러 모델을 독립적으로 학습시킨 뒤, 테스트 시 각 모델의 예측을 평균내는 방법이다. 분산을 줄여서 일반화 성능이 올라간다. 실전 대회에서 상위권을 노릴 때 거의 필수적으로 쓰인다.
모델 여러 개를 새로 학습시키는 건 비용이 크다. 그래서 나온 아이디어가 Snapshot Ensemble이다.
▲ 왼쪽: 단일 모델은 LR decay로 하나의 minimum에 수렴한다. 오른쪽: Cyclic LR로 여러 minimum을 탐색하고 각 시점을 저장해 앙상블한다 (출처: cs231n Lecture 7)
하나의 모델을 학습하면서 learning rate를 주기적으로 올렸다가 내리면(cosine annealing with restart), 매 사이클마다 다른 local minimum에 수렴한다. 각 사이클 끝에서 checkpoint를 저장해두면 추가 학습 비용 없이 여러 모델 앙상블과 비슷한 효과를 얻는다.
• • •
6. Transfer Learning
대규모 데이터셋으로 미리 학습된 모델의 가중치를 내 태스크에 재활용하는 방법이다. 내 데이터가 적거나 학습 리소스가 부족할 때 특히 강력하다.
CNN의 앞쪽 레이어들은 edge, texture 같은 low-level 특징을 학습하고, 뒤로 갈수록 task-specific한 high-level 특징을 학습한다. Low-level 특징은 어떤 시각 태스크에서나 공통적으로 유용하니까 가져다 쓰고, 마지막 레이어만 내 태스크에 맞게 바꾸면 된다.
▲ 데이터 크기에 따른 전략. 작으면 FC 레이어만 재학습(가운데), 많으면 상위 레이어까지 fine-tuning(오른쪽). fine-tuning 시 learning rate는 원본의 1/10이 좋은 출발점이다 (출처: cs231n Lecture 7)
데이터 크기 × 유사도에 따른 전략
▲ Transfer Learning 전략 결정 매트릭스. 가로축은 source 데이터와의 유사도, 세로축은 데이터 크기다 (출처: cs231n Lecture 7)
데이터 적고 유사도 높은 경우: 마지막 FC 레이어만 새로 학습한다. 나머지 레이어는 freeze. 데이터가 적으니까 많이 건드리면 오히려 overfitting된다.
데이터 많고 유사도 높은 경우: 상위 몇 레이어까지 fine-tuning한다. 앞쪽은 낮은 lr로, 뒤쪽은 높은 lr로 학습한다.
데이터 적고 유사도 낮은 경우: 가장 어려운 상황이다. 앞쪽의 일반적인 특징 레이어만 가져다 쓰는 게 그나마 낫다.
데이터 많고 유사도 낮은 경우: 전체를 fine-tuning하거나 처음부터 학습해도 된다. pretrained weight를 초기값으로 쓰면 random init보다 훨씬 빠르게 수렴한다.
이게 단순히 이론에 그치지 않는다는 걸 아래 슬라이드가 보여준다.
▲ Transfer Learning은 예외가 아니라 표준이다. Fast R-CNN도, Image Captioning (CNN+RNN)도, 모두 ImageNet pretrained CNN을 backbone으로 쓴다 (출처: cs231n Lecture 7)
Object Detection(Fast R-CNN)에서 ConvNet backbone도, Image Captioning에서 CNN 인코더도, 심지어 word2vec도 전부 pretrained 모델을 가져다 쓴다. Computer vision 태스크에서 ImageNet pretrained 모델을 쓰지 않는 건 이미 손해를 자처하는 거나 다름없다.
• • •
핵심 요약
| 개념 | 한 줄 요약 |
|---|---|
| SGD 문제 | ill-conditioned curvature, saddle point 정체, minibatch 노이즈 |
| SGD + Momentum | velocity로 관성 누적, 진동 감소 + 안장점 탈출. rho=0.9~0.99 |
| Nesterov | velocity 방향 미리 가본 뒤 gradient 계산, convex에서 이론적 우위 |
| AdaGrad | 파라미터별 adaptive lr, 누적 제곱합으로 분모 단조증가 → 조기 종료 |
| RMSProp | AdaGrad 개선, 지수이동평균으로 분모 제어 |
| Adam | Momentum + RMSProp + bias correction, 실전 기본값. β1=0.9, β2=0.999 |
| LR Schedule | Cosine annealing이 현재 표준, warmup은 초반 불안정 방지 |
| Dropout | 랜덤 뉴런 비활성화 → 앙상블 효과. Inverted dropout이 표준 |
| Data Augmentation | flip/crop/color jitter로 다양성 증가, 테스트 시 앙상블 효과 |
| Snapshot Ensemble | Cyclic LR로 한 모델에서 여러 minimum 탐색 후 checkpoint 앙상블 |
| Transfer Learning | 데이터 크기·유사도에 따라 freeze 범위 조정. Computer Vision에서 사실상 표준 |
• • •
참고
- cs231n Lecture 7 (YouTube)
- cs231n 공식 강의 노트
- Kingma & Ba (2014), Adam: A Method for Stochastic Optimization
- Srivastava et al. (2014), Dropout: A Simple Way to Prevent Neural Networks from Overfitting
- Huang et al. (2017), Snapshot Ensembles: Train 1, Get M for Free
• • •
다음: Lecture 8 - Deep Learning Software