预训练--微调

预训练–微调

一个很简单的道理,如果我们的模型是再ImageNet下训练的,那么这个模型一定是会比较复杂的,意思就是这个模型可以识别到很多种类别的即泛化能力很强,但是如果要它精确的识别是否某种类别,它的表现可能就不佳了,因此,我们需要在原来的基础上再对特定的我们需要识别的类别进行重新训练,微调原来网络结构中的参数,此时模型还是可以抽取较通用的图像特征。
在这里插入图片描述
参考自https://tangshusen.me/Dive-into-DL-PyTorch/#/chapter09_computer-vision/9.2_fine-tuning
当目标数据集远小于源数据集时,微调有助于提升模型的泛化能力。

热狗识别

源数据集是ImageNet,超过1000万个图像和1000类物体,热狗数据集包含1400个正类图像和其他多种负类图像
最开始还是导入所需要的库以及设置cuda

import torch
from torch import nn,optim
from torch.utils.data import Dataset, DataLoader
import torchvision
from torchvision.datasets import ImageFolder
from torchvision import transforms
from torchvision import models
import os
import d2lzh_pytorch as d2l
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

下载数据集https://apache-mxnet.s3-accelerate.amazonaws.com/gluon/dataset/hotdog.zip
我直接放在了我的默认路径下,读数据如下

train_imgs = ImageFolder("hotdog/train")
test_imgs = ImageFolder("hotdog/test")

然后我们观察一下数据集,可以看到大小,宽高比各不同

# 前八张正类图像和最后八张负类图像,可以看到宽高比、大小各不同
hotdogs = [train_imgs[i][0] for i in range(8)]
not_hotdogs = [test_imgs[-1-i][0] for i in range(8)]
d2l.show_images(hotdogs + not_hotdogs,2, 8, scale=2)

在这里插入图片描述
接下来就是训练时,我们先从图像中随机裁剪一块区域,然后将该区域缩放成224*224的图像进行输入,测试时,我们将图像的高和宽均缩放为256像素,然后从中裁剪出高、宽均为224的中心区域作为输入,此外对RGB三通道作标准化,每个数值减去通道的平均值,再除以标准差需要注意的是,在使用预训练模型时,一定要和预训练时作同样的预处理。 如果你使用的是torchvision的models,
那就要求: All pre-trained models expect input images normalized in the same way, i.e. mini-batches of 3-channel RGB images of shape (3 x H x W), where H and W are expected to be at least 224. The images have to be loaded in to a range of [0, 1] and then normalized using mean = [0.485, 0.456, 0.406] and std = [0.229, 0.224, 0.225].
如果你使用的是pretrained-models.pytorch仓库,请务必阅读其README,其中说明了如何预处理。

normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
train_augs = transforms.Compose([#transforms.Resize(size=256),  # 是将最小边调整到256#transforms.CenterCrop(size=224),transforms.RandomResizedCrop(size=224),transforms.RandomHorizontalFlip(),transforms.ToTensor(),normalize
])test_augs = transforms.Compose([transforms.Resize(size=256),transforms.CenterCrop(size=224),transforms.ToTensor(),normalize
])

需要注意的是,首先我有最开始有两点疑惑

  1. 为什么不能需要从图像中随机裁剪一块区域,然后将该区域缩放成224*224的图像进行输入。然后我测试了一下,如果不这样做的话,那么泛化能力会比较差
  2. 如果非要这么做,那么可不可以直接transforms.Resize(size=224)?不可以的,transforms.Resize(size=224)是把最短的边变为224,宽高比没变,那么这样就会导致图像的尺寸不一样,后面自然会报错,所以需要先transforms.Resize(size=256),然后transforms.CenterCrop(size=224)

之后我们使用在ImageNet上预训练的ResNet18,pretrained=True,自动下载预训练参数
不管你是使用的torchvision的models还是pretrained-models.pytorch仓库,默认都会将预训练好的模型参数下载到你的home目录下.torch文件夹。
你可以通过修改环境变量$TORCH_MODEL_ZOO来更改下载目录

pretrained_net = models.resnet18(pretrained=True)

修改最后一层

pretrained_net.fc = nn.Linear(512, 2)

接下来设置训练的参数,由于除了最后一层,之前的参数都经过预训练,所以我们学习率调小一点,最后的fc层是初始化过的,于是我们学习率调大一点

output_params = list(map(id, pretrained_net.fc.parameters()))  # fc层
feature_params = filter(lambda p: id(p) not in output_params, pretrained_net.parameters())  # 除了fc层
lr = 0.01 # 用来更新特征层
# fc层是lr * 10
optimizer = optim.SGD([{"params":feature_params},{"params":pretrained_net.fc.parameters(), "lr":lr*10}
] ,lr = lr, weight_decay=0.001)

在之后就是训练了

def train_fine_tuning(net, optimizer, batch_size=64, num_epochs=5):train_iter = DataLoader(ImageFolder("hotdog/train", transform=train_augs), batch_size, shuffle=True)test_iter = DataLoader(ImageFolder("hotdog/test", transform=test_augs), batch_size, shuffle=False)loss = torch.nn.CrossEntropyLoss()d2l.train(train_iter, test_iter, net, loss, optimizer, device, num_epochs)
train_fine_tuning(pretrained_net, optimizer)

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/258925.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

frp内网穿透部署,轻松实现内网服务对外访问

FRP(Fast Reverse Proxy)是一种轻量级、高性能的反向代理工具,利用反向代理技术将公网请求转发至内网服务器上,并将内网服务器的响应再次转发至公网请求者。在实现内网穿透时,FRP能够将公网与内网之间的隔离突破&#…

ArkTS快速入门

一、概述 ArkTS是鸿蒙生态的应用开发语言。它在保持TypeScript(简称TS)基本语法风格的基础上,对TS的动态类型特性施加更严格的约束,引入静态类型。同时,提供了声明式UI、状态管理等相应的能力,让开发者可以…

jmeter常用的性能测试监听器

jmeter中提供了很多性能数据的监听器,我们通过监听器可以来分析性能瓶颈 本文以500线程的阶梯加压测试结果来描述图表。 常用监听器 1:Transactions per Second 监听动态TPS,用来分析吞吐量。其中横坐标是运行时间,纵坐标是TPS…

火狐,要完了!

在过去几年中,关于Firefox 浏览器的衰落有过不少讨论。目前来说,很多公共的以及私营的大型网站都缺乏对Firefox的适当支持。但是Firefox也多次试图“自救”,甚至就在不久前,Mozilla 通过官博发文,表示 Firefox 在 2023…

一个 postman实现参数化让我丢掉了一份20k的offer

什么时候会用到参数化 比如:一个模块要用多组不同数据进行测试 验证业务的正确性 Login模块:正确的用户名,密码 成功;错误的用户名,正确的密码 失败 postman实现参数化 在实际的接口测试中,部分参数…

设计并实现一个多线程图书馆管理系统,涉及数据库操作

没有实现全部功能,希望路过的大佬,可以实现全部功能,在评论区聊聊 创建数据库library-demo CREATE DATABASE library-demo创建图书表book CREATE TABLE book (bookId int(11) NOT NULL AUTO_INCREMENT COMMENT 图书ID,bookName varchar(15)…

Leetcode—213.打家劫舍II【中等】

2023每日刷题&#xff08;五十二&#xff09; Leetcode—213.打家劫舍II 算法思路 实现代码 class Solution { public:// 左闭右开int rob1(vector<int>& nums, int start, int end) {int n nums.size();int f0 0, f1 0, new_f 0;for(int i start; i < end…

挡墙边界提取

基于点云对挡墙边界进行提取 算法思路 将点转到极坐标系下&#xff0c;并得到极坐标系下的索引值&#xff0c;并输出距离信息。 double getCellIndexFromPoints(double x, double y, int& chI) {// 计算点到原点的欧几里得距离double distance sqrt(x * x y * y);// 将…

vue中组件传值方法

父组件给子组件传值 一、 1.在子组件标签中写入父组件传递数据 向下传递prop 2.在子组件内声明props选项接收父组件传递的数据 props:[,,] 父组件&#xff1a; <Header :msgmsg ></Header> 子组件&#xff1a; props:[msg], 二、 provide i…

vue3 vue-router编程式导航(二)

文章目录 一、跳转到指定路径1. query传参2. Params传参 二、前进/后退三、替换当前页 Vue Router提供了强大且灵活的编程式导航功能&#xff0c;能够通过代码来控制路由的切换和跳转。本篇博客将介绍如何在Vue 3应用程序中使用Vue Router进行编程式导航。 一、跳转到指定路径…

markdown记录

文章目录 基础操作使用一级列表、二级列表 博文链接 基础操作 使用一级列表、二级列表 博文链接 CSDN-Markdown语法集锦 CSDN-markdown语法之如何使用LaTeX语法编写数学公式 CSDN Markdown简明教程1-关于Markdown CSDN Markdown简明教程2-基本使用 CSDN Markdown简明教程3-表…

uni-app 微信小程序之好看的ui登录页面(五)

文章目录 1. 页面效果2. 页面样式代码 更多登录ui页面 uni-app 微信小程序之好看的ui登录页面&#xff08;一&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;二&#xff09; uni-app 微信小程序之好看的ui登录页面&#xff08;三&#xff09; uni-app 微信小程…