PyTorch를 활용한 전이 학습
오늘은 PyTorch로 사전 학습된 VGG 모델을 Caltech-101 데이터셋에 미세 조정하며, 사전 학습 모델을 활용해 새로운 과제의 성능을 높이는 방법을 보여 드리겠습니다. 이 글은 AI 번역본입니다. 오역이 의심되면 댓글로 알려 주세요.
Created on September 15|Last edited on September 15
Comment
소개
전이 학습은 사전 학습된 모델을 새로운 과제에 맞게 재활용하는 기법입니다. 비유를 들어 설명하면, 이탈리아 요리를 잘하는 사람이 중국 요리에 도전하는 경우와 같습니다. 양파를 다지는 법을 다시 배울 필요는 없으므로, 이미 가진 기술을 중국 요리에 그대로 옮겨 쓸 수 있습니다. 몇 가지 새로운 기술이 더 필요하겠지만, 이미 탄탄한 출발점을 갖추고 있는 셈입니다.
요약하면, 그게 바로 전이 학습입니다.

출처: 작성자
전이 학습에서는 사전 학습된 네트워크(이탈리아 요리)를 가져와 중국 요리에 맞게 미세 조정합니다. 이전 과제에서 얻은 지식을 활용해 새로운 과제를 더 잘 학습하도록 돕는 것입니다. 이는 네트워크를 처음부터 학습시키는 것에 비해 시간과 계산 자원을 크게 절약합니다.
이번 구현에는 PyTorch를 사용합니다. 쉽게 말해, 머신러닝 모델을 “요리”하는 데 필요한 도구와 재료가 모두 갖춰진 주방이라고 생각하면 됩니다. PyTorch는 초보자에게 친숙하고 유연하며 커뮤니티 지원이 뛰어나 매우 널리 쓰입니다. 또한 신경망을 구축하고 학습시키는 과정을 수월하게 해 주는 유용한 기능을 다수 제공합니다.
전이 학습의 기초
전이 학습은 하나의 문제를 해결하며 얻은 지식을 서로 관련된 다른 문제에 적용하는 기법입니다.
전이 학습을 구현하려면 사전 학습된 모델이 필수입니다. 이 모델은 대규모 데이터셋에서 학습한 특성 표현을 활용하며, 새로운 과제에 맞게 미세 조정할 수 있습니다. 이 방법은 새로운 과제의 라벨링된 데이터나 계산 자원이 제한적일 때 특히 유용합니다.
처음부터 시작하지 않고 학습된 특성을 적절히 조정해 활용함으로써, 전이 학습은 모델 개발 속도를 높이고 성능을 향상시킵니다. 특히 데이터 특성이나 패턴이 유사한 과제에서는 그 효과가 더욱 큽니다.
전이 학습의 작동 원리
전이 학습이 보통 어떻게 작동하는지 간단히 설명하면 다음과 같습니다:

1. 사전 학습된 모델
이미지 분류처럼 수백만 장의 라벨링된 이미지로 특정 과제를 학습한 사전 학습된 신경망 모델에서 시작합니다.
2. 특성 추출
다음으로, 사전 학습된 모델에서 원래 과제와 관련된 데이터의 고수준 패턴을 나타내는 학습된 특성을 추출합니다. 이러한 특성은 일반적으로 모델의 각 층 파라미터에 담겨 있습니다.
3. 전이
다음으로, 사전 학습된 모델을 새 과제에 맞게 재활용하기 위해 원래 출력층(소스 과제에 특화된 층)을 제거하고, 대상 과제에 맞춘 새 출력층으로 교체합니다. 이 새 출력층의 가중치는 무작위로 초기화합니다.
4. 파인 튜닝
사전 학습된 모델을 새 과제에 맞게 재구성한 뒤에는 대상 과제의 데이터셋으로 해당 모델을 학습합니다. 이 과정에서는 사전 학습된 모델의 파라미터를 파인 튜닝하고, 대상 과제를 위해 추가한 모든 층도 함께 학습합니다.
파인 튜닝은 모델의 파라미터를 전체 층 또는 특정 층에 한해 조정하여, 학습된 특성이 새 과제의 특성에 더 잘 맞도록 적응시키는 과정입니다. 학습하는 동안 모델은 대상 과제의 데이터셋을 입력받고, 예측 결과와 정답 라벨 간의 손실을 최소화하도록 역전파를 통해 파라미터를 업데이트합니다.
5. 평가
모델 학습이 완료되면, 대상 과제에서의 성능을 평가하기 위해 별도의 검증 또는 테스트 데이터셋으로 평가합니다. 이 평가 단계는 모델이 보지 못한 데이터에 얼마나 잘 일반화하는지 확인하고, 해당 과제를 해결하는 데 있어 모델의 효과성에 대한 통찰을 제공합니다.
정확도, 정밀도, 재현율, F1 점수와 같은 성능 지표를 사용해 모델의 성능을 정량화하고, 추가 개선 또는 배포 여부를 결정하는 데 참고합니다.
이러한 단계를 따르면, 전이 학습은 사전 학습된 모델에 담긴 지식을 활용하여 모델 개발을 가속하고 새로운 과제에서의 성능을 향상시킬 수 있게 합니다.
전이 학습의 유형: 유도형, 전이추론형, 비지도형
전이 학습은 소스와 타깃 도메인, 그리고 라벨 유무에 따라 여러 유형으로 구분할 수 있습니다. 다음��� 전이 학습의 대표적인 세 가지 유형입니다:
유도형 전이 학습
에서 유도형 전이 학습은 라벨이 있는 소스 도메인에서 얻은 지식을 유사하지만 다른 과제를 가진 타깃 도메인으로 이전하는 방법입니다.
유도형 전이 학습의 핵심 특징은 소스와 타깃 도메인의 데이터 분포가 서로 다르지만, 전이를 가능하게 하는 공통의 기반 구조나 특징이 존재한다는 점입니다. 목표는 도메인 전반에 일반화 가능한 표현을 학습하여, 데이터 분포가 달라도 모델이 타깃 과제에서 우수한 성능을 내도록 하는 것입니다.
전이추론형 전이 학습
전이추론형 전이 학습은 라벨이 있는 소스 도메인에서 얻은 지식을 라벨이 없는 데이터의 타깃 도메인으로 이전하는 과정을 말합니다.
유도형 전이 학습과 달리, 전이추론형 전이 학습은 소스 도메인과 타깃 도메인 사이의 데이터 분포 차이를 가정하지 않습니다. 대신 소스 도메인의 라벨이 있는 데이터를 활용해 데이터 내에 존재하는 공통 구조나 관계를 이용함으로써 타깃 과제의 성능을 향상시키는 것을 목표로 합니다.
비지도 전이 학습
비지도 전이 학습은 라벨이 있는 소스 도메인에서 라벨이 없는 타깃 도메인으로 지식을 이전하는 데 초점을 둡니다.
이 유형의 전이 학습은 타깃 과제를 위한 라벨링된 데이터가 부족하거나 아예 없을 때 특히 유용합니다. 소스 도메인의 라벨링된 데이터를 활용해 모델이 유용한 특징이나 표현을 학습하도록 함으로써, 라벨이 없는 상태에서도 해당 표현을 타깃 도메인에 적용할 수 있습니다.
전이 학습을 사용할 때
전이 학습은 다음과 같은 여러 상황에서 고려할 수 있는 강력한 머신 러닝 접근법입니다:
라벨링된 데이터가 부족함
타깃 과제가 있지만 모델을 효과적으로 학습시킬 만큼 충분한 라벨링된 데이터가 없을 때, 전이 학습을 사용하면 풍부한 데이터가 있는 관련 과제에서 얻은 지식을 활용할 수 있습니다.
시간과 자원 절약
모델을 처음부터 학습시키는 것은 계산 비용이 많이 들고 시간이 오래 걸릴 수 있습니다. 사전 학습된 모델을 사용해 요구 사항에 맞게 적절히 변경하면 학습 시간과 계산 비용을 모두 크게 줄일 수 있습니다.
성능 향상
타깃 데이터셋이 작을 경우, 처음부터 학습한 모델은 과적합으로 인해 성능이 낮아질 수 있습니다. 전이 학습은 관련 있고 잘 연구된 과제에서 얻은 지식을 도입해 일반화 성능을 향상시킬 수 있습니다.
도메인 간 응용 분야
한 도메인의 통찰을 다른 도메인에 적용하고자 할 때, 예를 들어 이미지 인식 기법을 의료 영상에 적용하는 경우, 전이 학습은 서로 다른 데이터 분포와 특성 공간 사이의 간극을 메워 줄 수 있습니다.
벤치마킹
새로운 문제나 데이터셋을 도입할 때 전이 학습으로 시작하면 성능에 대한 기준선을 마련할 수 있습니다. 이는 과제의 난이도를 파악하고 모델 개선에 대한 현실적인 기대치를 설정하는 데 도움이 됩니다.
PyTorch 이해하기
Meta AI가 개발한 PyTorch는 유연성과 사용 용이성, GPU 가속에 대한 네이티브 지원으로 잘 알려진 머신러닝 프레임워크로, 딥러닝 프로젝트에 매우 적합합니다.
경쟁 프레임워크인 TensorFlow와 비교하면, PyTorch는 정적 그래프 기반의 TensorFlow보다 더 유연하고 직관적이어서 연구에 적합합니다. 또한 TensorFlow가 확장성 측면에서 유리할 수는 있지만, PyTorch는 사용 편의성과 동적 특성 덕분에 실험적 프로젝트와 프로토타이핑에 자주 선호됩니다. PyTorch의 장점은 다음과 같습니다:
- 사용자 친화적: PyTorch는 Python 사용자에게 직관적이며, 딥러닝 모델 개발 과정을 단순화합니다.
- 동적 계산 그래프: 실행 중 그래프를 수정하여 모델 설계의 유연성을 확보할 수 있습니다.
- 강력한 GPU 가속: 더 빠른 연산을 위해 GPU 하드웨어를 효율적으로 활용합니다.
- 풍부한 생태계: 사전 구축된 모델과 학습 도구를 폭넓게 제공합니다.
Weights & Biases 개요
Weights & Biases(W&B)는 실험 추적, 데이터 시각화, 그리고 ML 커뮤니티 내 인사이트 공유를 돕기 위해 설계된 머신러닝 플랫폼입니다. 하이퍼파라미터, 출력, 모델 결과를 로깅하는 도구를 제공하여 다양한 실험과 모델을 모니터링하고 비교하기 쉽게 해줍니다. W&B는 기존 ML 워크플로에 원활히 통합되도록 설계되었으며, PyTorch, TensorFlow, Keras를 포함한 폭넓은 ML 프레임워크를 지원합니다.
PyTorch와 전이 학습 시작하기
1. 라이브러리 가져오기
import pandas as pdimport osimport torchimport torchvisionimport torchvision.transforms as transformsfrom torch.utils.data import DataLoader, random_splitfrom torchvision import modelsfrom torchvision import datasets, transformsimport torch.nn as nnimport torch.optim as optimimport zipfile!pip install wandbimport wandbos.environ['CUDA_LAUNCH_BLOCKING'] = "1"
2. 데이터셋 다운로드 및 압축 해제
Caltech-101 데이터셋은 컴퓨터 비전 연구에서 널리 사용되는 벤치마크 데이터셋입니다. 101개의 객체 범주로 구성되며, 각 범주는 약 40장부터 800장까지의 이미지를 포함합니다.
이 이미지들은 객체의 시점, 포즈, 스케일, 조명 조건, 배경 잡음, 그리고 클래스 내 변이가 크게 다릅니다. 이 데이터셋은 원래 California Institute of Technology(Caltech) 연구진이 구축했습니다. 일반적으로 객체 인식, 분류, 검출 등의 작업에 사용됩니다. 데이터셋은 Kaggle에서 zip 파일 형태로 제공되며, 다운로드한 후 압축을 해제해 사용합니다.
from google.colab import drivedrive.mount('/content/drive')!pip install kaggleos.environ['KAGGLE_CONFIG_DIR'] = '/content/drive/MyDrive/kaggle'!kaggle datasets download -d imbikramsaha/caltech-101file_path = '/content/caltech-101.zip'with zipfile.ZipFile(file_path, 'r') as zip_ref:zip_ref.extractall('/content/kaggle/')
3. 데이터셋 전처리
Caltech-101 데이터에는 300 × 200픽셀 크기의 이미지가 있으므로, VGG 모델의 기본 입력 크기 요구 사항에 맞춰 224 × 224로 리사이즈합니다.
데이터는 정규화한 뒤 테스트(20%)와 학습(80%) 세트로 분할하며, PyTorch에서 제공하는 데이터 로더에 적재합니다. 이렇게 하면 모델 입력을 위한 데이터 로딩을 효율적이고 유연하게 수행할 수 있습니다.
transform = transforms.Compose([transforms.Resize((224, 224)),transforms.ToTensor(),transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),])dataset = datasets.ImageFolder(root='/content/kaggle/caltech-101', transform=transform)total_size = len(dataset)train_size = int(0.8 * total_size)test_size = total_size - train_sizetrain_dataset, test_dataset = random_split(dataset, [train_size, test_size])train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)test_loader = DataLoader(test_dataset, batch_size=32, shuffle=False)
4. Weights & Biases 설정
wandb.init(project="transfer_learn_pytorch", name="caltech101_classification_2")
5. 사전 학습된 VGG 모델 불러오기 및 수정
사전 학습된 VGG 모델을 pretrained=True로 설정해 불러온 뒤, 특징 추출 계층을 고정해 해당 계층이 학습되지 않도록 합니다. 다음으로 분류기 계층을 추가하고, 출력 계층을 Caltech-101의 0~101 클래스에 대응하도록 출력 뉴런 수를 102개로 설정합니다.
vgg = models.vgg16(pretrained=True)for param in vgg.features.parameters():param.requires_grad = Falsenum_features = vgg.classifier[6].in_featuresvgg.classifier[6] = nn.Linear(num_features, 102) # Change the last layerdevice = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")print(device)vgg.to(device)
6. 전이 학습
전이 학습을 구현하기 위해 config 변수를 설정합니다. wandb 하이퍼파라미터와 입력값을 보관하고 저장합니다.
config = wandb.configconfig.learning_rate = 0.001config.momentum = 0.9config.epochs = 5config.batch_size = 32
마지막으로 손실 함수와 옵티마이저를 설정하고, 학습 함수를 정의한 뒤 성능 지표를 로깅합니다. wandb 주어진 하이퍼파라미터에 대해 모델의 성능을 평가하는 데 도움이 됩니다.
criterion = nn.CrossEntropyLoss()optimizer = optim.SGD(vgg.classifier.parameters(), lr=0.001, momentum=0.9)def train_model(model, criterion, optimizer, num_epochs):for epoch in range(num_epochs):model.train()running_loss = 0.0for inputs, labels in train_loader:inputs, labels = inputs.to(device), labels.to(device)optimizer.zero_grad()outputs = model(inputs)loss = criterion(outputs, labels)loss.backward()optimizer.step()running_loss += loss.item()epoch_loss = running_loss / len(train_loader)print(f"Epoch {epoch+1}, Loss: {epoch_loss}")wandb.log({"epoch": epoch + 1, "loss": epoch_loss})train_model(vgg, criterion, optimizer, num_epochs=5)
7. 성능 지표 평가
모델을 평가하기 위해, 추론 시 그래디언트 계산을 비활성화하고 모델을 즉시 평가 모드로 전환한 뒤 손실을 보고하는 함수를 정의합니다.
def evaluate_model(model, criterion, loader):model.eval()total_loss = 0.0total = 0with torch.no_grad():for inputs, labels in loader:inputs, labels = inputs.to(device), labels.to(device)outputs = model(inputs)loss = criterion(outputs, labels)total_loss += loss.item() * inputs.size(0)total += inputs.size(0)average_loss = total_loss / totalreturn average_loss
a. 사전 학습된 모델
아래 코드는 사전 학습된 모델을 불러온 뒤 evaluate_model 함수를 호출하여 모델을 평가합니다.
pretrained_vgg = models.vgg16(pretrained=True).to(device)pretrained_test_loss = evaluate_model(pretrained_vgg, criterion, test_loader)wandb.log({"pretrained_test_loss": pretrained_test_loss})
b. 미세 조정된 모델
아래 코드는 evaluate_model 함수를 호출하여 미세 조정된 모델을 평가합니다.
test_loss = evaluate_model(vgg, criterion, test_loader)wandb.log({"fine_tuned_test_loss": test_loss})
c. 결과
아래 그래프는 Weights & Biases에 기록된 결과를 보여줍니다. 첫 번째 그래프에서는 에포크 수가 증가함에 따라 학습 손실이 감소하는 모습을 확인할 수 있으며, 이를 통해 더 많은 에포크로 미세 조정하면 정확도를 높일 수 있음을 평가할 수 있습니다. 다음 두 그래프는 미세 조정된 모델과 사전 학습된 모델의 손실을 각각 보여줍니다. 이를 통해 미세 조정된 모델이 사전 학습된 모델(손실 16.07)보다 더 우수한 성능을 보여 손실 0.277을 기록함을 확인할 수 있습니다.

출처: 작성자
8. 예측 결과 이미지 평가
또한 실제 클래스와 예측 클래스를 비교하여 시각화함으로써 모델의 성능을 평가합니다. 이를 통해 각 클래스별로 모델의 학습이 어떻게 분포되어 있는지 더 잘 파악할 수 있습니다. 간단히 하기 위해 이미지 한 배치(32장)를 기록합니다.
def log_predictions(model, loader, prefix=""):model.eval()with torch.no_grad():for inputs, labels in loader:inputs, labels = inputs.to(device), labels.to(device)outputs = model(inputs)_, preds = torch.max(outputs, 1)wandb.log({f"{prefix}examples": [wandb.Image(x.cpu(), caption=f"Pred:{pred.item()}, Label:{y.item()}")for x, pred, y in zip(inputs, preds, labels)]})break
a. 사전 학습된 모델
사전 학습된 모델의 예측을 기록합니다.
log_predictions(pretrained_vgg, test_loader, prefix="pretrained_")
b. 미세 조정된 모델
미세 조정된 모델의 예측을 기록합니다.
log_predictions(vgg, test_loader, prefix="fine_tuned_")
c. 결과
아래 이미지는 Caltech 데이터셋에 대해 사전 학습된 모델과 미세 조정된 모델의 분류 결과를 보여줍니다. ‘pred’는 모델이 예측한 클래스를, ‘label’은 실제 클래스를 나타냅니다. ‘pred’와 ‘label’이 일치하면 모델이 클래스를 올바르게 식별한 것입니다.
사전 학습된 모델 예시

출처: 작성자
미세 조정된 모델 예시

출처: 작성자
보여준 바와 같이, 미세 조정된 모델은 사전 학습된 모델이 대체로 오분류한 많은 클래스를 정확하게 분류합니다.
결론
PyTorch를 활용한 전이 학습은 머신러닝과 딥러닝 분야에서 판도를 바꿔 놓았습니다. 사전 학습된 모델을 활용해 새로운 과제에 맞게 적응시키면, 개발자와 연구자는 소중한 시간과 자원을 절약하고, 데이터 부족 문제를 완화하며, 다양한 도메인에서 최첨단 성능을 달성할 수 있습니다.
이번 전이 학습 탐구에서는 PyTorch로 ImageNet에서 사전 학습된 VGG 모델을 Caltech-101 데이터셋에 맞춰 미세 조정했습니다. Weights & Biases에 기록된 결과를 통해, 과제에 특화된 문제를 다룰 때 미세 조정이 사전 학습된 모델보다 우수하다는 결론에 효율적으로 도달할 수 있었습니다. 다만, 사전 학습된 모델의 특성 표현을 활용하면 소중한 시간과 자원을 절약할 수 있습니다.
Add a comment