6--微调

本文介绍了如何利用迁移学习中的微调技术,通过ResNet18模型在小规模热狗数据集上提升模型性能。通过预训练的ResNet18进行调整,实验结果显示微调后的模型在测试集上达到0.935的精度,优于未微调的模型。
摘要由CSDN通过智能技术生成

        迁移学习(transfer learning)将从源数据集学到的知识迁移到目标数据集。尽管两个数据集内容不尽相同,但在源数据集上训练的模型可能会提取更通用的图像特征,这有助于识别边缘、纹理、形状和对象组合。

        当目标数据集比源数据集小得多时,迁移学习中的微调有助于提高模型的泛化能力。主要包括以下步骤:

  1. 在源数据集(例如ImageNet数据集)上预训练神经网络模型,即源模型

  2. 创建一个新的神经网络模型,即目标模型。这将复制源模型上的所有模型设计及其参数(输出层除外)。假定这些模型参数包含从源数据集中学到的知识,这些知识也将适用于目标数据集。假设源模型的输出层与源数据集的标签密切相关,因此不在目标模型中使用该层。

  3. 向目标模型添加输出层,其输出数是目标数据集中的类别数。然后随机初始化该层的模型参数。

  4. 在目标数据集(如椅子数据集)上训练目标模型。输出层将从头开始进行训练,而所有其他层的参数将根据源模型的参数进行微调。

使用ResNet18在一个小数据集上进行微调,这个小型数据集包含数千张包含热狗和不包含热狗的图像,将使用微调模型来识别图像中是否包含热狗。

!pip install git+https://github.com/d2l-ai/d2l-zh@release  # installing d2l
!pip install matplotlib_inline
!pip install matplotlib==3.0.0

%matplotlib inline
import os
import torch
import torchvision
from torch import nn
from d2l import torch as d2l

d2l.DATA_HUB['hotdog']=(d2l.DATA_URL + 'hotdog.zip','fba480ffa8aa7e0febbb511d181409f899b9baa5')

data_dir = d2l.download_extract('hotdog')

train_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir,'train'))
train_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir,'test'))
hotdogs = [train_imgs[i][0] for i in range(8)]
not_hotdogs = [train_imgs[-i - 1][0] for i in range(8)]
d2l.show_images(hotdogs + not_hotdogs, 2, 8, scale=1.4)

#直接使用在ImageNet上的数据
normalize = torchvision.transforms.Normalize([0.485, 0.456, 0.406], [0.229, 0.224, 0.225])

tran_augs = torchvision.transforms.Compose([
    torchvision.transforms.RandomResizedCrop(224),
    torchvision.transforms.RandomHorizontalFlip(),
    torchvision.transforms.ToTensor(),
    normalize])

test_augs = torchvision.transforms.Compose([
    torchvision.transforms.Resize(256),
    torchvision.transforms.CenterCrop(224),
    torchvision.transforms.ToTensor(),
    normalize])
#调用进行预训练过的resnet18
finetune_net = torchvision.models.resnet18(pretrained=True)
#修改最后一层输出层的参数 finetune_net.fc.in_features 即最后一层的输入个数不改变
finetune_net.fc = nn.Linear(finetune_net.fc.in_features,2)

# 如果param_group=True,输出层中的模型参数将使用十倍的学习率
def train_fine_tuning(net, learning_rate, batch_size=128, num_epochs=5,
                      param_group=True):
    train_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(
        os.path.join(data_dir, 'train'), transform=train_augs),
        batch_size=batch_size, shuffle=True)
    test_iter = torch.utils.data.DataLoader(torchvision.datasets.ImageFolder(
        os.path.join(data_dir, 'test'), transform=test_augs),
        batch_size=batch_size)
    devices = d2l.try_all_gpus()
    loss = nn.CrossEntropyLoss(reduction="none")
    if param_group:#这里就是让最后一层的lr变得大一点 因为微调前面用的lr就比较小
        params_1x = [param for name, param in net.named_parameters()
             if name not in ["fc.weight", "fc.bias"]]
        trainer = torch.optim.SGD([{'params': params_1x},
                                   {'params': net.fc.parameters(),
                                    'lr': learning_rate * 10}],
                                lr=learning_rate, weight_decay=0.001)
    else:
        trainer = torch.optim.SGD(net.parameters(), lr=learning_rate,
                                  weight_decay=0.001)
    d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,
                   devices)

train_fine_tuning(finetune_net, 5e-5)

运行结果,在测试集上的精度达到了0.935,比训练精度还高是因为对训练数据进行了数据增强,对比下没有进行修改的测试数据更加的纯粹,所以精度会比测试的高。

#作为对比实验,这里直接使用初始的resnet模型来进行学习
net = torchvision.models.resnet18()
net.fc = nn.Linear(net.fc.in_features,2)
train_fine_tuning(net,0.001,param_group=False)

运行结果如下,可以看出还是微调效果更好,实质是因为它的初始参数值更有效。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值