บทช่วยสอนการถ่ายโอน PyTorch พร้อมตัวอย่าง
Transfer Learning คืออะไร?
ถ่ายทอดการเรียนรู้ เป็นเทคนิคการใช้แบบจำลองที่ผ่านการฝึกอบรมเพื่อแก้ไขงานอื่นที่เกี่ยวข้อง เป็นวิธีการวิจัย Machine Learning ที่เก็บความรู้ที่ได้รับขณะแก้ไขปัญหาเฉพาะ และใช้ความรู้เดียวกันเพื่อแก้ปัญหาอื่นที่แตกต่างกันแต่เกี่ยวข้องกัน สิ่งนี้ช่วยปรับปรุงประสิทธิภาพโดยการนำข้อมูลที่รวบรวมจากงานที่เรียนรู้ก่อนหน้านี้กลับมาใช้ใหม่
นิยมใช้น้ำหนักโมเดลเครือข่ายอื่นๆ เพื่อลดเวลาการฝึก เนื่องจากคุณต้องการข้อมูลจำนวนมากเพื่อฝึกโมเดลเครือข่าย เพื่อลดเวลาการฝึกอบรม คุณใช้เครือข่ายอื่นและน้ำหนักของมัน และแก้ไขเลเยอร์สุดท้ายเพื่อแก้ไขปัญหาของเรา ข้อดีคือคุณสามารถใช้ชุดข้อมูลขนาดเล็กเพื่อฝึกเลเยอร์สุดท้ายได้
ต่อไปในบทช่วยสอนการเรียนรู้ PyTorch Transfer นี้ เราจะได้เรียนรู้วิธีใช้ Transfer Learning กับ PyTorch
กำลังโหลดชุดข้อมูล
ที่มา: Alien vs. Predator Kaggle
ก่อนที่คุณจะเริ่มใช้ Transfer Learning PyTorch คุณต้องเข้าใจชุดข้อมูลที่คุณจะใช้ ในตัวอย่าง Transfer Learning PyTorch นี้ คุณจะจำแนกเอเลี่ยนและนักล่าจากรูปภาพเกือบ 700 รูป สำหรับเทคนิคนี้ คุณไม่จำเป็นต้องมีข้อมูลจำนวนมากในการฝึก คุณสามารถดาวน์โหลดชุดข้อมูลได้จาก Kaggle: เอเลี่ยนกับพรีเดเตอร์
วิธีใช้การถ่ายโอนการเรียนรู้
ต่อไปนี้เป็นกระบวนการทีละขั้นตอนเกี่ยวกับวิธีใช้ Transfer Learning เพื่อการเรียนรู้เชิงลึกด้วย PyTorch:
ขั้นตอนที่ 1) โหลดข้อมูล
ขั้นตอนแรกคือการโหลดข้อมูลของเราและทำการเปลี่ยนแปลงรูปภาพเพื่อให้ตรงกับข้อกำหนดของเครือข่าย
คุณจะโหลดข้อมูลจากโฟลเดอร์ที่มี torchvision.dataset โมดูลจะวนซ้ำในโฟลเดอร์เพื่อแยกข้อมูลสำหรับการฝึกและการตรวจสอบ กระบวนการแปลงจะครอบตัดรูปภาพจากกึ่งกลาง พลิกแนวนอน ทำให้เป็นมาตรฐาน และสุดท้ายแปลงเป็นเทนเซอร์โดยใช้การเรียนรู้เชิงลึก
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")
มาดูชุดข้อมูลของเราสำหรับ PyTorch Transfer Learning กัน กระบวนการสร้างภาพจะได้รับรูปภาพชุดถัดไปจากตัวโหลดข้อมูลและป้ายกำกับและแสดงด้วย Matplot
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()
ขั้นตอนที่ 2) กำหนดโมเดล
ในการนี้ การเรียนรู้ลึก ๆ กระบวนการคุณจะใช้ ResNet18 จากโมดูล torchvision
คุณจะใช้ torchvision.models เพื่อโหลด resnet18 โดยตั้งค่าน้ำหนักที่ฝึกไว้ล่วงหน้าให้เป็น True หลังจากนั้น คุณจะตรึงเลเยอร์เหล่านี้เพื่อไม่ให้สามารถฝึกได้ นอกจากนี้ คุณยังแก้ไขเลเยอร์สุดท้ายด้วยเลเยอร์เชิงเส้นเพื่อให้เหมาะกับความต้องการของเรา ซึ่งก็คือ 2 คลาส นอกจากนี้ คุณยังใช้ CrossEntropyLoss สำหรับฟังก์ชันการสูญเสียหลายคลาส และสำหรับตัวเพิ่มประสิทธิภาพ คุณจะใช้ SGD ด้วยอัตราการเรียนรู้ 0.0001 และโมเมนตัม 0.9 ดังที่แสดงในตัวอย่าง PyTorch Transfer Learning ด้านล่าง
## 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)
โครงสร้างโมเดลเอาท์พุต
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) ฝึกและทดสอบโมเดล
เราจะใช้ฟังก์ชันบางอย่างจาก Transfer Learning การสอน 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)
สุดท้ายนี้ในตัวอย่าง Transfer Learning ใน PyTorch เราจะมาเริ่มกระบวนการฝึกอบรมโดยกำหนดจำนวนยุคไว้ที่ 25 และประเมินหลังกระบวนการฝึกอบรม ในแต่ละขั้นตอนการฝึก แบบจำลองจะรับข้อมูลเข้าและคาดการณ์ผลลัพธ์ หลังจากนั้นผลลัพธ์ที่คาดการณ์ไว้จะถูกส่งไปยังเกณฑ์เพื่อคำนวณการสูญเสีย จากนั้นส่วนที่สูญเสียจะทำการคำนวณ backprop เพื่อคำนวณการไล่ระดับสี และสุดท้ายคือคำนวณน้ำหนักและปรับพารามิเตอร์ให้เหมาะสมด้วยระบบออโต้กราด
ที่โมเดลการแสดงภาพ เครือข่ายที่ได้รับการฝึกอบรมจะได้รับการทดสอบด้วยชุดรูปภาพเพื่อทำนายป้ายกำกับ จากนั้นมันจะเห็นภาพด้วยความช่วยเหลือของ 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
สิ้นสุด จากนั้นผลลัพธ์ของแบบจำลองของเราจะถูกมองเห็นด้วย matplot ด้านล่าง:
สรุป
มาสรุปกันก่อนดีกว่า ปัจจัยแรกก็คือ PyTorch เป็นเฟรมเวิร์กการเรียนรู้เชิงลึกที่กำลังเติบโตสำหรับผู้เริ่มต้นหรือเพื่อวัตถุประสงค์ในการวิจัย มันมีเวลาการคำนวณสูง กราฟแบบไดนามิก รองรับ GPU และเขียนขึ้นทั้งหมดด้วย Python- คุณสามารถกำหนดโมดูลเครือข่ายของคุณเองได้อย่างง่ายดาย และดำเนินกระบวนการฝึกอบรมด้วยการวนซ้ำที่ง่ายดาย เห็นได้ชัดว่า PyTorch เหมาะสำหรับผู้เริ่มต้นในการค้นหาการเรียนรู้เชิงลึก และสำหรับนักวิจัยมืออาชีพ มันมีประโยชน์มากด้วยเวลาในการคำนวณที่เร็วขึ้น และยังมีฟังก์ชัน Autograd ที่มีประโยชน์มากในการช่วยกราฟแบบไดนามิก