位置: IT常识 - 正文

卷积神经网络学习—Resnet50(论文精读+pytorch代码复现)(卷积神经网络课程)

编辑:rootadmin
卷积神经网络学习—Resnet50(论文精读+pytorch代码复现) 前言一、Resnet论文精读引入残差残差块ResNet50模型基本构成BN层Resnet50总体结构二、Resnet50代码复现完整代码前言

推荐整理分享卷积神经网络学习—Resnet50(论文精读+pytorch代码复现)(卷积神经网络课程),希望有所帮助,仅作参考,欢迎阅读内容。

文章相关热门搜索词:卷积神经网络视频,卷积神经网络教程,卷积神经网络学到了什么,卷积神经网络教学视频,卷积神经网络学到了什么,卷积神经网络教程,卷积神经网络学生,卷积神经网络学的是什么,内容如对您有帮助,希望把文章链接给更多的朋友!

如果说在CNN领域一定要学习一个卷积神经网络,那一定非Resnet莫属了。 接下来我将按照:Resnet论文解读、Pytorch实现ResNet50模型两部分,进行讲解,博主也是初学者,不足之处欢迎大家批评指正。

预备知识:卷积网络的深度越深,提取的特征越高级,性能越好,但传统的卷积神经网络随着层数深度的增加,会面临网络退化、梯度消失、梯度爆炸等问题,使得高层网络的性能反而不如浅层网络。

卷积细节: 将一个*(W,H,C)的3维矩阵*,输入卷积层,卷积步长stride,边界填充数量padding,KxK卷积核Cout个:

输出一个(W-K+2padding)/stride +1,(H-K+2padding)/stride +1,Cout)的3维矩阵。

网络退化: 深层网络训练模型可收敛,但在测试集和训练集的误差均大于浅层网络。 (与过拟合不同:过拟合是训练集误差低,测试集误差高) 梯度消失: 假设每层梯度是一个小于1的数,由链式法则,反向传播时,梯度时不断相乘的,每向前传播一层,梯度就乘以一个小于1的数,传到最后一层,梯度已经接近0了,这就是梯度消失,换句话说就是,小于1的数连成很快会趋近于0。 梯度爆炸: 反之,如果每层梯度是一个大于1的数,大于1的数连成很快会趋近于无穷。

为解决上述问题 Resnet创新亮点: 1.解决梯度消失\爆炸问题:引入BN层(Batch Normalization),弃用Dropout 2.解决网络退化问题:引入残差(Residual)

`提示:以下是本篇文章正文

一、Resnet论文精读引入残差

残差的基本思想:真实测量值=预测值+残差 **

残差块

**: 其中,输入X,分为两路,X为恒等映射,F(X)为残差映射,两者求和进入激活函数,再输出Relu(F(X)+X)。

残差F(X)的作用:是修正恒等映射X的误差,使网络拟合的更好。 如果X足够好,则残差的参数均为0,使输出的F(X)=0; 如果X不够好,F(X)在X的基础上优化。

其中,F(X)与X相加时,shape必须相同,若F(X)的数据维数变化(如stride>1降维),则X也需要进行相应的变化(如对X做1x1的卷积)。

求F(X)残差的卷积均使用3x3conv,下采样大小降维一半。

卷积神经网络学习—Resnet50(论文精读+pytorch代码复现)(卷积神经网络课程)

由于恒等映射X的存在,反向传播时,梯度可以从深层直接给到浅层,避免了梯度消失与爆炸。

改进的残差块:

**

ResNet50模型基本构成

** ResNet50有两个基本的块,分别名为Conv Block和Identity Block。 Conv Block:针对X和F(X)的维度(通道数和size)是不一样的,所以不能连续串联,它的作用是改变网络的维度;

Identity Block:针对X和F(X)的维度(通道数和size)相同,可以串联,用于加深网络的。 **

BN层

:** Batch normalization:目的是预处理使我们的一批(Batch)的feature map满足均值为0,方差为1的分布规律,这样能够加速网络的收敛。(在网络中间调整每层输入的feature map)。

一个batch size为2(两张图片,每张图片有3个通道,其中颜色红,绿,蓝分别代表r,g,b通道。)的Batch Normalization的原理,首先会统计每个通道数目所有点的像素值,求得均值和方差,然后在每个通道上分别用该点的像素值减均值除方差得到该点的像素值,此过程就是BN。最后将其接入到激活函数中。 (其中,Xi是指一批数据的同一个通道的所有特征图的数据,如下图X1就是指两张彩图的R通道的所有数据)

上述公式中,xi经过减均值,除方差之后,得到的数据的均值为0,方差为1,而后面的γ和β参数的作用又是什么呢?有时均值为0,方差为1并不是最好的效果,所以可以用通过γ调整数据的方差,通过β调整数据的均值。

介绍完BN层的原理,下面我们来看看具体的实例吧: feature map1、feature map2分别是由image1、image2经过一系列卷积池化后得到的特征矩阵。其中每个网格的值代表该点的像素值,分别统计feature map1 和feature map2每个通道的像素值,得到一个矩阵,在使用BN的计算公式计算经过BN以后,得到每个通道每个像素点的像素值。计算公式也如下。 [注]: (1)训练时要将traning参数设置为True,在验证时将trainning参数设置为False。在pytorch中可通过创建 模型的model.train()和model.eval()方法控制。 (2)batch size尽可能设置大点,设置小后表现可能很糟糕,设置的越大求的均值和方差越接近整个训练集的均值和方差。 (3)一般将bn层放在卷积层(Conv)和激活层(例如Relu)之间,且卷积层不要使用偏置bias,因为使用偏置和不使用偏置的yi是相等的,所以使用偏置只会徒增网络的参数,导致训练起来更加的费劲。

标准化(standardization):将数据通过去均值实现中心化的处理,根据凸优化理论与数据概率分布相关知识,数据中心化符合数据分布规律,更容易取得训练之后的泛化效果, 数据标准化是数据预处理的常见方法之一,缩放和每个点都有关系,通过方差(variance)体现出来。与归一化对比,标准化中所有数据点都有贡献(通过均值和标准差造成影响)。加速模型收敛:标准化后,最优解的寻优过程明显会变得平缓,更容易正确的收敛到最优解。 归一化(Normalization):归一化的目标是找到某种映射关系,将原数据映射到(a,b)区间上,如0~1之间,缩放仅仅跟最大、最小值的差别有关。提升模型精度:归一化后,不同维度之间的特征在数值上有一定比较性,可以大大提高分类器的准确性。

**

Resnet50总体结构

:** Resnet网络就是残差块的堆叠,解决了网络退化问题,实现网络层数的加深,使之拥有足够好的特征提取能力。

补充: Resnet解决网络退化的原理: 1.深度梯度回传顺畅:恒等映射这一路的梯度是1,可以把浅层的信号传到深层,也可以把深层的梯度注回浅层,防止梯度消失。 2.传统线性结构网络难以拟合“恒等映射”:什么都不做时很重要;skip connection可以让模型自行选择要不要更新;弥补了高度线性造成的不可逆的信息损失。 3.图像相邻像素梯度的局部相关性:解决了传统多层卷积造成的,回传的相邻像素梯度的局部相关性越来越低的问题。

二、Resnet50代码复现

完整代码

代码如下(示例):

import torch.nn as nnimport torch# Resnet 18/34使用此残差块class BasicBlock(nn.Module): # 卷积2层,F(X)和X的维度相等 # expansion是F(X)相对X维度拓展的倍数 expansion = 1 # 残差映射F(X)的维度有没有发生变化,1表示没有变化,downsample=None # in_channel输入特征矩阵的深度(图像通道数,如输入层有RGB三个分量,使得输入特征矩阵的深度是3),out_channel输出特征矩阵的深度(卷积核个数),stride卷积步长,downsample是用来将残差数据和卷积数据的shape变的相同,可以直接进行相加操作。 def __init__(self, in_channel, out_channel, stride=1, downsample=None, **kwargs): super(BasicBlock, self).__init__() self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=out_channel,kernel_size=3, stride=stride, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(out_channel) # BN层在conv和relu层之间 self.conv2 = nn.Conv2d(in_channels=out_channel, out_channels=out_channel,kernel_size=3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(out_channel) self.relu = nn.ReLU(inplace=True) self.downsample = downsample def forward(self, x): identity = x if self.downsample is not None: identity = self.downsample(x) out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) # out=F(X)+X out += identity out = self.relu(out) return out# Resnet 50/101/152使用此残差块class Bottleneck(nn.Module): # 卷积3层,F(X)和X的维度不等 """ 注意:原论文中,在虚线残差结构的主分支上,第一个1x1卷积层的步距是2,第二个3x3卷积层步距是1。 但在pytorch官方实现过程中是第一个1x1卷积层的步距是1,第二个3x3卷积层步距是2, 这么做的好处是能够在top1上提升大概0.5%的准确率。 """ # expansion是F(X)相对X维度拓展的倍数 expansion = 4 def __init__(self, in_channel, out_channel, stride=1, downsample=None, groups=1, width_per_group=64): super(Bottleneck, self).__init__() width = int(out_channel * (width_per_group / 64.)) * groups # 此处width=out_channel self.conv1 = nn.Conv2d(in_channels=in_channel, out_channels=width,kernel_size=1, stride=1, bias=False) # squeeze channels self.bn1 = nn.BatchNorm2d(width) # ----------------------------------------- self.conv2 = nn.Conv2d(in_channels=width, out_channels=width, groups=groups,kernel_size=3, stride=stride, bias=False, padding=1) self.bn2 = nn.BatchNorm2d(width) # ----------------------------------------- self.conv3 = nn.Conv2d(in_channels=width, out_channels=out_channel * self.expansion,kernel_size=1, stride=1, bias=False) # unsqueeze channels self.bn3 = nn.BatchNorm2d(out_channel * self.expansion) self.relu = nn.ReLU(inplace=True) self.downsample = downsample def forward(self, x): identity = x # downsample是用来将残差数据和卷积数据的shape变的相同,可以直接进行相加操作。 if self.downsample is not None: identity = self.downsample(x) out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.conv3(out) out = self.bn3(out) # out=F(X)+X out += identity out = self.relu(out) return outclass ResNet(nn.Module): def __init__(self, block, # 使用的残差块类型 blocks_num, # 每个卷积层,使用残差块的个数 num_classes=1000, # 训练集标签的分类个数 include_top=True, # 是否在残差结构后接上pooling、fc、softmax groups=1, width_per_group=64): super(ResNet, self).__init__() self.include_top = include_top self.in_channel = 64 # 第一层卷积输出特征矩阵的深度,也是后面层输入特征矩阵的深度 self.groups = groups self.width_per_group = width_per_group # 输入层有RGB三个分量,使得输入特征矩阵的深度是3 self.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, padding=1) # _make_layer(残差块类型,残差块中第一个卷积层的卷积核个数,残差块个数,残差块中卷积步长)函数:生成多个连续的残差块的残差结构 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.layer4 = self._make_layer(block, 512, blocks_num[3], stride=2) if self.include_top: # 默认为True,接上pooling、fc、softmax self.avgpool = nn.AdaptiveAvgPool2d((1, 1)) # 自适应平均池化下采样,无论输入矩阵的shape为多少,output size均为的高宽均为1x1 # 使矩阵展平为向量,如(W,H,C)->(1,1,W*H*C),深度为W*H*C self.fc = nn.Linear(512 * block.expansion, num_classes) # 全连接层,512 * block.expansion为输入深度,num_classes为分类类别个数 for m in self.modules(): # 初始化 if isinstance(m, nn.Conv2d): nn.init.kaiming_normal_(m.weight, mode='fan_out', nonlinearity='relu') # _make_layer()函数:生成多个连续的残差块,(残差块类型,残差块中第一个卷积层的卷积核个数,残差块个数,残差块中卷积步长) def _make_layer(self, block, channel, block_num, stride=1): downsample = None # 寻找:卷积步长不为1或深度扩张有变化,导致F(X)与X的shape不同的残差块,就要对X定义下采样函数,使之shape相同 if 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用于顺序储存各连续残差块 # 每个残差结构,第一个残差块均为需要对X下采样的残差块,后面的残差块不需要对X下采样 layers = [] # 添加第一个残差块,第一个残差块均为需要对X下采样的残差块 layers.append(block(self.in_channel, channel, downsample=downsample, stride=stride, groups=self.groups, width_per_group=self.width_per_group)) self.in_channel = channel * block.expansion # 后面的残差块不需要对X下采样 for _ in range(1, block_num): layers.append(block(self.in_channel, channel, groups=self.groups, width_per_group=self.width_per_group)) # 以非关键字参数形式,将layers列表,传入Sequential(),使其中残差块串联为一个残差结构 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: # 一般为True x = self.avgpool(x) x = torch.flatten(x, 1) x = self.fc(x) return x# 至此resnet的基本框架就写好了# ——————————————————————————————————————————————————————————————————————————————————# 下面定义不同层的resnetdef resnet50(num_classes=1000, include_top=True): # https://download.pytorch.org/models/resnet50-19c8e357.pth return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet34(num_classes=1000, include_top=True): # https://download.pytorch.org/models/resnet34-333f7ec4.pth return ResNet(BasicBlock, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top)def resnet101(num_classes=1000, include_top=True): # https://download.pytorch.org/models/resnet101-5d3b4d8f.pth return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, include_top=include_top)def resnext50_32x4d(num_classes=1000, include_top=True): # https://download.pytorch.org/models/resnext50_32x4d-7cdf4587.pth groups = 32 width_per_group = 4 return ResNet(Bottleneck, [3, 4, 6, 3], num_classes=num_classes, include_top=include_top, groups=groups, width_per_group=width_per_group)def resnext101_32x8d(num_classes=1000, include_top=True): # https://download.pytorch.org/models/resnext101_32x8d-8ba56ff5.pth groups = 32 width_per_group = 8 return ResNet(Bottleneck, [3, 4, 23, 3], num_classes=num_classes, include_top=include_top, groups=groups, width_per_group=width_per_group)
本文链接地址:https://www.jiuchutong.com/zhishi/300707.html 转载请保留说明!

上一篇:多智能体强化学习—QMIX(多智能体概念)

下一篇:css添加边框阴影(css添加边框阴影 立体效果)

  • 小红书怎么改名字(小红书怎样改名字)

    小红书怎么改名字(小红书怎样改名字)

  • switch输入序号是啥意思

    switch输入序号是啥意思

  • 小米路由器密码忘记了怎么重新设置(小米路由器密码初始密码)

    小米路由器密码忘记了怎么重新设置(小米路由器密码初始密码)

  • 摇骰子怎么摇到自己想要的数字(摇骰子怎么摇到最大)

    摇骰子怎么摇到自己想要的数字(摇骰子怎么摇到最大)

  • 极速退款为什么突然没有了(极速退款为什么不退款)

    极速退款为什么突然没有了(极速退款为什么不退款)

  • 删除好友再加回来对方知道吗(删除好友再加回来看不到朋友圈)

    删除好友再加回来对方知道吗(删除好友再加回来看不到朋友圈)

  • 苹果xr有缝隙正常吗(苹果xr手机屏幕缝隙大)

    苹果xr有缝隙正常吗(苹果xr手机屏幕缝隙大)

  • 静态查找和动态查找的根本区别(静态查找和动态查找的相同点)

    静态查找和动态查找的根本区别(静态查找和动态查找的相同点)

  • 三星a90上市时间(三星a90什么时间上市)

    三星a90上市时间(三星a90什么时间上市)

  • 微信开发者工具打不开(微信开发者工具模拟器启动失败)

    微信开发者工具打不开(微信开发者工具模拟器启动失败)

  • 微信无备份怎么恢复(微信没有备份)

    微信无备份怎么恢复(微信没有备份)

  • 路由器拨号失败是怎么回事(路由器拨号失败是什么原因)

    路由器拨号失败是怎么回事(路由器拨号失败是什么原因)

  • 电脑拨号连接不上怎么办(电脑拨号连接不上怎么办错误629)

    电脑拨号连接不上怎么办(电脑拨号连接不上怎么办错误629)

  • 手机百度被禁止安装程序怎么解除(手机百度被禁止安装应用如何解开权限)

    手机百度被禁止安装程序怎么解除(手机百度被禁止安装应用如何解开权限)

  • ios自动清理缓存(ios自动清除缓存)

    ios自动清理缓存(ios自动清除缓存)

  • iphone11pro怎么返回上一级(iphone11pro怎么返回上一步)

    iphone11pro怎么返回上一级(iphone11pro怎么返回上一步)

  • 苹果xr是什么系列(苹果xr是什么系列手机)

    苹果xr是什么系列(苹果xr是什么系列手机)

  • oppor17多少厘米尺寸(oppor17尺寸是多少?)

    oppor17多少厘米尺寸(oppor17尺寸是多少?)

  • 荣耀20pro是什么解锁(荣耀20PRO是什么扬声器)

    荣耀20pro是什么解锁(荣耀20PRO是什么扬声器)

  • 微信乘车码可以免费换乘么(微信乘车码可以刷几个人)

    微信乘车码可以免费换乘么(微信乘车码可以刷几个人)

  • 苹果11是全面屏吗(苹果11全面屏怎么操作)

    苹果11是全面屏吗(苹果11全面屏怎么操作)

  • 微信头像怎么删除(微信头像怎么删除历史头像)

    微信头像怎么删除(微信头像怎么删除历史头像)

  • 华为平板m5分辨率怎么调(华为平板m5分辨率怎么样)

    华为平板m5分辨率怎么调(华为平板m5分辨率怎么样)

  • 无线鼠标怎么换电池(无线鼠标怎么换一台电脑使用)

    无线鼠标怎么换电池(无线鼠标怎么换一台电脑使用)

  • 蟹爪兰的养殖方法和注意事项(图文)(蟹爪兰的养殖方法和浇水)

    蟹爪兰的养殖方法和注意事项(图文)(蟹爪兰的养殖方法和浇水)

  • 小规模纳税人滚动累计
  • 其他收益是什么类
  • 固定资产十几万可以直接入费用吗
  • 预提利息收入纳税调整
  • 工商年报本期社保怎么填
  • 代办汽车过户手续
  • 应交税费消费税分录
  • 票据利息科目怎么设置
  • 并购重组资产怎么算
  • 并购投资的方式有哪些
  • 预付房租发票未到分录
  • 非居民企业股权转让协议
  • 员工出国补贴标准
  • 企业收取客户利润违法吗
  • 销售产品收取的价款
  • 免税和不免税的价格区别
  • 企业法人个人帐户是什么
  • 企业筹办期间,发生亏损,应该计算为亏损年度
  • 离职补偿金个税计算器2022
  • 外资企业需要遵守哪些法律
  • 增值税是售价乘以税率吗
  • 平销行为如何冲减进项税金
  • 租赁发票多少点
  • 分支机构注销留抵税额可以税前扣除吗?
  • 业务招待费是什么科目
  • 投资收益借贷方向增减
  • system进程有什么用
  • MacOS Big Sur 11.3网页怎么设置时间限制?
  • 差额征税的项目 按差额记账还是全额倒算销项税
  • PHP:eregi_replace()的用法_Regex正则函数
  • PHP:pg_lo_import()的用法_PostgreSQL函数
  • php-fig
  • 房屋租赁经营要交哪些税
  • php多线程curl
  • uni-app 怎么实现页面不跳转依旧可以传数据
  • yarn install报错
  • 企业合并一般债权怎么算
  • 工会经费申报表填写说明
  • linux 运行php
  • electron引入vue
  • 现金报销医药费
  • 长投转可供
  • 金融商品转让的销售额
  • 企业开具劳务费发票怎么开,税率多少
  • 对外捐赠的会计处理企业会计准则和小企业会计准则
  • mongodb主从复制和副本集架构有什么联系和区别
  • 应交税金相关内容包括
  • 金蝶固定资产累计折旧凭证生成
  • mysql 重复记录查询
  • MYSQL5 masterslave数据同步配置方法第1/3页
  • 银行开出的发票可以进行税抵扣吗?
  • 个人如何缴纳公积金和社保费用
  • 小规模纳税人销售自己使用过的物品
  • 本年利润的会计分录怎么写
  • 购买汽车的工本费如何入账
  • 发票验旧后才能领新发票吗
  • 陈列费收取标准
  • 事业单位职工福利费支出范围
  • mysql_info
  • u盘装系统系统资料会被泄露吗
  • win10打开ie8
  • 进程process.acore已停止怎么办
  • win10开机出现microsoft
  • 预装win7旗舰版
  • 安装与配置linux操作系统
  • win10大更新2021要多久
  • win10系统激活后怎么关闭
  • perl 批量注释
  • shell.epc
  • netcfghlp怎么安装
  • js动态加载图片
  • javascript例题
  • node.js使用教程
  • javascript数组去重set方法
  • python怎么写一个类
  • unity接入安卓sdk
  • 绿本补办需要本人去吗
  • 贷款利息扣款日未足额缴纳
  • 公民海外收入纳税
  • 国家税务总局2016年17号公告
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

    网站地图: 企业信息 工商信息 财税知识 网络常识 编程技术

    友情链接: 武汉网站建设