文章目录

  • 一、微调(fine tuning)
    • 1. 微调的四个步骤:
    • 2. 微调的训练过程
    • 3. 常用的微调技术
    • 4. 总结
  • 二、动手实现和测试微调
    • 1. 数据准备
    • 2. 模型微调
    • 3. 对比不使用微调和不同的微调参数
    • 4. 冻结层进行微调

一、微调(fine tuning)

1. 微调的四个步骤:

  1. 在源数据集(如ImageNet数据集)上预训练一个神经网络模型,即源模型。
  2. 创建一个新的神经网络模型,即目标模型。它复制了源模型上除了输出层外的所有模型设计及其参数。我们假设这些模型参数包含了源数据集上学习到的知识,且这些知识同样适用于目标数据集。我们还假设源模型的输出层与源数据集的标签紧密相关,因此在目标模型中不予采用。
  3. 为目标模型添加一个输出大小为目标数据集类别个数的输出层,并随机初始化该层的模型参数。
  4. 在目标数据集(如椅子数据集)上训练目标模型。我们将从头训练输出层,而其余层的参数都是基于源模型的参数微调得到的。

2. 微调的训练过程

  1. 是一个目标数据集上的正常训练任务
  2. 使用了更强的正则化:
    • 更小的学习率(大stride在初始模型中已走过了,相当于已经有一个比较好的模型了)
    • 更少的迭代次数
      3.源数据集远复杂于目标数据,通常得到的微调效果更好

3. 常用的微调技术

  1. 重用分类器权重(对最后的分类层进行的处理哦!!!)

    • 源数据可能也有目标数据中的部分标号
    • 可以使用预训练好的模型分类器中对应标号对应的向量作初始化值
  2. 固定一些层
    • 神经网络通常学习有层次的特征表示(底层描述的特征更加通用,而高层的特征和数据集相关性更强)
    • 可以固定相对底部的层,不参与参数更新(应用了更强的正则化)

4. 总结

  1. 微调通过使用在大数据上得到的预训练模型来初始化权重来提高精度
  2. 预训练模型质量非常重要
  3. 微调通常速度更快、精度更高

二、动手实现和测试微调

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

1. 数据准备

# 下载热狗数据集
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'))
test_imgs = torchvision.datasets.ImageFolder(os.path.join(data_dir, 'test'))
# 查看数据
'''展示了8张热狗数据和非热狗的数据,图像的大小和横纵比例都不尽相同'''
hotdogs = [train_imgs[i][0] for i in range(8)] # hotdogs
not_hotdogs = [train_imgs[-i-1][0] for i in range(8)] # not hotdogs
d2l.show_images(hotdogs + not_hotdogs, 2, 8, scale=1.4);
# 数据增广使数据规整变多
'''
在训练期间,我们首先从图像中裁切随机大小和随机长宽比的区域,然后将该区域缩放为 224x224 输入图像。
在测试过程中,我们将图像的高度和宽度都缩放到 256 像素,然后裁剪中央 224 x 224 区域作为输入。
此外,对于三个 RGB(红、绿和蓝)颜色通道,我们标准化每个通道。
具体而言,通道的平均值将从该通道的每个值中减去,然后将结果除以该通道的标准差。
'''
# 在Imagenet上使用的Normalize直接搬过来,参数第一个是mean,第二个是std;image = (image-mean)/std;这里是三通道
normalize = torchvision.transforms.Normalize([0.485, 0.456, 0.406],[0.229, 0.224, 0.225])
train_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])

2. 模型微调

定义和初始化模型

# 定义和初始化模型
'''
使用ImageNet数据集预训练的ResNet-18作为源模型;
指pretrained =True,以保存模型参数
'''
pretrained_net = torchvision.models.resnet18(pretrained=True)

Check原始模型参数

# 源模型包含多个要素图层和一个输出图层,对除了输出图层之外的层进行微调
'''查看源模型的输出图层参数'''
pretrained_net.fc
Linear(in_features=512, out_features=1000, bias=True)
# 初始化微调图层
finetune_net = torchvision.models.resnet18(pretrained=True)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
nn.init.xavier_uniform_(finetune_net.fc.weight);

定义训练函数,便于更多参数的调整

# 如果 `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:'''将所有层的参数都拿出来进行训练,最后一层的学习率是前面层的10倍'''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)
loss 0.181, train acc 0.932, test acc 0.935
228.9 examples/sec on [device(type='cuda', index=0)]

3. 对比不使用微调和不同的微调参数

如果不使用微调,直接从零开始训练:不使用微调的结果精度远远低于微调的结果

# 对比不使用微调
scratch_net = torchvision.models.resnet18()
scratch_net.fc = nn.Linear(scratch_net.fc.in_features, 2)
train_fine_tuning(scratch_net, 5e-4, param_group=False)
loss 0.384, train acc 0.831, test acc 0.814
229.5 examples/sec on [device(type='cuda', index=0)]

调整fine turning 的学习率发现:学习率变太高会降低训练的精度

# 调高fine turning 的学习率
finetune_net = torchvision.models.resnet18(pretrained=True)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
nn.init.xavier_uniform_(finetune_net.fc.weight);
train_fine_tuning(finetune_net, 4e-5)
loss 0.203, train acc 0.921, test acc 0.930
229.4 examples/sec on [device(type='cuda', index=0)]

4. 冻结层进行微调

冻结一部分的层进行训练:冻结层训练可以减少训练的时间,但是具体要冻结哪些层需要调整,我这里使用的方法也不确定是否正确,因为使用requires_grad没有使用成功,就找了个笨方法

# 如果不更新输出层之前的层的参数(冻结一些层)
# 我这里没有使用requires_grad = False,没有仔细探究是否真的冻结住了。是否需要将不计算梯度放到train函数之中
def train_fine_tuning_freeze(net, learning_rate, batch_size=128, num_epochs=5):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")'''冻结一些层(只更新最后层的参数)'''trainer = torch.optim.SGD(net.fc.parameters(), lr=learning_rate,weight_decay=0.001)d2l.train_ch13(net, train_iter, test_iter, loss, trainer, num_epochs,devices)finetune_net = torchvision.models.resnet18(pretrained=True)
finetune_net.fc = nn.Linear(finetune_net.fc.in_features, 2)
nn.init.xavier_uniform_(finetune_net.fc.weight);
train_fine_tuning_freeze(finetune_net, 5e-5,num_epochs=10)
loss 0.299, train acc 0.878, test acc 0.887
231.1 examples/sec on [device(type='cuda', index=0)]

如果有什么存在疑惑的地方可以在评论区提出,大家一起讨论!

动手学深度学习(二十七)——微调(fine turning)相关推荐

  1. 动手学深度学习打卡之二。

    第二次打卡内容(2月15日-18日) Task03:过拟合.欠拟合及其解决方案:梯度消失.梯度爆炸:循环神经网络进阶(1天) Task04:机器翻译及相关技术:注意力机制与Seq2seq模型:Tran ...

  2. 资源 | 李沐等人开源中文书《动手学深度学习》预览版上线

    来源:机器之心 本文约2000字,建议阅读10分钟. 本文为大家介绍了一本交互式深度学习书籍. 近日,由 Aston Zhang.李沐等人所著图书<动手学深度学习>放出了在线预览版,以供读 ...

  3. 《动手学深度学习》PyTorch版本

    Dive-Into-Deep-Learning-PyTorch-PDF 简介   本项目对中文版<动手学深度学习>中的代码进行整理,并参考一些优秀的GitHub项目给出基于PyTorch的 ...

  4. 【深度学习】李沐《动手学深度学习》的PyTorch实现已完成

    这个项目是中文版<动手学深度学习>中的代码进行整理,用Pytorch实现,是目前全网最全的Pytorch版本. 项目作者:吴振宇博士 简介   Dive-Into-Deep-Learnin ...

  5. 送10本今年最火的《动手学深度学习》

    点击我爱计算机视觉标星,更快获取CVML新技术 52CV曾经多次介绍FlyAI机器学习竞赛平台,不少粉丝也曾在FlyAI拿到现金奖励. 本次52CV & FlyAI联合送书,CV君查找了两天, ...

  6. 《动手学深度学习》TF2.0 实现

    本项目将<动手学深度学习> 原书中MXNet代码实现改为TensorFlow2.0实现.经过我的导师咨询李沐老师,这个项目的实施已得到李沐老师的同意.原书作者:阿斯顿·张.李沐.扎卡里 C ...

  7. 364 页 PyTorch 版《动手学深度学习》分享(全中文,支持 Jupyter 运行)

    1 前言 最近有朋友留言要求分享一下李沐老师的<动手学深度学习>,小汤本着一直坚持的"好资源大家一起分享,共同学习,共同进步"的初衷,于是便去找了资料,而且还是中文版的 ...

  8. 《动手学深度学习》—学习笔记

    文章目录 深度学习简介 起源 特点 小结 预备知识 获取和运行本书的代码 pytorch环境安装 方式一 方式二 数据操作 创建 运算 广播机制 索引 运算的内存开销 NDArray和NumPy相互变 ...

  9. 第0章【序】--动手学深度学习【Tensorflow2.0版本】

    项目地址:https://github.com/TrickyGo/Dive-into-DL-TensorFlow2.0 这个项目将<动手学深度学习> 原书中MXNet代码实现改为Tenso ...

  10. 动手学深度学习: 图像分类案例2,GAN,DCGAN

    动手学深度学习: 图像分类案例2,GAN,DCGAN 内容摘自伯禹人工智能AI公益课程 图像分类案例2 1.关于整理数据集后得到的train.valid.train_valid和test数据集: 1) ...

最新文章

  1. 招募100名科研人,念出书中内容即可,300元/小时,无经验要求!
  2. 大数据算法系列——布隆过滤器
  3. 计算机应用基础形考报告2020,放大学计算机应用基础形考本学习报告
  4. 面向中文短文本的实体链指任务竞赛亚军DeepBlueAI团队技术分享
  5. Django Abstract Models使用下划线设置related_name
  6. runtime相关知识
  7. return和break的区别
  8. 使用Prometheus针对自己的服务器采集自定义的参数
  9. 不可变集合相比可变集合_简单的基准测试:不可变集合VS持久集合
  10. python xlrd读取文件报错_python中xlrd库如何实现文件读取?
  11. 转:关掉Archlinux中烦人的响铃
  12. 老男孩教育学员参观机房实践活动
  13. python文件加锁
  14. J2EE常用Listener(转载)
  15. 自动优化工具Black帮你写出规范漂亮的python代码
  16. WinDriver高级编程
  17. 怎么设计计算机网络共享,怎么设置网络共享?教大家两种设置共享网络的方法...
  18. 这个机器人还原魔方,只需八秒!
  19. 【音频编码】AAC编码之FDK AAC
  20. 【Simulink】仿真_PID控制器调谐/调参/整定

热门文章

  1. 猜名人读心术作业C语言答案,读心术游戏,读心术游戏猜人物
  2. 5G移动通信技术基本介绍(附92页PDF下载)
  3. 蓝桥 盾神与积木游戏(Java)
  4. 点对点网络带宽测试软件,点对点带宽测试工具iperf
  5. 房屋登记官考核模拟题(6)
  6. 中科院软件所的毕业去向(硕+博)
  7. Discuz showWindow函数解析
  8. 2021安徽安全员C证考试多选练习题库
  9. OverTheWire的bandit游戏(11-20)
  10. 江苏事业单位——计算机类