Bài 5: Transfer learning | Deep Learning cơ bản
 

Bài 5: Transfer learning

| Posted in Pytorch

Bài này mình sẽ hướng dẫn sử dụng transfer learning trong Pytorch. Trước khi bắt đầu mọi người nên xem lại các kiến thức về transfer learning ở đây. Phần đầu mình sẽ hướng dẫn sử dụng pre-trained model để dự đoán, phần sau mình sẽ hướng dẫn fine-tune model.

Sử dụng pre-trained model để dự đoán

Các bước dùng pretrained model để dự đoán các giá trị mới bao gồm:

  • Load ảnh cần dự đoán
  • Thực hiện các phép transformation trên ảnh
  • Cho ảnh qua model để dự đoán

Load pretrained model

Thư viện torchvision hỗ trợ rất nhiều model

from torchvision import models
dir(models)
# output:
['AlexNet',
 'DenseNet',
 'GoogLeNet',
 'GoogLeNetOutputs',
 'Inception3',
 'InceptionOutputs',
 'MNASNet',
 'MobileNetV2',
 'MobileNetV3',
 'ResNet',
 'ShuffleNetV2',
 'SqueezeNet',
 'VGG',
 'alexnet',
 'densenet',
 'densenet121',
 'densenet161',
 'densenet169',
 'densenet201',
 'resnet',
 'resnet101',
 'resnet152',
 'resnet18',
 'resnet34',
 'resnet50',
 'detection',
 'googlenet',
 'inception',
 'inception_v3',
 ]

Mọi người thấy hầu hết các model phổ biến như resnet, densenet đều được được implement sẵn trong torchvision. Ở phần này mình sẽ dùng pretrained resnet model để dự đoán.

Từ torchvision.models mình có thể load các model, ví dụ mình dùng resnet50. Ở trong có tham số pretrained = True, ý là mình dùng pretrained model resnet50 với weight được train với bộ dữ liệu ImageNet. Còn nếu pretrained = False, thì mình sẽ dùng resnet50 model với weight được khởi tạo ngẫu nhiên.

resnet = models.resnet50(pretrained=True)

Để xem các layer trong resnet model mình có thể in ra

print(resnet)

Image Transformation

Khi đã load xong model, mình cần transform ảnh input cho giống với các thuộc tính của ảnh trong bộ ImageNet mà trước mình dùng để train model resnet50 như:

  • Ảnh chuyển về kích thước 224 * 224
  • Normalize ảnh theo mean và standard deviation của bộ dữ liệu ImageNet.
  • Chuyển về Torch tensor để cho vào model
from torchvision import transforms
transform = transforms.Compose([  
 transforms.Resize(256),
 transforms.CenterCrop(224),
 transforms.ToTensor(),
 transforms.Normalize(
 mean=[0.485, 0.456, 0.406],
 std=[0.229, 0.224, 0.225]
 )])

Sau đó mình sẽ load ảnh và thực hiện transform ảnh.

from PIL import Image
img = Image.open("cat.jpg")
cat

Tiếp theo mình sẽ thực hiện transform ảnh

img_t = transform(img)
batch_t = torch.unsqueeze(img_t, 0)

Prediction

Tiếp đó mình sẽ cho ảnh qua model để được kết quả dự đoán

resnet.eval()
out = resnet(batch_t)
out.argmax() # 281

Nếu mọi người xem label của ImageNet ở đây, thì 281 tương ứng với tabby, con mèo.

Code phần này mọi người xem ở đây.

Finetuning model

Phần này mình sẽ hướng dẫn fine tune pretrained model resnet50 cho dữ liệu cifar100.

Dataset

Dữ liệu CIFAR-100 bao gồm 60000 hình ảnh màu (50000 ảnh tập train và 10000 ảnh tập test) có kích thước 32 × 32 pixel. Dữ liệu được chia thành 100 lớp.

Deep Learning Lab] Episode-5: CIFAR-100 | by Furkan Kınlı | Medium
Ảnh cifar100

Data Augmentation

Vì mình dùng resnet pretrained model với bộ dữ liệu ImageNet, nên mình sẽ transform ảnh về kích thước 224 * 224 cho giống với ảnh trong dữ liệu ImageNet.

train_transform = transforms.Compose([
        transforms.RandomResizedCrop(size=256),
        transforms.RandomRotation(degrees=15),
        transforms.RandomHorizontalFlip(),
        transforms.CenterCrop(size=224),
        transforms.ToTensor(),
        transforms.Normalize([0.485, 0.456, 0.406],
                             [0.229, 0.224, 0.225])
    ])

Tiếp đó mình dùng một số kĩ thuật để augumentation ảnh để tránh overfitting như xoay ảnh, lật ảnh ngẫu nhiên. Và cuối cùng mình normalize ảnh về standard normal distribution theo mean và standard deviation của bộ dữ liệu ImageNet.

Transfer Learning

Đầu tiên mình cần load pretrained model resnet50

resnet50 = models.resnet50(pretrained=True)

Mình sẽ freeze các parameter trong model resnet50, freeze ở đây ý là không update hệ số W và b trong quá trình thực hiện gradient descent.

# Freeze model parameters
for param in resnet50.parameters():
    param.requires_grad = False

Tiếp đó mình sẽ thêm các lớp mới của mình vào sau resnet50

fc_inputs = resnet50.fc.in_features

resnet50.fc = nn.Sequential(
    nn.Linear(fc_inputs, 256),
    nn.ReLU(),
    nn.Dropout(0.4),
    nn.Linear(256, 100), # Since 100 possible outputs
    nn.LogSoftmax(dim=1) # For using NLLLoss()
)

Mình sẽ cho output của resnet50 model lần lượt qua lớp Dense (256), rồi Dense (100), vì bài này mình làm bài toán phân loại 100 lớp. Sau đó dùng softmax activation ở output layer. Ở giữa 2 lớp Dense mình để 1 lớp Dropout để giảm overfitting của mô hình.

Learning rate schedule

Khi train model, xu hướng là càng về các epoch sau thì giảm learning rate sẽ dễ hội tụ hơn. Trong bài này mình có dùng MultiStepLR để giảm learning rate theo epoch.

optimizer = optim.Adam(resnet50.parameters(), lr=0.005)
scheduler = optim.lr_scheduler.MultiStepLR(optimizer, milestones=[10,20], gamma=0.1)

Như ở trên thì mình dùng optimizer Adam với learning rate ban đầu là 0.005. Sau đó mình dùng scheduler với 2 milestons là 10, 20 thì cứ đến milestons, learning_rate = gamma * learning_rate

  • Từ epoch 1->9: learning rate là 0.005
  • Từ epoch 10->19: learning rate là 0.0005
  • Từ epoch 20 trở đi: learning rate là 0.00005

Cuối cùng mình đạt 60% accuracy trên tập validation trên tập cifar100. Model vẫn có xu hướng train tốt, nhưng do mỗi epoch mất tầm 5 phút nên mình để việc train tiếp cho bạn đọc.

Code phần này mọi người xem ở đây.


Deep Learning cơ bản ©2024. All Rights Reserved.
Powered by WordPress. Theme by Phoenix Web Solutions