PyTorch 实现经典模型5:ResNet
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=w1x+x。
残差网络
两个简单的设计原则:
- 具有相同输出特征图大小的网络卷积层卷积核数量相同;
- 特征图大小减半,则卷积数量增加一倍,保证时间复杂度。
基于普通网络,插入跳跃连接。
维度增加时,增加零输出,或 1x1 卷积改变维度。
Ref
- Pytorch学习(三)–用50行代码搭建ResNet
- Pytorch实战2:ResNet-18实现Cifar-10图像分类(测试集分类准确率95.170%)
PyTorch 实现经典模型5:ResNet相关推荐
- PyTorch 实现经典模型3:VGG
VGG 网络结构 代码 1) 导入必需的包 # 1) 导入必需的包 import torch import torch.nn as nn import torch.nn.functional as F ...
- PyTorch 实现经典模型2:AlexNet
AlexNet 网络结构 论文总结 成功使用ReLU作为CNN的激活函数,并验证效果在较深的网络中超过了Sigmoid.成功解决了Sigmoid在网络较深时的梯度弥散问题. 训练时使用Dropout随 ...
- PyTorch 实现经典模型6:RCNN (Fast RCNN, Faster RCNN)
RCNN (Fast RCNN, Faster RCNN) 适用范围 图像分类(Image classification) 目标检测(Object detection) 网络结构 代码 Ref R-C ...
- PyTorch 实现经典模型4:GoogLeNet
GoogLeNet 创新点: 通过多种卷积核叠加网络复杂性 学习多种卷积 提升计算效率 GoogLeNet网络深度达到22层 1x1卷积降低维度 降低计算量,提升计算效率 网络结构 代码 import ...
- PyTorch 实现经典模型1:LeNet5
模型:LeNet5 网络结构 符号说明 网络参数 代码实现 1) 导入必需的包 2) 搭建网络模型 3) 导入使用的数据集 4) 训练模型 5) 保存模型 6) 测试模型效果 所遇错误 '_Incom ...
- PyTorch 实现经典模型8:FCN
FCN 网络结构 代码 class fcn(nn.Module):def __init__(self, num_classes):super(fcn, self).__init__()self.sta ...
- PyTorch 实现经典模型7:YOLO (v1, v2, v3, v4)
YOLO (v1, v2, v3, v4) 网络结构 YOLO v3 网络结构 代码 Ref <机器爱学习>YOLO v1深入理解 <机器爱学习>YOLOv2 / YOLO90 ...
- PyTorch Hub发布获Yann LeCun强推!一行代码调用经典模型
作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 导读:6月11日,Facebook PyTorch 团队推出了全 ...
- Facebook 发布 PyTorch Hub:一行代码实现经典模型调用!
作者 | Team PyTorch 译者 | Monanfei 责编 | 夕颜 出品 | AI科技大本营(ID: rgznai100) 6月11日,Facebook PyTorch 团队推出了全新 A ...
最新文章
- [C++基础]034_C++模板编程里的主版本模板类、全特化、偏特化(C++ Type Traits)
- Redis:17---常用功能之(事务)
- phpcmsV9重装 - 踩坑篇
- 带你尝鲜LiteOS 组件EasyFlash
- spring mvc后端代码实现弹出对话框_伟源|一图搞定Spring框架
- 099 元类( 控制对象产生和控制类产生)模板
- 目标跟踪经典论文阅读(1)MOSSE
- XP Mod Android6,手机瞬间变电脑 主题软件XP MOD有惊喜
- 大数据安全国内外技术发展现状与趋势现状
- 计算机一级大学生一定要考吗,关于大学大学生要考计算机一级吗
- tree traversal (树的遍历) - postorder traversal (后序遍历)
- 开关电源-反激+单级PFC超低纹波超低THD
- 【uView】picker 地区选择
- GStreamer插件实列rockchipmpp
- OTA自动化测试解决方案
- 【QT项目:视频播放器——Qt opengl编程】通过shader完成显示yuv
- linux c编程文件枷锁
- Python 计算 瑞幸和星巴克 谁的门店最多
- pandas入门(6)——数据加载、存储与文件格式
- 微信公众号-开发相关信息了解