位置: 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添加边框阴影 立体效果)

  • 网商银行怎么开通(网商银行怎么开发票)

    网商银行怎么开通(网商银行怎么开发票)

  • 佛山公交车可以微信支付吗(佛山公交车可以用支付宝吗)

    佛山公交车可以微信支付吗(佛山公交车可以用支付宝吗)

  • 抖音如何增加粉丝(抖音如何增加粉丝量和关注度)

    抖音如何增加粉丝(抖音如何增加粉丝量和关注度)

  • 分区类型mbr和gpt有什么区别(分区类型mbr和gui如何选?)

    分区类型mbr和gpt有什么区别(分区类型mbr和gui如何选?)

  • 苹果微信怎么设置视频美颜视频(苹果微信怎么设置来电铃声)

    苹果微信怎么设置视频美颜视频(苹果微信怎么设置来电铃声)

  • mesh和无线桥接的区别(mesh无线组网和无线桥接)

    mesh和无线桥接的区别(mesh无线组网和无线桥接)

  • 电脑放电是什么意思(电脑放电对电脑有什么影响)

    电脑放电是什么意思(电脑放电对电脑有什么影响)

  • excel单元格对齐方式在哪里(excel表格怎么锁定单元格)

    excel单元格对齐方式在哪里(excel表格怎么锁定单元格)

  • xbox one x和s区别(xbox ones和x的区别)

    xbox one x和s区别(xbox ones和x的区别)

  • 为什么我的抖音看不到别人在线(为什么我的抖音没有同城)

    为什么我的抖音看不到别人在线(为什么我的抖音没有同城)

  • 微信好友人数在哪里看(微信好友人数列表)

    微信好友人数在哪里看(微信好友人数列表)

  • qq精选照片栏怎样弄掉(qq精选照片栏怎么不见了)

    qq精选照片栏怎样弄掉(qq精选照片栏怎么不见了)

  • 华为P30pro双卡怎么放(华为p30pro双卡怎么设置网络)

    华为P30pro双卡怎么放(华为p30pro双卡怎么设置网络)

  • 方舟编译器是什么(方舟编译器用处大么)

    方舟编译器是什么(方舟编译器用处大么)

  • 为什么苹果11的微信不会提醒(为什么苹果11的像素那么低)

    为什么苹果11的微信不会提醒(为什么苹果11的像素那么低)

  • vivo手机的ai键是干嘛用的(vivo手机上的ai键是用来干嘛的)

    vivo手机的ai键是干嘛用的(vivo手机上的ai键是用来干嘛的)

  • qq举报几次会封号(qq举报几次会永久封号)

    qq举报几次会封号(qq举报几次会永久封号)

  • 华为mate30怎么返回(mate30怎么把返回键设置出来)

    华为mate30怎么返回(mate30怎么把返回键设置出来)

  • 小米9pro怎么设置通知亮屏(小米9prolhdc怎么设置)

    小米9pro怎么设置通知亮屏(小米9prolhdc怎么设置)

  • mate30pro在哪打开HiCar(华为mate30pro手机功能怎么用)

    mate30pro在哪打开HiCar(华为mate30pro手机功能怎么用)

  • 怎么设置qq通知栏显示(手机消息通知栏在哪里设置)

    怎么设置qq通知栏显示(手机消息通知栏在哪里设置)

  • 抖音里删除的作品能找到吗(抖音里删除的作品还能找回来吗)

    抖音里删除的作品能找到吗(抖音里删除的作品还能找回来吗)

  • pr怎么添加大量字幕(pr视频怎么添加多种视频效果)

    pr怎么添加大量字幕(pr视频怎么添加多种视频效果)

  • 库乐队怎么边弹边录音(怎么用库乐队弹奏)

    库乐队怎么边弹边录音(怎么用库乐队弹奏)

  • launcher什么意思(epiclauncher什么意思)

    launcher什么意思(epiclauncher什么意思)

  • overflow:auto的用法和实现弹性盒横向滚动(overflow常见释义)

    overflow:auto的用法和实现弹性盒横向滚动(overflow常见释义)

  • 大二学生web期末大作业 在线电影网站 HTML+CSS+JS(大二期末要考试吗)

    大二学生web期末大作业 在线电影网站 HTML+CSS+JS(大二期末要考试吗)

  • 盘亏存货进项税额转出的计算公式
  • 公司旧车出售要交什么税
  • 个人出售二手房要交增值税吗
  • 发票开具,发票备注栏能手写字吗?
  • 大盛房地产中介公司
  • 计提个人所得税怎么计提
  • 合同不交印花税合法吗
  • 小规模纳税人认定标准2023
  • 二房东转租需要备案吗
  • 未开票收入下月开票怎么做分录
  • 其他权益工具投资是什么类科目
  • 支付劳务费需要开发票吗
  • 企业购入车辆会计分录
  • 抵减的增值税如何记账
  • 服装租赁开票税目
  • 企业厂房整改应该计入什么科目?
  • 上个月有留抵税这个月怎么结转税金
  • 银行和保险公司归哪个部门管
  • 劳务外包与劳务派遣公司
  • 资本公积金转增资本属于所有者权益吗
  • 周转材料盘点报告单
  • linux禁用root用户
  • 赡养老人支出如果有四个子女都要填吗
  • php实现用户登录
  • php imap函数
  • 土地差价款和土地出让金
  • 供电局销售电力产品
  • 前端埋点sdk
  • php背景图片代码
  • 如何成功安装暗区突围
  • nerf 入门
  • iis搭建网站教程win10
  • apt-show-versions
  • 结转销售成本的方法
  • 固定资产清理的借贷方向表示什么
  • 所得税时间性差异
  • 销售发票重复开库存商品如何处理?
  • 增值税一般纳税人可以开普票吗
  • c 语言 static
  • 普票退货需要开红字信息表吗
  • 科目余额表怎么填
  • 小微企业利润表数据
  • 专利技术资本化
  • 以前年度损益调整属于哪类科目
  • 什么叫总分类账簿
  • 企业收到退回的银行汇票多余款项
  • 期间费用明细表必须填吗
  • 商品买一送一应该怎么写
  • 未开票收入如何申报增值税
  • 为什么到期一次还本付息要用债权投资利息调整
  • 建账选用什么会计制度
  • windows的实验步骤
  • iis7配置asp
  • mac系统照片在哪个文件夹
  • solaris删除文件命令
  • ubuntu18 设置静态ip
  • aow进程
  • win7电脑桌面图标不见了右键也没用
  • win7如何设置屏幕不黑屏
  • win7更新8007000e
  • 外国电影怎么看双语的
  • html截取字符串
  • java怎样学
  • n归档是什么软件
  • js全选和全不选效果复选框
  • unity中ngui
  • js跨域请求有哪些方式
  • python字符串的编码规则
  • php使用js
  • jquery通过id赋值
  • python迭代器iter
  • js遍历table的td
  • javascript原生函数的源代码
  • 浙江省网上税务局app下载
  • 个人所得税中途换了公司 退税
  • 新能源汽车车船税
  • 上市公司的税务风险大吗
  • 登录电子税务局的方式
  • 注册地址和税务登记可以不一致吗
  • 绍兴柯桥有哪些村
  • 免责声明:网站部分图片文字素材来源于网络,如有侵权,请及时告知,我们会第一时间删除,谢谢! 邮箱:opceo@qq.com

    鄂ICP备2023003026号

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

    友情链接: 武汉网站建设