resnet在深度学习领域的重要性不言而喻,自从15年resnet提出后,被各种深度学习模型大量引用。得益于其残差结构的设计,使得深度学习模型可以训练更深层的网络。常见的resnet有resnet18、resnet34、resnet50、resnet101、resnet152几种结构,resnet残差网络由一个卷积块和四个残差块组成,每个残差块包含多个残差结构。从残差结构上看,resnet18和resnet34结构近似,使用相同的残差结构,仅在残差结构数量上有区别,都是使用两个卷积层加一个残差连接层作为残差结构。

resnet18与resnet34的残差结构:

输入特征图x经过两个卷积核大小为3*3的卷积层,使用padding为1的填充保持特征图大小不变,每个卷积层后接BN层和Relu层,完成两次卷积核将结果与输入特征图x直接相加。resnet50到resnet152使用另一种残差结构,这种残差结构使用两个1*1的卷积核加一个3*3的卷积核。

resnet18 resnet34 resnet50 resnet101 resnet152
block1 1*conv 1*conv 1*conv 1*conv 1*conv
block2 2*res(2*conv) 3*res(2*conv) 3*res(3*conv) 3*res(3*conv) 3*res(3*conv)
block3 2*residual(2*conv) 4*res(2*conv) 4*res(3*conv) 4*res(3*conv) 8*res(3*conv)
block4 2*residual(2*conv) 6*res(2*conv) 6*res(3*conv) 23*res(3*conv) 36*res(3*conv)
block5 2*residual(2*conv) 3*res(2*conv) 3*res(3*conv) 3*res(3*conv) 3*res(3*conv)
FN linear linear linear linear linear

resnet18的模型实现:

import torch.nn as nn
from torch.nn import functional as F# 残差单元
class Residual(nn.Module):def __init__(self, input_channel, out_channel, use_conv1x1=False, strides=1):super().__init__()self.conv1 = nn.Conv2d(input_channel, out_channel, kernel_size=3, stride=strides, padding=1)self.conv2 = nn.Conv2d(out_channel, out_channel, kernel_size=3, stride=1, padding=1)if use_conv1x1:self.conv3 = nn.Conv2d(input_channel, out_channel, kernel_size=1, stride=strides)else:self.conv3 = Noneself.bn1 = nn.BatchNorm2d(out_channel)self.bn2 = nn.BatchNorm2d(out_channel)self.relu = nn.ReLU(inplace=True)def forward(self, X):Y = self.relu(self.bn1(self.conv1(X)))Y = self.bn2(self.conv2(Y))if self.conv3:X = self.conv3(X)Y += Xreturn F.relu(Y)# 多个残差单元组成的残差块
def res_block(input_channel, out_channel, num_residuals, first_block=False):blk = []for i in range(num_residuals):if i == 0 and not first_block:blk.append(Residual(input_channel, out_channel, use_conv1x1=True, strides=2))else:blk.append(Residual(out_channel, out_channel))return blkdef resnet18(num_channel, classes):block_1 = nn.Sequential(nn.Conv2d(num_channel, 64, kernel_size=7, stride=2, padding=3),  nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1)  )block_2 = nn.Sequential(*res_block(64, 64, 2, first_block=True))block_3 = nn.Sequential(*res_block(64, 128, 2))block_4 = nn.Sequential(*res_block(128, 256, 2))block_5 = nn.Sequential(*res_block(256, 512, 2))model = nn.Sequential(block_1, block_2, block_3, block_4, block_5,nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(512, classes))return model

resnet34的实现:

def resnet34(classes):b1 = nn.Sequential(nn.Conv2d(3, 64, kernel_size=7, stride=2, padding=3),  # [3,224,224]-->[1,112,112]nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1)  # [1,110,110]-->[1,56,56])b2 = nn.Sequential(*res_block(64, 64, 3, first_block=True))b3 = nn.Sequential(*res_block(64, 128, 4))b4 = nn.Sequential(*res_block(128, 256, 6))b5 = nn.Sequential(*res_block(256, 512, 3))model = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(512, classes))return model

其中残差连接1*1的卷积核,在每个残差块第一个残差结构中对输入特征图使用用于改变输入特征图通道数量,对除第一个残差块之外的其他残差块输入特征图进行特征缩放。当输入图像为[3,224,224],经过第一个卷积层,特征图变为[64,56,56]。由于之前的卷积层和池化层已经进行了两次特征缩放,在设计的时候,在第一个残差块没有对特征图做缩放,也没有改变通道数。之后的每个残差块,都会对特征图进行大小减半,通道加倍,因此在后面三个残差块中,第一个残差单元需要对输入通道进行1*1卷积核加步长为2的操作,以改变特征图大小和通道数,同时对其中第一个卷积层使用步长为2,以保证最后相加时特征图大小和通道数一致。

resnet50模型实现:

import torch
import torch.nn as nn
from torch.nn import functional as F# 残差单元
class Residual(nn.Module):def __init__(self, input_channel, out_channel, use_conv1x1=False, strides=1):super().__init__()self.conv1 = nn.Conv2d(input_channel, int(out_channel / 4), kernel_size=1, stride=strides)self.conv2 = nn.Conv2d(int(out_channel / 4), int(out_channel / 4), kernel_size=3, stride=1, padding=1)self.conv3 = nn.Conv2d(int(out_channel / 4), out_channel, kernel_size=1)if use_conv1x1:self.conv4 = nn.Conv2d(input_channel, out_channel, kernel_size=1, stride=strides)else:self.conv4 = Noneself.bn1 = nn.BatchNorm2d(int(out_channel / 4))self.bn2 = nn.BatchNorm2d(out_channel)self.relu = nn.ReLU(inplace=True)def forward(self, X):Y = self.relu(self.bn1(self.conv1(X)))Y = self.relu(self.bn1(self.conv2(Y)))Y = self.bn2(self.conv3(Y))if self.conv4:X = self.conv4(X)Y += Xreturn F.relu(Y)# 多个残差单元组成的残差块
def res_block(input_channel, out_channel, num_residuals, first_block=False):blk = []for i in range(num_residuals):if i == 0 and not first_block:blk.append(Residual(input_channel, out_channel, use_conv1x1=True, strides=2))input_channel = out_channelif i == 0 and first_block:blk.append(Residual(input_channel, out_channel, use_conv1x1=True, strides=1))input_channel = out_channelelse:blk.append(Residual(input_channel, out_channel))return blkdef resnet50(num_channel, classes):b1 = nn.Sequential(nn.Conv2d(num_channel, 64, kernel_size=7, stride=2, padding=3),nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1))b2 = nn.Sequential(*res_block(64, 256, 3, first_block=True))b3 = nn.Sequential(*res_block(256, 512, 4))b4 = nn.Sequential(*res_block(512, 1024, 6))b5 = nn.Sequential(*res_block(1024, 2048, 3))model = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(2048, classes))return modelnet = resnet50(num_channel=3, classes=2)
x = torch.rand(size=(1, 3, 224, 224), dtype=torch.float32)
for layer in net:print(layer)x = layer(x)print(x.shape)

resnet101实现:

def resnet101(num_channel, classes):b1 = nn.Sequential(nn.Conv2d(num_channel, 64, kernel_size=7, stride=2, padding=3),  # [3,224,224]-->[64,112,112]nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1)  # [1,110,110]-->[1,56,56])b2 = nn.Sequential(*res_block(64, 256, 3, first_block=True))b3 = nn.Sequential(*res_block(256, 512, 4))b4 = nn.Sequential(*res_block(512, 1024, 23))b5 = nn.Sequential(*res_block(1024, 2048, 3))model = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(2048, classes))return model

resnet152实现:

def resnet152(num_channel, classes):b1 = nn.Sequential(nn.Conv2d(num_channel, 64, kernel_size=7, stride=2, padding=3),  # [3,224,224]-->[64,112,112]nn.BatchNorm2d(64),nn.ReLU(),nn.MaxPool2d(kernel_size=3, stride=2, padding=1)  # [64,112,112]-->[64,56,56])b2 = nn.Sequential(*res_block(64, 256, 3, first_block=True))b3 = nn.Sequential(*res_block(256, 512, 8))b4 = nn.Sequential(*res_block(512, 1024, 36))b5 = nn.Sequential(*res_block(1024, 2048, 3))model = nn.Sequential(b1, b2, b3, b4, b5,nn.AdaptiveAvgPool2d((1, 1)),nn.Flatten(),nn.Linear(2048, classes))return model

resnet50之后的网络出了采用3个卷结合,在残差结构内部也有一些区别,在残差结构内第一个卷积层和第二个卷积层输出通道为残差块输出通道的四分之一,并且第一个残差块需要对特征图通道进行变换,那么在代码实现上需要对第一个残差块的第一个残差结构使用1*1卷积核进行输入特征图的通道变换。

resnet18到resnet152模型pytorch实现相关推荐

  1. 通过和resnet18和resnet50理解PyTorch的ResNet模块

    文章目录 模型介绍 resnet18模型流程 总结 resnet50 总结 resnet和resnext的框架基本相同的,这里先学习下resnet的构建,感觉高度模块化,很方便.本文算是对 PyTor ...

  2. DIN模型pytorch代码逐行细讲

    DIN模型pytorch代码逐行细讲 文章目录 DIN模型pytorch代码逐行细讲 一.DIN模型的结构 二.代码介绍 三.导入包 四.导入数据 五.数据处理 六.模型定义 七.封装训练集,测试集 ...

  3. python人脸识别训练模型生产_深度学习-人脸识别DFACE模型pytorch训练(二)

    首先介绍一下MTCNN的网络结构,MTCNN有三种网络,训练网络的时候需要通过三部分分别进行,每一层网络都依赖前一层网络产生训练数据供当前训练网络,这样也推动了两个网络之间的最小损耗. Pnet Rn ...

  4. 轴承故障诊断经典模型pytorch复现(一)——WDCNN

    论文地址:<A New Deep Learning Model for Fault Diagnosis with Good Anti-Noise and Domain Adaptation Ab ...

  5. ResNet18识别CelebA数据集(Pytorch实战)

    文章目录 1.导库 2.获取数据集 自定义数据集 简单查看 创建数据集 3.创建Resnet18模型 简单查看一下网络结构 4.开启训练 训练结果 训练损失和测试损失关系图 训练精度和测试精度关系图 ...

  6. 车牌识别 远距离监控视角 自创简化模型 Pytorch

    甲方一拍脑门,让我去实现车牌识别,还是远距离监控视角的,真开心. 数据?呵~ 不会有人期待甲方提供数据吧?? 先逛逛某宝,一万张车辆图片,0.4元/张. 甲方:阿巴阿巴- 嗯,那没事了. 再逛逛全球同 ...

  7. Seq2Seq模型PyTorch版本

    Seq2Seq模型介绍以及Pytorch版本代码详解 一.Seq2Seq模型的概述 Seq2Seq是一种循环神经网络的变种,是一种端到端的模型,包括 Encoder编码器和 Decoder解码器部分, ...

  8. python调用yolov3模型,pytorch版yolov3训练自己的数据(数据,代码,预训练模型下载链接)...

    1.数据预处理 准备图片数据(JPEGImages),标注文件(Annotations),以及划分好测试集训练集的索引号(ImageSets) 修改代码中voc_label.py文件中的路径以及类别, ...

  9. SRGAN模型——pytorch实现

    论文传送门:https://arxiv.org/pdf/1609.04802.pdf SRGAN模型目的:输入低分辨率图像,生成高分辨率图像. 生成网络由三部分构成: ①卷积+PReLU激活函数: ② ...

最新文章

  1. java scala 混合编程_java与scala混合编程打包(maven构建)
  2. 创建采购申请---BAPI_REQUISITION_CREATE
  3. List接口实现类-ArrayList、Vector、LinkedList集合深入学习以及源代码解析
  4. [HDU 4842]--过河(dp+状态压缩)
  5. 大数据日知录_腾讯T4专家精心整理:java+大数据+机器学习+数据挖掘+算法大集结...
  6. mac 打不开 不受信任_管理不受信任的外键
  7. 【体系结构】Oracle的各种文件及其重要性
  8. 字符编码ASCII ,Unicode ,UTF-8
  9. 公共关系学试题与参考答案
  10. [NLP]OpenNLP介绍
  11. 从GoogLeNet架构到deep dream模型
  12. 深度学习:深度复数网络(Deep Complex Networks)-从论文到pytorch实现
  13. vue项目中实现汉字转拼音缩写
  14. Docker容器运行GUI程序的方法(直接进入Docker容器运行或通过SSH连接Docker容器运行)
  15. 账户结构,推广计划,推广单元
  16. 远程IO模块16DO开关量输出采集远程模块
  17. ln的c语言表达式,c程序中语句中如何表示ln函数?
  18. 正交设计 python算法_Python实现正交实验法-高级篇
  19. 第一步PHP开发环境搭建
  20. 王道2021版计算机考研书勘误表

热门文章

  1. 【已解决】CMake Error: Cannot determine link language for target “xxx“. CMake Error: CMake can not determ
  2. 【解析】1012 The Best Rank (25 分)
  3. 【简洁代码】1071 小赌怡情 (15分)_22行代码
  4. Pytest入门【1】
  5. Spring容器中导入组件方式
  6. (*长期更新)软考网络工程师学习笔记——Section 14 Linux服务器配置
  7. linux shell删除归档_linux打怪技能方向规划,送给迷茫学习的你
  8. 华为交换机配置Telnet步骤
  9. 实验详解——parted单磁盘分区并进行配额
  10. Linux系统安全与应用(一)——账号安全与控制与PAM认证模块