Step 6에서 우리가 만든 CNN은 약 70-75%의 정확도를 보였습니다. 나쁘지 않지만, 더 좋은 방법이 있습니다. 바로 전이학습(Transfer Learning)입니다.
상상해보세요. 영어를 이미 잘하는 사람이 스페인어를 배울 때,
알파벳부터 다시 배우지 않죠. 영어 문법 지식을 활용하면 훨씬 빠릅니다.
딥러닝도 마찬가지입니다!
ImageNet 1000개 클래스를 이미 학습한 모델은:
• 가장자리, 질감, 색상 패턴을 인식하는 법을 알고 있습니다
• 눈, 코, 귀 같은 얼굴 부위를 감지할 수 있습니다
• 동물의 털, 다리, 꼬리 등을 구별할 수 있습니다
이런 "일반적인 시각 지식"을 우리 문제(고양이 vs 강아지)에 그대로 활용하는 것이
바로 전이학습입니다! 🚀
전이학습을 사용하는 방법은 크게 두 가지입니다. 데이터의 양과 유사도에 따라 선택합니다.
사전학습된 모델을 "고정된 특징 추출기"로 사용하는 방법입니다.
📌 동작 방식:
1. 사전학습 모델의 모든 층을 동결(freeze)
→ Conv층의 가중치는 절대 업데이트하지 않음
2. 마지막 FC층만 교체하고 학습
→ 1000 클래스 → 2 클래스 (고양이/강아지)
3. 사전학습 층은 특징만 뽑아주고, 새 FC층이 분류 학습
from torchvision import models import torch.nn as nn # ResNet50 사전학습 모델 로드 model = models.resnet50(pretrained=True) # 모든 파라미터 동결 for param in model.parameters(): param.requires_grad = False # 학습 안 함! # 마지막 FC층만 교체 (2 클래스) num_features = model.fc.in_features model.fc = nn.Linear(num_features, 2) # 이것만 학습됨
✅ 언제 사용?
• 데이터가 적을 때 (수백~수천 장)
• 빠른 프로토타입이 필요할 때
• 컴퓨팅 자원이 제한적일 때
사전학습 모델의 일부 또는 전체를 우리 데이터에 맞게 재학습하는 방법입니다.
📌 동작 방식:
1. 사전학습 모델을 로드 (ImageNet 가중치 포함)
2. 마지막 FC층 교체
3. 전체 네트워크를 학습 (단, 차등 학습률 적용)
→ 하위 층: 매우 낮은 학습률 (기존 지식 보존)
→ 상위 층: 보통 학습률
→ 새 FC층: 높은 학습률
import torch.optim as optim # ResNet50 로드 model = models.resnet50(pretrained=True) # 마지막 FC층 교체 model.fc = nn.Linear(model.fc.in_features, 2) # 차등 학습률 설정 optimizer = optim.Adam([ {'params': model.layer1.parameters(), 'lr': 1e-5}, # 하위 층: 매우 낮은 LR {'params': model.layer2.parameters(), 'lr': 1e-5}, {'params': model.layer3.parameters(), 'lr': 1e-4}, # 중간 층: 낮은 LR {'params': model.layer4.parameters(), 'lr': 1e-4}, {'params': model.fc.parameters(), 'lr': 1e-3} # 새 FC층: 높은 LR ])
✅ 언제 사용?
• 데이터가 충분할 때 (수천~수만 장)
• 최고 성능이 필요할 때
• 시간과 컴퓨팅 자원이 있을 때
| 상황 | 데이터 양 | 추천 전략 | 이유 |
|---|---|---|---|
| 데이터 매우 적음 | < 1,000장 | Feature Extraction | 과적합 방지, 빠른 학습 |
| 데이터 적음 | 1,000 ~ 5,000장 | Feature Extraction 또는 상위 층만 Fine-tuning | 안정적인 학습 보장 |
| 데이터 중간 | 5,000 ~ 10,000장 | Fine-tuning (일부 층) | 성능과 안정성의 균형 |
| 데이터 많음 | > 10,000장 | Fine-tuning (전체 층) | 최고 성능 달성 가능 |
| 빠른 프로토타입 | 상관없음 | Feature Extraction | 빠른 실험과 검증 |
PyTorch에서는 다양한 사전학습 모델을 제공합니다. 각 모델의 특징을 알아봅시다.
| 모델 | 년도 | 깊이 | 파라미터 | Top-1 Acc | 특징 |
|---|---|---|---|---|---|
| AlexNet | 2012 | 8층 | 61M | 56.5% | 딥러닝 시대를 연 역사적 모델 |
| VGG16/19 | 2014 | 16-19층 | 138M | 71.5% | 단순하고 이해하기 쉬움 |
| ResNet50 | 2015 | 50층 | 25M | 76.1% | ⭐ 가장 많이 사용, Skip Connection |
| ResNet101 | 2015 | 101층 | 45M | 77.4% | ResNet50보다 깊고 정확 |
| Inception v3 | 2015 | 48층 | 27M | 77.5% | 효율적인 멀티스케일 처리 |
| MobileNet v2 | 2018 | 54층 | 3.5M | 71.8% | ⚡ 모바일/임베디드용, 매우 가벼움 |
| EfficientNet | 2019 | 다양 | 5-66M | 84.3% | 🚀 효율성과 정확도의 균형 |
| Vision Transformer | 2020 | 12-24층 | 86-632M | 88.5% | 💡 Transformer 기반 (최신 트렌드) |
💡 추천 모델:
• 초보자: ResNet50 (안정적이고 성능 좋음)
• 모바일/임베디드: MobileNet v2 (가볍고 빠름)
• 최고 성능: EfficientNet 또는 Vision Transformer
• 학습용: VGG16 (구조가 단순해서 이해하기 쉬움)
ResNet이 왜 이렇게 인기 있을까요? 바로 Skip Connection 때문입니다!
💡 왜 Skip Connection이 중요한가?
1. Gradient Vanishing 문제 해결
→ 깊은 네트워크에서도 그래디언트가 잘 전달됨
2. 항등 함수(Identity) 학습 가능
→ F(x) = 0을 학습하면 출력 = 입력 (아무것도 안 해도 됨)
→ 층을 더 쌓아도 성능이 나빠지지 않음!
3. 더 빠른 학습
→ 초기 학습 단계에서 빠르게 수렴
이제 실제로 전이학습을 구현해봅시다. ResNet50을 사용해서 고양이 vs 강아지를 분류해보겠습니다.
import torch import torch.nn as nn from torchvision import models # ResNet50 사전학습 모델 로드 # pretrained=True: ImageNet 가중치 포함 model = models.resnet50(pretrained=True) print(f"총 파라미터: {sum(p.numel() for p in model.parameters()):,}개") # 출력: 총 파라미터: 25,557,032개 # 모델 구조 확인 (마지막 부분) print(model.fc) # Linear(in_features=2048, out_features=1000, bias=True)
# 마지막 FC층 확인 num_features = model.fc.in_features # 2048 print(f"FC 입력 차원: {num_features}") # 1000 클래스 → 2 클래스로 교체 model.fc = nn.Linear(num_features, 2) print(f"수정된 FC층: {model.fc}") # Linear(in_features=2048, out_features=2, bias=True) # GPU로 이동 device = torch.device("cuda" if torch.cuda.is_available() else "cpu") model = model.to(device) print(f"Device: {device}")
전략 A: Feature Extraction (빠른 학습)
# 모든 파라미터 동결 for param in model.parameters(): param.requires_grad = False # 마지막 FC층만 학습 가능하게 for param in model.fc.parameters(): param.requires_grad = True # 옵티마이저: FC층만 import torch.optim as optim optimizer = optim.Adam(model.fc.parameters(), lr=0.001) print("학습 가능 파라미터:", sum(p.numel() for p in model.parameters() if p.requires_grad)) # 출력: 학습 가능 파라미터: 4,098 (FC층만)
전략 B: Fine-tuning (최고 성능)
# 모든 파라미터 학습 가능 (기본값) for param in model.parameters(): param.requires_grad = True # 차등 학습률 옵티마이저 optimizer = optim.Adam([ {'params': model.layer1.parameters(), 'lr': 1e-5}, # 하위 층: 매우 낮은 LR {'params': model.layer2.parameters(), 'lr': 1e-5}, {'params': model.layer3.parameters(), 'lr': 1e-4}, # 중간 층: 낮은 LR {'params': model.layer4.parameters(), 'lr': 1e-4}, {'params': model.fc.parameters(), 'lr': 1e-3} # FC층: 높은 LR ]) print("전체 파라미터 학습!") # 출력: 학습 가능 파라미터: 25,557,032개 (전체)
# 손실 함수 criterion = nn.CrossEntropyLoss() # 학습률 스케줄러 (검증 성능 기반) from torch.optim import lr_scheduler scheduler = lr_scheduler.ReduceLROnPlateau( optimizer, mode='max', # 정확도 최대화 factor=0.5, # 학습률을 절반으로 patience=3 # 3 epoch 개선 없으면 LR 감소 ) print("학습 준비 완료!")
이제 실제로 전이학습을 적용해서 고양이 vs 강아지를 분류해봅시다.
Step 6의 70-75%에서 95% 이상으로 성능을 끌어올릴 수 있습니다!
| 방법 | 학습 시간 | 검증 정확도 | 테스트 정확도 |
|---|---|---|---|
| 처음부터 학습 (Step 6) | 3-4시간 | 70-75% | 68-73% |
| 전이학습 (Feature Extraction) | 30-60분 | 90-93% | 88-91% |
| 전이학습 (Fine-tuning) | 1-2시간 | 95-98% | 94-97% |
💡 실습 팁:
• 먼저 Feature Extraction으로 빠르게 90% 달성
• 만족스럽지 않다면 Fine-tuning으로 95% 도전
• Data Augmentation을 더 강하게 적용하면 98%까지도 가능!
전이학습을 통해 95% 이상의 정확도를 달성했습니다!
📊 배운 내용 정리:
• ImageNet 사전학습 모델의 위력
• Feature Extraction vs Fine-tuning 전략
• 차등 학습률로 안정적인 Fine-tuning
• ResNet의 Skip Connection 원리
💡 실무에서의 전이학습:
• 의료 영상 분석: X-ray, CT 판독
• 자율주행: 도로 표지판, 차량 인식
• 제조업: 불량품 검출
• 패션: 옷 스타일 분류
실제로 딥러닝 엔지니어의 90% 이상은
모델을 처음부터 학습하지 않고,
사전학습 모델을 전이학습으로 활용합니다! 🚀