ResNet

网络结构


代码

#------------------------------用50行代码搭建ResNet-------------------------------------------
from torch import nn
import torch as t
from torch.nn import functional as Fclass ResidualBlock(nn.Module):#实现子module: Residual    Blockdef __init__(self,inchannel,outchannel,stride=1,shortcut=None):super(ResidualBlock,self).__init__()self.left=nn.Sequential(nn.Conv2d(inchannel,outchannel,3,stride,1,bias=False),nn.BatchNorm2d(outchannel),nn.ReLU(inplace=True),nn.Conv2d(outchannel,outchannel,3,1,1,bias=False),nn.BatchNorm2d(outchannel))self.right=shortcutdef forward(self,x):out=self.left(x)residual=x if self.right is None else self.right(x)out+=residualreturn F.relu(out)class ResNet(nn.Module):#实现主module:ResNet34#ResNet34包含多个layer,每个layer又包含多个residual block#用子module实现residual block , 用 _make_layer 函数实现layerdef __init__(self,num_classes=1000):super(ResNet,self).__init__()self.pre=nn.Sequential(nn.Conv2d(3,64,7,2,3,bias=False),nn.BatchNorm2d(64),nn.ReLU(inplace=True),nn.MaxPool2d(3,2,1))#重复的layer,分别有3,4,6,3个residual blockself.layer1=self._make_layer(64,64,3)self.layer2=self._make_layer(64,128,4,stride=2)self.layer3=self._make_layer(128,256,6,stride=2)self.layer4=self._make_layer(256,512,3,stride=2)#分类用的全连接self.fc=nn.Linear(512,num_classes)def _make_layer(self,inchannel,outchannel,block_num,stride=1):#构建layer,包含多个residual blockshortcut=nn.Sequential(nn.Conv2d(inchannel,outchannel,1,stride,bias=False),nn.BatchNorm2d(outchannel))layers=[ ]layers.append(ResidualBlock(inchannel,outchannel,stride,shortcut))for i in range(1,block_num):layers.append(ResidualBlock(outchannel,outchannel))return nn.Sequential(*layers)def forward(self,x):x=self.pre(x)x=self.layer1(x)x=self.layer2(x)x=self.layer3(x)x=self.layer4(x)x=F.avg_pool2d(x,7)x=x.view(x.size(0),-1)return self.fc(x)resnet = ResNet()
print(resnet)

输出结果如下:

ResNet((pre): Sequential((0): Conv2d(3, 64, kernel_size=(7, 7), stride=(2, 2), padding=(3, 3), bias=False)(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): MaxPool2d(kernel_size=3, stride=2, padding=1, dilation=1, ceil_mode=False))(layer1): Sequential((0): ResidualBlock((left): Sequential((0): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(right): Sequential((0): Conv2d(64, 64, kernel_size=(1, 1), stride=(1, 1), bias=False)(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((left): Sequential((0): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(2): ResidualBlock((left): Sequential((0): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(64, 64, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(64, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(layer2): Sequential((0): ResidualBlock((left): Sequential((0): Conv2d(64, 128, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(right): Sequential((0): Conv2d(64, 128, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((left): Sequential((0): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(2): ResidualBlock((left): Sequential((0): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(3): ResidualBlock((left): Sequential((0): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(128, 128, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(128, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(layer3): Sequential((0): ResidualBlock((left): Sequential((0): Conv2d(128, 256, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(right): Sequential((0): Conv2d(128, 256, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((left): Sequential((0): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(2): ResidualBlock((left): Sequential((0): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(3): ResidualBlock((left): Sequential((0): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(4): ResidualBlock((left): Sequential((0): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(5): ResidualBlock((left): Sequential((0): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(256, 256, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(256, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(layer4): Sequential((0): ResidualBlock((left): Sequential((0): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))(right): Sequential((0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(1): ResidualBlock((left): Sequential((0): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)))(2): ResidualBlock((left): Sequential((0): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)(2): ReLU(inplace=True)(3): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)(4): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True))))(fc): Linear(in_features=512, out_features=1000, bias=True)
)

论文一些注意点

拟合高维

深度神经网络可以拟合高维非线性函数

  • 可以拟合 H(x)H(x)H(x),也可以拟合 H(x)−xH(x)-xH(x)−x。
  • 令 F(x)=H(x)−xF(x)=H(x)-xF(x)=H(x)−x,则 H(x)=F(x)+xH(x)=F(x)+xH(x)=F(x)+x。
  • 网络学习的难易程度不同。
  • 解决梯度消失问题,增加的网络层学习成恒等映射,则不会提升训练误差。
跳层的恒等映射

残差块
y=F(x,{wi})+xy=F(x,\{w_i\})+xy=F(x,{wi​})+x
其中,FFF:需要学习的残差映射,维度与 xxx 一致;F+xF+xF+x:跳跃连接,逐一加和,最后二者的输出经过函数 ReLU;

没有额外参数,不增加复杂度。
FFF 包含两个或两个以上网络层,否则表现为线性层 y=w1x+xy=w_1x+xy=w1​x+x。

残差网络

两个简单的设计原则:

  1. 具有相同输出特征图大小的网络卷积层卷积核数量相同;
  2. 特征图大小减半,则卷积数量增加一倍,保证时间复杂度。

基于普通网络,插入跳跃连接。
维度增加时,增加零输出,或 1x1 卷积改变维度。

Ref

  1. Pytorch学习(三)–用50行代码搭建ResNet
  2. Pytorch实战2:ResNet-18实现Cifar-10图像分类(测试集分类准确率95.170%)

PyTorch 实现经典模型5:ResNet相关推荐

  1. PyTorch 实现经典模型3:VGG

    VGG 网络结构 代码 1) 导入必需的包 # 1) 导入必需的包 import torch import torch.nn as nn import torch.nn.functional as F ...

  2. PyTorch 实现经典模型2:AlexNet

    AlexNet 网络结构 论文总结 成功使用ReLU作为CNN的激活函数,并验证效果在较深的网络中超过了Sigmoid.成功解决了Sigmoid在网络较深时的梯度弥散问题. 训练时使用Dropout随 ...

  3. PyTorch 实现经典模型6:RCNN (Fast RCNN, Faster RCNN)

    RCNN (Fast RCNN, Faster RCNN) 适用范围 图像分类(Image classification) 目标检测(Object detection) 网络结构 代码 Ref R-C ...

  4. PyTorch 实现经典模型4:GoogLeNet

    GoogLeNet 创新点: 通过多种卷积核叠加网络复杂性 学习多种卷积 提升计算效率 GoogLeNet网络深度达到22层 1x1卷积降低维度 降低计算量,提升计算效率 网络结构 代码 import ...

  5. PyTorch 实现经典模型1:LeNet5

    模型:LeNet5 网络结构 符号说明 网络参数 代码实现 1) 导入必需的包 2) 搭建网络模型 3) 导入使用的数据集 4) 训练模型 5) 保存模型 6) 测试模型效果 所遇错误 '_Incom ...

  6. PyTorch 实现经典模型8:FCN

    FCN 网络结构 代码 class fcn(nn.Module):def __init__(self, num_classes):super(fcn, self).__init__()self.sta ...

  7. PyTorch 实现经典模型7:YOLO (v1, v2, v3, v4)

    YOLO (v1, v2, v3, v4) 网络结构 YOLO v3 网络结构 代码 Ref <机器爱学习>YOLO v1深入理解 <机器爱学习>YOLOv2 / YOLO90 ...

  8. PyTorch Hub发布获Yann LeCun强推!一行代码调用经典模型

    作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 导读:6月11日,Facebook PyTorch 团队推出了全 ...

  9. Facebook 发布 PyTorch Hub:一行代码实现经典模型调用!

    作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 6月11日,Facebook PyTorch 团队推出了全新 A ...

最新文章

  1. [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)
  2. Redis:17---常用功能之(事务)
  3. phpcmsV9重装 - 踩坑篇
  4. 带你尝鲜LiteOS 组件EasyFlash
  5. spring mvc后端代码实现弹出对话框_伟源|一图搞定Spring框架
  6. 099 元类( 控制对象产生和控制类产生)模板
  7. 目标跟踪经典论文阅读(1)MOSSE
  8. XP Mod Android6,手机瞬间变电脑 主题软件XP MOD有惊喜
  9. 大数据安全国内外技术发展现状与趋势现状
  10. 计算机一级大学生一定要考吗,关于大学大学生要考计算机一级吗
  11. tree traversal (树的遍历) - postorder traversal (后序遍历)
  12. 开关电源-反激+单级PFC超低纹波超低THD
  13. 【uView】picker 地区选择
  14. GStreamer插件实列rockchipmpp
  15. OTA自动化测试解决方案
  16. 【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv
  17. linux c编程文件枷锁
  18. Python 计算 瑞幸和星巴克 谁的门店最多
  19. pandas入门(6)——数据加载、存储与文件格式
  20. 微信公众号-开发相关信息了解

热门文章

  1. 移动硬盘由于IO设备错误,无法运行此项请求文件怎样恢复
  2. hdu 2191 多重背包
  3. DIV+CSS笔记(一)
  4. 【转】Plotting texts as graphs with R and igraph
  5. 代码中设置excel自定义格式为[红色]的处理方法
  6. 意识到自己的无知这就是进步
  7. python dict sorted
  8. 电动力学每日一题 2021/10/13 用Fourier变换法计算静止电荷产生的电场
  9. R语言 非中心化F分布
  10. 批处理显示是上午还是下午