【小白学PyTorch】12.SENet详解及PyTorch实现
<<小白学PyTorch>>
小白学PyTorch | 11 MobileNet详解及PyTorch实现
小白学PyTorch | 10 pytorch常见运算详解
小白学PyTorch | 9 tensor数据结构与存储结构
小白学PyTorch | 8 实战之MNIST小试牛刀
小白学PyTorch | 7 最新版本torchvision.transforms常用API翻译与讲解
小白学PyTorch | 6 模型的构建访问遍历存储(附代码)
小白学PyTorch | 5 torchvision预训练模型与数据集全览
小白学PyTorch | 4 构建模型三要素与权重初始化
小白学PyTorch | 3 浅谈Dataset和Dataloader
小白学PyTorch | 2 浅谈训练集验证集和测试集
小白学PyTorch | 1 搭建一个超简单的网络
小白学PyTorch | 动态图与静态图的浅显理解
参考目录:
1 网络结构
2 参数量分析
3 PyTorch实现与解析
上一节课讲解了MobileNet的一个DSC深度可分离卷积的概念,希望大家可以在实际的任务中使用这种方法,现在再来介绍EfficientNet的另外一个基础知识,Squeeze-and-Excitation Networks压缩-激活网络
1 网络结构
可以看出来,左边的图是一个典型的Resnet的结构,Resnet这个残差结构特征图求和而不是通道拼接,这一点可以注意一下
这个SENet结构式融合在残差网络上的,我来分析一下上图右边的结构:
输出特征图假设shape是的;
一般的Resnet就是这个特征图经过残差网络的基本组块,得到了输出特征图,然后输入特征图和输入特征图通过残差结构连在一起(通过加和的方式连在一起);
SE模块就是输出特征图先经过一个全局池化层,shape从变成了,这个就变成了一个全连接层的输入啦
压缩Squeeze:先放到第一个全连接层里面,输入个元素,输出,r是一个事先设置的参数;
激活Excitation:在接上一个全连接层,输入是个神经元,输出是个元素,实现激活的过程;
现在我们有了一个个元素的经过了两层全连接层的输出,这个C个元素,刚好表示的是原来输出特征图中C个通道的一个权重值,所以我们让C个通道上的像素值分别乘上全连接的C个输出,这个步骤在图中称为Scale。而这个调整过特征图每一个通道权重的特征图是SE-Resnet的输出特征图,之后再考虑残差接连的步骤。
在原文论文中还有另外一个结构图,供大家参考:
2 参数量分析
每一个卷积层都增加了额外的两个全连接层,不够好在全连接层的参数非常小,所以直观来看应该整体不会增加很多的计算量。Resnet50的参数量为25M的大小,增加了SE模块,增加了2.5M的参数量,所以大概增加了10%左右,而且这2.5M的参数主要集中在final stage的se模块,因为在最后一个卷积模块中,特征图拥有最大的通道数,所以这个final stage的参数量占据了增加的2.5M参数的96%。
这里放一个几个网络结构的对比:
3 PyTorch实现与解析
先上完整版的代码,大家可以复制本地IDE跑一跑,如果代码有什么问题可以联系我:
import torch
import torch.nn as nn
import torch.nn.functional as Fclass PreActBlock(nn.Module):def __init__(self, in_planes, planes, stride=1):super(PreActBlock, self).__init__()self.bn1 = nn.BatchNorm2d(in_planes)self.conv1 = nn.Conv2d(in_planes, planes, kernel_size=3, stride=stride, padding=1, bias=False)self.bn2 = nn.BatchNorm2d(planes)self.conv2 = nn.Conv2d(planes, planes, kernel_size=3, stride=1, padding=1, bias=False)if stride != 1 or in_planes != planes:self.shortcut = nn.Sequential(nn.Conv2d(in_planes, planes, kernel_size=1, stride=stride, bias=False))# SE layersself.fc1 = nn.Conv2d(planes, planes//16, kernel_size=1)self.fc2 = nn.Conv2d(planes//16, planes, kernel_size=1)def forward(self, x):out = F.relu(self.bn1(x))shortcut = self.shortcut(out) if hasattr(self, 'shortcut') else xout = self.conv1(out)out = self.conv2(F.relu(self.bn2(out)))# Squeezew = F.avg_pool2d(out, out.size(2))w = F.relu(self.fc1(w))w = F.sigmoid(self.fc2(w))# Excitationout = out * wout += shortcutreturn outclass SENet(nn.Module):def __init__(self, block, num_blocks, num_classes=10):super(SENet, self).__init__()self.in_planes = 64self.conv1 = nn.Conv2d(3, 64, kernel_size=3, stride=1, padding=1, bias=False)self.bn1 = nn.BatchNorm2d(64)self.layer1 = self._make_layer(block, 64, num_blocks[0], stride=1)self.layer2 = self._make_layer(block, 128, num_blocks[1], stride=2)self.layer3 = self._make_layer(block, 256, num_blocks[2], stride=2)self.layer4 = self._make_layer(block, 512, num_blocks[3], stride=2)self.linear = nn.Linear(512, num_classes)def _make_layer(self, block, planes, num_blocks, stride):strides = [stride] + [1]*(num_blocks-1)layers = []for stride in strides:layers.append(block(self.in_planes, planes, stride))self.in_planes = planesreturn nn.Sequential(*layers)def forward(self, x):out = F.relu(self.bn1(self.conv1(x)))out = self.layer1(out)out = self.layer2(out)out = self.layer3(out)out = self.layer4(out)out = F.avg_pool2d(out, 4)out = out.view(out.size(0), -1)out = self.linear(out)return outdef SENet18():return SENet(PreActBlock, [2,2,2,2])net = SENet18()
y = net(torch.randn(1,3,32,32))
print(y.size())
print(net)
输出和注解我都整理了一下:
- END -
往期精彩回顾适合初学者入门人工智能的路线及资料下载机器学习及深度学习笔记等资料打印机器学习在线手册深度学习笔记专辑《统计学习方法》的代码复现专辑
AI基础下载机器学习的数学基础专辑获取一折本站知识星球优惠券,复制链接直接打开:https://t.zsxq.com/662nyZF本站qq群704220115。加入微信群请扫码进群(如果是博士或者准备读博士请说明):
【小白学PyTorch】12.SENet详解及PyTorch实现相关推荐
- 【小白学PyTorch】13.EfficientNet详解及PyTorch实现
<<小白学PyTorch>> 小白学PyTorch | 12 SENet详解及PyTorch实现 小白学PyTorch | 11 MobileNet详解及PyTorch实现 小 ...
- 【小白学PyTorch】10.pytorch常见运算详解
点击上方"小白学视觉",选择加"星标"或"置顶" 重磅干货,第一时间送达 <<小白学PyTorch>> 参考目录: ...
- 3 矩阵运算_小白学PyTorch——pytorch常见运算详解
公众号关注 "DL-CVer" 设为 "星标",DLCV消息即可送达! 参考目录: 1 矩阵与标量 2 哈达玛积 3 矩阵乘法 4 幂与开方 5 对数运算 6 ...
- 【小白学PyTorch】11.MobileNet详解及PyTorch实现
<<小白学PyTorch>> 小白学PyTorch | 10 pytorch常见运算详解 小白学PyTorch | 9 tensor数据结构与存储结构 小白学PyTorch | ...
- 我的世界服务器怎么找到指定路径,[小白]MC服务端目录详解
服务器的前期准备工作都做好了,是时候上传服务端到服务器了.不过--先等等,在上传前你应该先了解一下服务端目录的结构以便于后期的维护! 如图所示的是MCPC+1.6.4的服务端结构示意图,其他开服端基本 ...
- pytorch MSELoss参数详解
pytorch MSELoss参数详解 import torch import numpy as np loss_fn = torch.nn.MSELoss(reduce=False, size_av ...
- Carson带你学Android:图文详解RxJava背压策略
前言 Rxjava,由于其基于事件流的链式调用.逻辑简洁 & 使用简单的特点,深受各大 Android开发者的欢迎. 本文主要讲解的是RxJava中的 背压控制策略,希望你们会喜欢. Cars ...
- Joomla远程代码执行漏洞分析小白版(小宇特详解)
Joomla远程代码执行漏洞分析小白版(小宇特详解) 今天看了一下2021陇原战役WP,在看web方向的时候,看到pop链,想了解一下,后来又看到了p师傅在15年的一篇文章,在这里记录一下.这里主要是 ...
- 我的世界JAVA版有没有混凝土_我的世界1.12混凝土详解 混凝土合成教程
我的世界1.12混凝土详解 混凝土合成教程.我的世界1.12新增加了方块混凝土,今天小编为大家带来了我的世界1.12版新方块混凝土详解和怎样合成的,还不清楚的玩家下面一起来看看吧! 游戏园我的世界官方 ...
最新文章
- java qq ui界面,java UI之QQ登录
- java中 resource_Java从Resource中读取文本文件
- IIS设置Access-Control-Allow-Origin
- linux7为nginx添加服务,CentOS7添加Nginx为系统服务
- java split 坑_java String split 踩坑记
- 比特飞-建站100天感悟
- 窗口缩小 怎么让定位的盒子不动_一次解决你的图像尺寸和定位问题
- 卡尔曼滤波估算车辆质量——matab simulink仿真
- Mysql 声明变量
- 【Restful】你还不懂Restful API规范吗?
- 正则表达式(思维导图速查版)
- centos7安装redies
- Listen1:让你畅听全网音乐,支持多平台
- matlab积分器重置功能,MATLABSIMULINK积分器相关操作.docx
- matlab画基尼系数,matlab 拟合洛伦兹曲线求基尼系数
- 完美解决IIS 服务器无法加载应用程序 '/LM/W3SVC/1/ROOT'。错误是 '没有注册类别
- 关于加强网络舆情监测的几点建议,TOOM强化舆情监控有方法
- 天猫淘宝整合营销 为你的店铺点亮奇迹!
- 计算机英语反思总结怎么写,英语考试反思总结(精选10篇)
- TextView长按复制实现方法小结
热门文章
- 【转】typedef函数指针的用法(C++)
- Grid布局和Flex布局
- 一:(1.4)了解MVC之区域
- css--calc()函数
- 使用iis发布wcf服务
- 2021-08-28 C++职业课程转录博客
- 大数据标签获取处理步骤_大数据处理分为哪些步骤
- 问题 | CSDN编辑图像怎么使图像居中、偏左、偏右
- 一些常规形几何形状的绘制和效果填充(一)
- CreateThread()与beginthread()的区别详细解析