【pytorch图像分类】ResNet网络结构
目录
1.引言
2.网络创新
Residual-残差块
Batch Normalization 批范规划层
迁移学习
3.网络架构
4.代码实现
5.总结
1.引言
ResNet 是在 2015 年由何凯明提出来的,斩获当年 ImageNet 竞赛中分类任务第一名,目标检测任务第一名,获得 COCO 数据集中目标检测第一名,图像分割第一名,NB。 原始论文为:Deep Residual Learning for Image Recognition。
随着网络越深,出现的问题
产生梯度消失的现象
网络返回的梯度相关性会越来越差,接近白噪声,导致梯度更新也接近于随机扰动
下面这个是退化(在训练和测试集上都会表现很差),不是过拟合(训练集上表现很好,测试集很差)
下图所示网络越深,错误率反而越高
2.网络创新
Residual-残差块
引入深度残差框架,
让卷积网络取学习残差映射
而不是每一个对叠层网络都完整的拟合潜在的拟合函数
相较于直接优化潜在映射H(x),优化残差映射是更为容
- 注意:加了之后再经过 ReLU 激活函数。
- 注意:主分支与 shortcut 分支的输出特征矩阵的shape必须一致才能进行元素加法。回顾,GoogleNet 是在深度方向进行拼接。
通过最大池化下采样后得到的输出是[56,56,64]
刚好是实线残差结构所需的输入shape
如何理解 Residual 呢?
假设我们要求解的映射为: H ( x ) H(x) H(x)。现在咱们将这个问题转换为求解网络的残差映射函数,也就是 F ( x ) F(x) F(x),其中 F ( x ) = H ( x ) − x F(x) = H(x)-x F(x)=H(x)−x。残差即观测值与估计值之间的差。这里 H ( x ) H(x) H(x) 就是观测值, x x x 就是估计值(也就是上一层Residual 输出的特征映射)。我们一般称 x x x 为 Identity Function(恒等变换),它是一个跳跃连接;称 F ( x ) F(x) F(x) 为 Residual Function。
那么我们要求解的问题变成了 H ( x ) = F ( x ) + x H(x) = F(x)+x H(x)=F(x)+x。有小伙伴可能会疑惑,我们干嘛非要经过 F ( x ) F(x) F(x) 之后在求解 H ( x ) H(x) H(x) 啊!整这么麻烦干嘛,直接搞不好吗,神经网络那么强(三层全连接可以拟合任何函数)!我们来分析分析:如果是采用一般的卷积神经网络的话,原先我们要求解的是 H ( x ) = F ( x ) H(x) = F(x) H(x)=F(x) 这个值对不?那么,我们现在假设,在我的网络达到某一个深度的时候,咱们的网络已经达到最优状态了,也就是说,此时的错误率是最低的时候,再往下加深网络的化就会出现退化问题(错误率上升的问题)。我们现在要更新下一层网络的权值就会变得很麻烦,权值得是一个让下一层网络同样也是最优状态才行,对吧?我们假设输入输出特征尺寸不变,那么下一层最优的状态就是学习一个恒等映射,不改变输入特征是最好的,这样后续的计算会保持,错误了就和浅一层一样了。但是这是很难的,试想一下,给你个 3 × 3 3 \times 3 3×3 卷积,数学上推导出来恒等映射的卷积核参数有一个,那就是中间为 1,其余为 0。但是它不是想学就能学出来的,特别是初始化权重离得远时。
但是采用残差网络就能很好的解决这个问题。还是假设当前网络的深度能够使得错误率最低,如果继续增加咱们的 ResNet,为了保证下一层的网络状态仍然是最优状态,咱们只需要把令 F ( x ) = 0 F(x)=0 F(x)=0 就好啦!因为 x x x 是当前输出的最优解,为了让它成为下一层的最优解也就是希望咱们的输出 H ( x ) = x H(x)=x H(x)=x 的话,是不是只要让 F ( x ) = 0 F(x)=0 F(x)=0 就行了?这个太方便了,只要卷积核参数都足够小,乘法加法之后就是 0 呀。当然上面提到的只是理想情况,咱们在真实测试的时候 x x x 肯定是很难达到最优的,但是总会有那么一个时刻它能够无限接近最优解。采用 Residual 的话,也只用小小的更新 F ( x ) F(x) F(x) 部分的权重值就行啦!不用像一般的卷积层一样大动干戈!
注意:如果残差映射( F ( x ) F(x) F(x))的结果的维度与跳跃连接( x x x)的维度不同,那咱们是没有办法对它们两个进行相加操作的,必须对 x x x进行升维操作,让他俩的维度相同时才能计算。升维的方法有两种:
全 0 填充
采用 1×1 卷积
Bottleneck类的实现
import torch
from torch import nnclass Bottleneck(nn.Module):#残差块中的两个卷积的通道会由64->256,256->1024,所以乘4即可def __init__(self,in_dim,out_dim,stride = 1):super(Bottleneck,self).__init__()#网络堆叠层使用的1*1 3*3 1*1这三个卷积组成,中间有BN层self.bottleneck = nn.Sequential(nn.Conv2d(in_channels=in_dim,out_channels=in_dim,kernel_size=1,bias=False),nn.BatchNorm2d(in_dim),nn.ReLU(inplace=True),nn.Conv2d(in_channels=in_dim,out_channels=in_dim,kernel_size=3,padding=1,bias=False),nn.BatchNorm2d(in_dim),nn.ReLU(inplace=True),nn.Conv2d(in_channels=in_dim,out_channels=out_dim,kernel_size=1,padding=1,bias=False),nn.BatchNorm2d(out_dim))self.relu =nn.ReLU(inplace=True)#Downsample 部分是一个包含BN层的1*1卷积组成'''利用DownSample结构将恒等映射的通道数变为与卷积堆叠层相同,从而保证可以相加'''self.downslape = nn.Sequential(nn.Conv2d(in_channels=in_dim,out_channels=out_dim,kernel_size=1,padding=1,stride=1),nn.BatchNorm2d(out_dim))def forward(self,x):identity = xout = self.bottleneck(identity)identity = self.downslape(x)#将identity(恒等映射)与网络堆叠层输出进行相加。并经过Relu后输出out +=identityout =self.relu(out)return outbottleneck_1 = Bottleneck(64,256)
print(bottleneck_1)input = torch.randn(1,64,56,56)
out = bottleneck_1(input)
print(out.shape)
Batch Normalization 批范规划层
这里可以看之前的解读:深度学习理论-BN层
迁移学习
优势
能够快速的训练出一个理想的结果
当数据集较小时也能训练出理想的效果
理解:
将前面的网络学习到的浅层信息,变为通用的识别方式
注意:使用别人预训练模型的参数时,要注意别人的预处理方式
常见见的迁移学习方式:一般推荐载入权重后训练所有参数
3.网络架构
对于需要进行下采样的残差结构(conv_3, conv_4, conv_5 的第一个残差结构),论文使用如下形式(原论文有多个形式,我们这里说的是最后作者选择的形式),主线部分 3×3 的卷积层使用 stride = 2,实现下采样;虚线部分的 1 × 1 1 \times 1 1×1 卷积且 stride = 2:
4.代码实现
class ResNet(nn.Module):def __init__(self,block,blocks_num,num_class=1000,include_top =True,groups =1):super(ResNet, self).__init__()self.include_top = include_topself.in_channel = 64self.groups = groupsself.conv1 = nn.Conv2d(3,self.in_channel,kernel_size=7,stride=2,padding=3,bias=False)self.bn1 = nn.BatchNorm2d(self.in_channel)self.relu = nn.ReLU(inplace=True)self.maxpool = nn.MaxPool2d(kernel_size=3,stride=2)self.layer1 = self._make_layer(block, 64, blocks_num[0])self.layer2 = self._make_layer(block, 128, blocks_num[1],stride=2)self.layer3 = self._make_layer(block, 256, blocks_num[2],stride=2)self.layer1 = self._make_layer(block, 512, blocks_num[0],stride=2)if self.include_top:self.avgpool = nn.AdaptiveAvgPool2d((1, 1))self.fc = nn.Linear(512 * block.expansion, num_class)def _make_layer(self,block,channel,block_num,stride=1) ->nn.Sequential:downsample = Noneif stride != 1 or self.in_channel != channel*block.expansion:downsample = nn.Sequential(nn.Conv2d(self.in_channel,channel*block.expansion,kernel_size=1,stride=stride,bias=False),nn.BatchNorm2d(channel*block.expansion))layers = []layers.append(block(self.in_channel,channel,downsample=downsample,stride=stride))self.in_channel = channel*block.expansion#将实线的残差结构搭进去for _ in range(1,block_num):layers.append(block(self.in_channel,channel))return nn.Sequential(*layers)def forward(self, x):x = self.conv1(x)x = self.bn1(x)x = self.relu(x)x = self.maxpool(x)x = self.layer1(x)x = self.layer2(x)x = self.layer3(x)x = self.layer4(x)if self.include_top:x = self.avgpool(x)x = torch.flatten(x, 1)x = self.fc(x)return xdef resNet34(num_class=1000,include_top=True)->ResNet:return ResNet(BasicBlock,[3,4,6,3],num_class=num_class,include_top=include_top)def resNet50(num_class=1000,include_top=True):return ResNet(Bottleneck,[3,4,5,6],num_class=num_class,include_top=include_top)def resNet101(num_class=1000,include_top=True):return ResNet(Bottleneck,[3,4,23,3],num_class=num_class,include_top=include_top)
5.总结
学习嵌套函数(nested function)是训练神经网络的理想情况。在深层神经网络中,学习另一层作为恒等映射(identity function)较容易(尽管这是一个极端情况)。
残差映射可以更容易地学习同一函数,例如将权重层中的参数近似为零。
利用残差块(residual blocks)可以训练出一个有效的深层神经网络:输入可以通过层间的残余连接更快地向前传播。
残差网络(ResNet)对随后的深层神经网络设计产生了深远影响。
【pytorch图像分类】ResNet网络结构相关推荐
- pytorch图像分类篇:6. ResNet网络结构详解与迁移学习简介
前言 最近在b站发现了一个非常好的 计算机视觉 + pytorch 的教程,相见恨晚,能让初学者少走很多弯路. 因此决定按着up给的教程路线:图像分类→目标检测→-一步步学习用pytorch实现深度学 ...
- 图像分类篇:pytorch实现ResNet
一.ResNet详解 ResNet网络是在2015年由微软实验室提出的,斩获当年ImageNet竞赛中分类任务第一名,目标检测第一名,获得COCO数据集中目标检测第一名,图像分类第一名. 在ResNe ...
- ResNet网络结构详解,网络搭建,迁移学习
前言: 参考内容来自up:6.1 ResNet网络结构,BN以及迁移学习详解_哔哩哔哩_bilibili up的代码和ppt:https://github.com/WZMIAOMIAO/deep-le ...
- ResNet网络结构,BN以及迁移学习详解
看b站up主霹雳吧啦Wz视频,以及一些文章参考,所做笔计 链接: 6.1 ResNet网络结构,BN以及迁移学习详解_哔哩哔哩_bilibili 深度学习之残差神经网络(ResNet) - 知乎 (z ...
- 【pytorch速成】Pytorch图像分类从模型自定义到测试
文章首发于微信公众号<与有三学AI> [pytorch速成]Pytorch图像分类从模型自定义到测试 前面已跟大家介绍了Caffe和TensorFlow,链接如下. [caffe速成]ca ...
- pytorch图像分类_使用PyTorch和Streamlit创建图像分类Web应用
pytorch图像分类 You just developed a cool ML model. 您刚刚开发了一个很酷的ML模型. You are proud of it. You want to sh ...
- PyTorch 图像分类
PyTorch 图像分类 如何定义神经网络,计算损失值和网络里权重的更新. 应该怎么处理数据? 通常来说,处理图像,文本,语音或者视频数据时,可以使用标准 python 包将数据加载成 numpy 数 ...
- RNN知识+LSTM知识+encoder-decoder+ctc+基于pytorch的crnn网络结构
一.基础知识: 下图是一个循环神经网络实现语言模型的示例,可以看出其是基于当前的输入与过去的输入序列,预测序列的下一个字符. 序列特点就是某一步的输出不仅依赖于这一步的输入,还依赖于其他步的输入或输出 ...
- [Pytorch图像分类全流程实战]Task06:可解释性分析
目录 前言 CAM热力图系列算法 [A]安装配置环境 [B] torchcam命令行 [C1]Pytorch预训练ImageNet图像分类-单张图像 [C2] Pytorch预训练lmageNet图像 ...
- 【PyTorch】1入门——Tensor、自动微分、神经网络、PyTorch 图像分类
PyTorch60min入门教程 1. PyTorch简介 2. 快速入门 2.1 安装与配置 2.2 PyTorch入门第一步 2.2.1 Tensor 2.2.2 自动微分 2.2.3 神经网络 ...
最新文章
- 激光SLAM如何帮助自动驾驶准确定位和建图?
- HDLBits 系列(16)Something about Counter
- 本文详解5G是个什么鬼,程序员都准备好了吗?
- 【动态规划】最大子矩阵之和
- 1091 N-自守数 (15 分)
- 计算机科学与技术专业分多少学科,计算机科学与技术专业,电子科学与技术有什么分别?...
- 有效压缩量子数据的量子自动编码器——Quantum autoencoders for efficient compression of quantum data论文翻译
- android字体颜色渐变色,android背景颜色渐变
- 如何提取html的音频,如何将网页中的音频文件提取出来
- 什么是bug(软件缺陷)
- office 向程序发送命令时出现问题
- 富士胶片展示透明投影膜、CMF表面装饰材料及HydroAg+抗菌技术
- 【python安装】错误——“User installations are disabled via policy on the machine”
- FF新推荐的本地文件
- 开源!!!100多个常用API接口免费分享!建议收藏!
- 图文详解 新版VMware Workstation 7.0的最大特色
- ubuntu backup-manager 高效备份工具
- iptables 设置端口转发/映射
- 一小时刷完英语口语常用3000词汇(绿色护眼版)day10-词汇901-1000
- activiti报错 cvc-datatype-valid.1.2.1: ‘‘ 不是 ‘NCName‘ 的有效值。