Pytorch实现迁移学习

迁移学习

迁移学习是一种机器学习的方法,指的是一个预训练的模型被重新用在另一个任务中,它专注于存储已有问题的解决模型,并将其利用在其他不同但相关问题上。例如我在A的场景下训练了一个模型,而B、C、D等场景与A类似,那么我们就可以把A的模型使用在这些类似场景上,A中的工作相当于做了预训练了。很多情况下迁移学习能够简化或降低模型构建的难度,节省训练时间、硬件消耗等,甚至还能取得不错的准确度。

Pytorch VGG16迁移学习实战

torchvision 包含流行的数据集、模型架构和用于计算机视觉的常见图像转换。因此我们调用VGG16这个图像领域的网络模型时,会用到torchvision来调用

首先需要调用torchvision中的models,通过models调用vgg16

from torchvision import models
model = models.vgg16(pretrained=True)

下图官方文档中对vgg16_bn的描述,pretrained=True即会返回一个预训练好的模型,VGG16在ImageNet上是224*224,之后只要将自己数据集中调整到符合vgg16要求即可了,同样也要注意vgg16的输出,因为它是基于ImageNet训练的,所以输出会是一个1000维的向量,之后就可以使用该模型做预测了,或者进行微调和二次训练。

函数vgg16_bn与函数vgg16的唯一区别在于vgg16_bn中添加了batch_normalization

image-20211028214557687

网络结构调整

这里以二分类为例,我们需要将原先1000维的输出调整为2维。

为避免不必要的训练消耗,将参数的自动梯度设为false

for parma in model.parameters():  # 设置自动梯度为false
    parma.requires_grad = False

首先我们先输出一下vgg16的网络结构

model._modules

<bound method Module.named_modules of VGG(
(features): Sequential(
(0): Conv2d(3, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(1): ReLU(inplace=True)
(2): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(3): ReLU(inplace=True)
(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=True)
(7): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(8): ReLU(inplace=True)
(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=True)
(12): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(13): ReLU(inplace=True)
(14): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(15): ReLU(inplace=True)
(16): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(17): Conv2d(256, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(18): ReLU(inplace=True)
(19): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(20): ReLU(inplace=True)
(21): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(22): ReLU(inplace=True)
(23): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
(24): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(25): ReLU(inplace=True)
(26): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(27): ReLU(inplace=True)
(28): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
(29): ReLU(inplace=True)
(30): MaxPool2d(kernel_size=2, stride=2, padding=0, dilation=1, ceil_mode=False)
)
(avgpool): AdaptiveAvgPool2d(output_size=(7, 7))
(classifier): Sequential(
(0): Linear(in_features=25088, out_features=4096, bias=True)
(1): ReLU(inplace=True)
(2): Dropout(p=0.5, inplace=False)
(3): Linear(in_features=4096, out_features=4096, bias=True)
(4): ReLU(inplace=True)
(5): Dropout(p=0.5, inplace=False)
(6): Linear(in_features=4096, out_features=1000, bias=True)
)
)>

可以看到最终的分类在classifier中,关键层是classifier[6],那我们就修改它

model.classifier[6] = nn.Linear(in_features=4096, out_features=2)

修改后梯度计算会恢复为默认的True,可以用同样的方法去冻结某个层参数的梯度计算以及修改模型中某一层的结构

参考

https://blog.csdn.net/weixin_43199584/article/details/105190965

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值