PyTor전이 학습 튜토리얼 (예제 포함)
⚡ 스마트 요약
전이 학습은 이미 대규모 데이터셋으로 학습된 네트워크를 재사용하여, 훨씬 적은 수의 레이블링된 이미지와 훨씬 짧은 학습 시간으로 새로운 관련 작업을 해결할 수 있도록 합니다.
전이 학습이란 무엇입니까?
전학 학습 훈련된 모델을 사용하여 다른 관련 작업을 해결하는 기술입니다. 머신 러닝 특정 문제를 해결하는 과정에서 얻은 지식을 저장하고, 동일한 지식을 활용하여 서로 다르지만 관련된 문제를 해결하는 연구 방법입니다. 이는 이전에 학습한 과제에서 얻은 정보를 재사용함으로써 효율성을 향상시킵니다.
신경망을 처음부터 학습시키려면 엄청난 양의 데이터가 필요하기 때문에, 기존 신경망 모델의 가중치를 재사용하는 것이 일반적입니다. 학습 시간을 줄이기 위해 기존 신경망과 그 가중치를 가져와 마지막 레이어를 수정하여 원하는 문제를 해결하도록 합니다. 이렇게 하면 마지막 레이어를 적은 데이터셋으로도 학습시킬 수 있다는 장점이 있습니다.
Py를 작성하기 전에Tor코드 유형이 다르기 때문에, 전이 학습의 어떤 유형에 속하는지 아는 것이 중요합니다. 왜냐하면 유형에 따라 필요한 레이블링된 데이터의 양이 결정되기 때문입니다.
전이 학습의 유형
연구 문헌에서는 이 기법을 세 가지 유형으로 분류합니다. 어떤 유형이 적용되는지는 사용하는 프레임워크가 아니라 문제의 어느 측면에 명칭이 붙어 있는지에 따라 결정됩니다.
| 타입 | 소스 도메인 | Target 도메인 | 일반적인 사용 |
|---|---|---|---|
| 유도 | 라벨이 붙은 | 라벨은 붙어 있지만, 다른 작업입니다. | ImageNet 백본을 에일리언 대 프레데터라는 두 클래스 문제에 맞게 재조정하기 |
| 변환 | 라벨이 붙은 | 레이블 없음, 동일한 작업, 데이터 분포가 다름 | 스튜디오 사진에서 휴대폰 사진으로 모델을 옮기는 것과 같은 도메인 적응. |
| 감독되지 않음 | 라벨 없음 | 라벨 없음 | Cluster모든 레코드에 레이블을 지정하는 것이 비현실적인 경우 차원 축소 또는 차원 축소 |
이 튜토리얼에서 다루는 예제는 귀납적 전이 학습입니다. VGG19는 레이블이 지정된 ImageNet 지식을 가지고 있으며, 이제 이전에 접해본 적 없는 레이블이 지정된 이진 클래스 문제에 대한 학습을 수행하게 됩니다.
기능 예시trac조정 vs 미세 조정
사전 학습된 네트워크를 선택한 후에는 두 가지 방법으로 네트워크를 조정할 수 있습니다. 두 방법의 차이점은 학습을 계속할 레이어 수를 얼마나 허용하느냐에 있습니다.
| 아래 | 기능 예시trac기 | 미세 조정 |
|---|---|---|
| 훈련하는 레이어 | 교체된 분류기만 | 분류기와 일부 또는 전체 컨볼루션 블록 |
| 백본에서 requires_grad를 사용합니다. | 거짓 | 업데이트되는 블록에 대해서는 사실입니다. |
| 필요한 데이터 | 클래스당 이미지 수가 적고, 대개 수백 개 정도입니다. | 더 큰 규모, 보통 수천 개 |
| 교육 비용 | 최저 사양은 CPU에서 실행됩니다. | 그보다 높은 해상도에서는 GPU를 사용하는 것이 가치가 있습니다. |
| 일반적인 정확도 | 원본 이미지와 대상 이미지가 비슷하게 생겼을 때 좋습니다. | 두 영역이 서로 다를 때 일반적으로 더 좋습니다. |
아래 단계에서는 기능 예시를 사용합니다.trac설정: 모든 VGG19 파라미터가 고정되고 새로운 최종 선형 레이어만 학습됩니다. 미세 조정으로 전환하려면 약간의 변경만 하면 됩니다. 즉, 업데이트하려는 블록에서 requires_grad를 True로 설정하고 학습률을 낮춰 빌려온 가중치가 파괴되지 않도록 하면 됩니다.
데이터 세트 로드 중
Py를 이용한 전이 학습을 시작하기 전에Tor먼저, 사용할 데이터셋을 이해해야 합니다. 이 전이 학습 Py에서는Tor예를 들어, 약 700장의 이미지 중에서 에일리언과 프레데터를 분류하게 됩니다. 이 기법에는 학습에 많은 양의 데이터가 필요하지 않습니다. 데이터셋은 다음에서 다운로드할 수 있습니다. Kaggle: 에일리언 vs. 프레데터.
이 컬렉션은 의도적으로 소규모로 구성되었으며, 포함된 사진의 일부는 아래에 나와 있습니다.
출처: 외국인 대 프레데터 카글
다음은 이 Py에서Tor이 전이 학습 튜토리얼에서는 Py를 사용하여 전이 학습을 적용하는 방법을 배우게 됩니다.Tor단계별로.
전이 학습을 사용하는 방법은 무엇입니까?
다음은 Py를 사용하여 딥러닝에 전이 학습을 적용하는 방법에 대한 단계별 설명입니다.Tor채널 :
1단계) 데이터 로드
첫 번째 단계는 데이터를 불러오고 네트워크 요구 사항에 맞도록 이미지에 몇 가지 변환을 적용하는 것입니다.
torchvision.datasets 폴더에서 데이터를 불러옵니다. 이 모듈은 폴더를 순회하며 데이터를 학습 세트와 검증 세트로 분할합니다. 여기에 사용된 변환 파이프라인은 이미지의 중앙 부분을 잘라내고, 텐서로 변환한 후 정규화합니다. 딥러닝.
from __future__ import print_function, division import os import time import torch import torchvision from torchvision import datasets, models, transforms import torch.optim as optim import numpy as np import matplotlib.pyplot as plt data_dir = "alien_pred" input_shape = 224 mean = [0.5, 0.5, 0.5] std = [0.5, 0.5, 0.5] #data transformation data_transforms = { 'train': transforms.Compose([ transforms.CenterCrop(input_shape), transforms.ToTensor(), transforms.Normalize(mean, std) ]), 'validation': transforms.Compose([ transforms.CenterCrop(input_shape), transforms.ToTensor(), transforms.Normalize(mean, std) ]), } image_datasets = { x: datasets.ImageFolder( os.path.join(data_dir, x), transform=data_transforms[x] ) for x in ['train', 'validation'] } dataloaders = { x: torch.utils.data.DataLoader( image_datasets[x], batch_size=32, shuffle=True, num_workers=4 ) for x in ['train', 'validation'] } dataset_sizes = {x: len(image_datasets[x]) for x in ['train', 'validation']} print(dataset_sizes) class_names = image_datasets['train'].classes device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu")
이제 데이터셋을 시각화해 보겠습니다. 시각화 단계에서는 학습 데이터 로더에서 다음 이미지 배치와 레이블을 가져와 Matplotlib을 사용하여 표시합니다.
images, labels = next(iter(dataloaders['train'])) rows = 4 columns = 4 fig=plt.figure() for i in range(16): fig.add_subplot(rows, columns, i+1) plt.title(class_names[labels[i]]) img = images[i].numpy().transpose((1, 2, 0)) img = std * img + mean plt.imshow(img) plt.show()
해당 코드 조각을 실행하면 로더가 반환한 클래스 이름으로 제목이 지정된 4x4 격자 형태의 학습 이미지가 그려집니다.
2단계) 모델 정의
이 딥러닝 과정에서는 torchvision 모듈의 VGG19를 사용합니다.
torchvision.models를 사용하여 사전 학습된 가중치가 활성화된 vgg19 모델을 로드합니다. 그 후, 레이어를 학습 불가능하도록 고정합니다. 마지막으로, 문제(여기서는 2개 클래스)에 맞는 선형 레이어를 마지막 레이어에 추가합니다. 손실 함수로는 CrossEntropyLoss를 사용하고, 옵티마이저는 SGD를 사용하며, 학습률은 0.001, 모멘텀은 0.9로 설정합니다. 아래 파이썬 코드를 참조하십시오.Tor전이 학습의 예시.
## Load the model based on VGG19 vgg_based = torchvision.models.vgg19(pretrained=True) ## freeze the layers for param in vgg_based.parameters(): param.requires_grad = False # Modify the last layer number_features = vgg_based.classifier[6].in_features features = list(vgg_based.classifier.children())[:-1] # Remove last layer features.extend([torch.nn.Linear(number_features, len(class_names))]) vgg_based.classifier = torch.nn.Sequential(*features) vgg_based = vgg_based.to(device) print(vgg_based) criterion = torch.nn.CrossEntropyLoss() optimizer_ft = optim.SGD(vgg_based.parameters(), lr=0.001, momentum=0.9)
버전 참고: 전에, 사전 학습됨=True 해당 논리는 여전히 유효하지만, TorchVision 0.13 버전 이후로는 다른 논리로 대체되었습니다. 무게 인수이므로 최신 설치에서는 다음과 같이 예상합니다. torchvision.models.vgg19(weights=VGG19_Weights.DEFAULT) 그렇지 않으면 사용 중단 경고를 출력합니다. 두 형식 모두 동일한 ImageNet 가중치를 로드합니다.
출력 모델 구조
모델을 출력하면 전체 VGG19 그래프가 반환됩니다. 분류기 블록의 마지막 줄을 읽어 스왑이 제대로 되었는지 확인하세요. 이제 1,000개의 ImageNet 클래스 대신 2개의 출력이 생성됩니다.
VGG( (features): Sequential( (0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (1): ReLU(inplace) (2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (3): ReLU(inplace) (4): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (5): Conv2d(64, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (6): ReLU(inplace) (7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (8): ReLU(inplace) (9): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (10): Conv2d(128, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (11): ReLU(inplace) (12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (13): ReLU(inplace) (14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (15): ReLU(inplace) (16): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (17): ReLU(inplace) (18): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (19): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (20): ReLU(inplace) (21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (22): ReLU(inplace) (23): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (24): ReLU(inplace) (25): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (26): ReLU(inplace) (27): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) (28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (29): ReLU(inplace) (30): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (31): ReLU(inplace) (32): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (33): ReLU(inplace) (34): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1)) (35): ReLU(inplace) (36): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False) ) (classifier): Sequential( (0): Linear(in_features=25088, out_features=4096, bias=True) (1): ReLU(inplace) (2): Dropout(p=0.5) (3): Linear(in_features=4096, out_features=4096, bias=True) (4): ReLU(inplace) (5): Dropout(p=0.5) (6): Linear(in_features=4096, out_features=2, bias=True) ) )
3단계) 모델 훈련 및 테스트
우리는 이것의 몇 가지 기능을 사용할 것입니다. PyTorch 튜토리얼 모델을 훈련하고 평가하는 데 도움이 됩니다.
def train_model(model, criterion, optimizer, num_epochs=25): since = time.time() for epoch in range(num_epochs): print('Epoch {}/{}'.format(epoch, num_epochs - 1)) print('-' * 10) #set model to trainable # model.train() train_loss = 0 # Iterate over data. for i, data in enumerate(dataloaders['train']): inputs , labels = data inputs = inputs.to(device) labels = labels.to(device) optimizer.zero_grad() with torch.set_grad_enabled(True): outputs = model(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() train_loss += loss.item() * inputs.size(0) print('{} Loss: {:.4f}'.format( 'train', train_loss / dataset_sizes['train'])) time_elapsed = time.time() - since print('Training complete in {:.0f}m {:.0f}s'.format( time_elapsed // 60, time_elapsed % 60)) return model def visualize_model(model, num_images=6): was_training = model.training model.eval() images_so_far = 0 fig = plt.figure() with torch.no_grad(): for i, (inputs, labels) in enumerate(dataloaders['validation']): inputs = inputs.to(device) labels = labels.to(device) outputs = model(inputs) _, preds = torch.max(outputs, 1) for j in range(inputs.size()[0]): images_so_far += 1 ax = plt.subplot(num_images//2, 2, images_so_far) ax.axis('off') ax.set_title('predicted: {} truth: {}'.format(class_names[preds[j]], class_names[labels[j]])) img = inputs.cpu().data[j].numpy().transpose((1, 2, 0)) img = std * img + mean ax.imshow(img) if images_so_far == num_images: model.train(mode=was_training) return model.train(mode=was_training)
마지막으로, Py를 이용한 전이 학습에 대해 알아보겠습니다.Tor예를 들어, 에포크 수를 25로 설정하여 학습 과정을 시작하고 이후 네트워크를 평가합니다. 각 학습 단계에서 모델은 입력을 받아 출력을 예측합니다. 예측값은 손실을 계산하는 기준 함수로 전달되고, 역전파는 기울기를 계산하며, 최적화기는 자동 미분(autograd)을 통해 가중치를 업데이트합니다.
시각화 기능에서는 학습된 네트워크를 이미지 배치로 테스트하여 레이블을 예측하고, 그 결과를 Matplotlib을 사용하여 시각화합니다.
vgg_based = train_model(vgg_based, criterion, optimizer_ft, num_epochs=25) visualize_model(vgg_based) plt.show()
4단계) 결과
이번 실행의 정확도는 92%입니다. 학습이 끝날 때 출력되는 로그에는 마지막 두 에포크 동안의 손실과 총 학습 시간이 표시됩니다.
Epoch 23/24 ---------- train Loss: 0.0044 train Loss: 0.0078 train Loss: 0.0141 train Loss: 0.0221 train Loss: 0.0306 train Loss: 0.0336 train Loss: 0.0442 train Loss: 0.0482 train Loss: 0.0557 train Loss: 0.0643 train Loss: 0.0763 train Loss: 0.0779 train Loss: 0.0843 train Loss: 0.0910 train Loss: 0.0990 train Loss: 0.1063 train Loss: 0.1133 train Loss: 0.1220 train Loss: 0.1344 train Loss: 0.1382 train Loss: 0.1429 train Loss: 0.1500 Epoch 24/24 ---------- train Loss: 0.0076 train Loss: 0.0115 train Loss: 0.0185 train Loss: 0.0277 train Loss: 0.0345 train Loss: 0.0420 train Loss: 0.0450 train Loss: 0.0490 train Loss: 0.0644 train Loss: 0.0755 train Loss: 0.0813 train Loss: 0.0868 train Loss: 0.0916 train Loss: 0.0980 train Loss: 0.1008 train Loss: 0.1101 train Loss: 0.1176 train Loss: 0.1282 train Loss: 0.1323 train Loss: 0.1397 train Loss: 0.1436 train Loss: 0.1467 Training complete in 2m 47s
모델의 예측 결과는 아래와 같이 Matplotlib을 사용하여 시각화됩니다.
전이 학습에서 흔히 발생하는 오류와 해결 방법
전이 학습 스크립트에서 발생하는 대부분의 오류는 수학적 오류보다는 기계적 오류입니다. 다음은 위 코드가 실행되지 못하게 하는 오류들과 각각의 의미입니다.
- 마지막 레이어의 크기 불일치: 교체된 선형 레이어는 원래 분류기가 보고한 in_features를 받아들이고 정확히 len(class_names)개의 출력을 내보내야 합니다. 2단계에서처럼 모델을 출력하는 것이 두 수치를 확인하는 가장 빠른 방법입니다.
- 핵심 부품은 절대 얼지 않았습니다. requires_grad가 True로 설정된 상태로 두면 모든 VGG19 매개변수가 업데이트되어 CPU에서 실행 속도가 매우 느려집니다. 분류기를 교체하기 전에 requires_grad를 False로 설정하십시오.
- 정규화 불일치: transforms.Normalize에 사용되는 평균과 표준 편차는 학습 시와 추론 시에 동일한 값이어야 합니다. 그렇지 않으면 예측값이 뚜렷한 이유 없이 변동될 수 있습니다.
- 더 이상 사용되지 않는 가중치 인수: TorchVision 0.13 이상 버전에서는 pretrained=True를 사용하면 사용 중단 경고가 표시되며, weights 열거형을 사용하는 것이 좋습니다.
- num_workers에 Windows 그리고 노트북: num_workers=4로 설정된 DataLoader는 진입점을 보호해야 하므로, 필요한 경우 num_workers=0으로 설정하십시오. Python 생성 또는 피클링 오류가 발생합니다.
- 훈련 모드에서 평가 중: Dropout과 BatchNorm이 결정론적으로 동작하도록 스코어링 전에 model.eval()을 호출하고, 그 후에 model.train()을 호출하여 원래대로 되돌리세요.



