卷积神经网络和迁移学习的pytorch实现

卷积神经网络和迁移学习

1 查看和下载常见CNN预训练模型的方法(AlexNet、GooLeNet、DenseNet、VGG、ResNet、NASNet、MobileNet、SqueezeNet等)

(1)使用torchvision
import torchvision.models as models
alexnet = models.alexnet(num_classes=1000, pretrained=True)
 print(alexnet)
 
(2)使用pytorch hub
resnet50 = torch.hub.load('pytorch/vision', 'resnet50',pretrained=True)
print(resnet50)

2 通过AlexNet说明CNN的基本知识点

按上述方法打印AlexNet的结构,可以发现AlexNet就是卷积层和池化层的堆叠,每个卷积层后面均紧跟一个ReLU激活函数。

###

AlexNet(
  (features): Sequential(
    (0): Conv2d(3, 64, kernel_size=(11, 11), stride=(4, 4), padding=(2, 2))
    (1): ReLU(inplace=True)
    (2): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (3): Conv2d(64, 192, kernel_size=(5, 5), stride=(1, 1), padding=(2, 2))
    (4): ReLU(inplace=True)
    (5): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
    (6): Conv2d(192, 384, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (7): ReLU(inplace=True)
    (8): Conv2d(384, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (9): ReLU(inplace=True)
    (10): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1))
    (11): ReLU(inplace=True)
    (12): MaxPool2d(kernel_size=3, stride=2, padding=0, dilation=1, ceil_mode=False)
  )
  (avgpool): AdaptiveAvgPool2d(output_size=(6, 6))
  (classifier): Sequential(
    (0): Dropout(p=0.5, inplace=False)
    (1): Linear(in_features=9216, out_features=4096, bias=True)
    (2): ReLU(inplace=True)
    (3): Dropout(p=0.5, inplace=False)
    (4): Linear(in_features=4096, out_features=4096, bias=True)
    (5): ReLU(inplace=True)
    (6): Linear(in_features=4096, out_features=1000, bias=True)
  )
)

注意事项:

(1)nn.Conv2d的调用格式为:

nn.Conv2d(in_channels,out_channels,kernel_size,stride,padding)

其中

kernel_size,stride,padding参数的行列值不相等时,用元组()的形式给出,行列值相等则简写为一个标量即可,如kernel_size = 3

(2)激活函数可简写为nn.ReLU()

(3)AdaptiveAvgPool2d和AdaptiveMaxPool2d 与 MaxPool2d和AvgPool2d的区别在于前者工作独立于接收的输入张量,可以处理不同数据维度的架构

(4) Dropout(0.5)是指每个训练周期内50%的输入张量会被随机地置为0,防止过拟合

(5)BatchNorm是指批归一化,常见于深度残差网络,确保通过网络的每个小批次的均值为0,方差为1,对于浅层网络,BatchNorm的用处不大,但是对于深层网络,BatchNorm可以确保网络中的乘法不会失控,发生梯度消失或爆炸

3 用resnet进行迁移学习

整体思想:对resnet的整体架构进行微调,在最后加入新的网络模块来替代正常情况下完成ImageNet分类(1000类)的标准线形层。冻结所有的resnet层,训练时只更新新层中的参数,但要从冻结层得到激活值,使我们可以快速地训练新层,同时保留预训练层已经包含的信息。

冻结层的方法即停止梯度累计,方法如下:

from torchvision import models
transfer_model = models.ResNet50(pretrained = True)

for name,param in transfer_model.named_parameters():
      param.requires_grad = False
      
 #也可以不冻结BatchNorm层
 for name,param in transfer_model.named_parameters():
      if('bn' not in name):
             param.requires_grad = False
             
  #把最后的分类模块替换为新模块,以检测鱼和猫为例
  #pytorch中resnet实现的定义将最后的分类部分存储为一个实例变量fc,因此这里直接替换fc即可(有的模型用的不是fc而是classifier,要加以区分)
  transfer_model.fc = nn.Sequential(nn.Linear(transfer_model.fc.in_features,500),nn.ReLU(),nn.Dropout(),nn.Linear(500,2))

4 查找学习率和差分学习率

学习率(learning rate)是深度学习中最重要的超参数之一,过去通常使用网格搜索技术来穷尽搜索一个学习率值的子集,但这种方法很耗时间。

学习率的经验值为3e-4(即Karpathy常量)

为了找到最佳学习率,可以使用查找学习率的方法:在一个epoch周期内,从一个小的学习率开始,每一个小批次增加到一个更大的学习率直到epoch结束得到最大的学习率,计算每个学习率对应的损失值,然后选出使损失下降最快的学习率。

该过程的实现直接调用fast.ai库中的一个函数如下(注意使用该函数找到最佳学习率后,应提前保存并重新加载模型,恢复到调用find_lr之前的状态,重新初始化优化器,设置最佳学习率,继续进行训练):

find_lr(model, loss_fn, optimizer, init_value, final_value)

差分学习率是指用不同的学习率训练不同的层组,用于对模型预训练层的微调,比如修改resnet模型的优化器(第3层和第4层):

optimizer = optimizer.Adam([{'params':transfer_model.layer4.parameters(),'lr':found_lr/3},
{'params':transfer_model.layer3.parameters(),'lr':found_lr/9}], lr = found_lr)

#由于之前已经冻结全部预训练层,因此这里解冻第3和4层,使这些层的参数再次接受梯度,

unfreeze_layers= [transfer_model.layer3,transfer_model.layer4]
for layer in unfreeze_layer:
	for param in layer.parameters():
		param.requires_grad  = True

5 常用的数据增强函数

(1)调整图像亮度、饱和度、对比度和色调

torchvision.transforms.ColorJitter(brightness=0, contrast=0, saturation=0, hue=0)

(2)水平或垂直翻转图像

torchvision.transforms.RandomHorizontalFlip(p = 0.5)
torchvision.transforms.RandomVerticalFlip(p = 0.5)

(3)随机转换图像灰度

torchvision.transforms.RandomGrayscale(p = 0.1)

(4)随机裁剪

torchvision.transforms.RandomCrop()
torchvision.transforms.RandomResizedCrop()

(5)随机旋转

torchvision.transforms.RandomRotation()

(6)填充

torchvision.transforms.Pad()

(7)仿射变换

torchvision.transforms.RandomAffine()

(8)颜色空间的Lambda转换

#使用Image.convert()函数可以将PIL图像从一个颜色空间转换到另一个颜色空间
def _random_colour_space(x):
	output = x.convert("HSV")
	return output
#封装成Lambda类
colour_transform = transforms.Lambda(lambda x: _random_colour_space(x))
random_colour_transform = torchvision.transforms.RandomApply([colour_transform])

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值