当前位置:网站首页>第四周学习 HybridSN,MobileNet V1,V2,V3,SENet
第四周学习 HybridSN,MobileNet V1,V2,V3,SENet
2022-08-03 11:07:00 【_盐焗鸡】
论文及视频学习
MobileNet V1
- 以我的理解,MoblieNetV1的操作就是把普通的卷积分解为两步来做,第一步DW,第二部PW,就相当于把一个333的卷积分为 331的卷积+113的卷积操作。
- 专注于移动端或嵌入式(轻量级)的网络,主要用来在不影响过多性能的情况下减少参数量
- 亮点:
- 提出了Depthwise Convolution
- 增加了超参数α和β:控制参数倍速和
- DW卷积
- 深度可分的卷积:DW卷积、PW卷积
- α:卷积核个数的倍率
- β:卷积的层数


MobileNet V2
- Inverted Residuals 倒残差结构
- 结构相反
- 和传统卷积比,这个先降维再升维
- 更改了激活函数为 RELU6=min(max(x,0),6)
- stride =1且输入输出特征矩阵shape相同时,才有shortcut连接
- 扩展因子?
- 也有α和β

- 结构相反
MobileNet V3
更新block(benck)
- 加入了SE模块:注意力机制:对每个chanel进行pooling处理
- 激活函数的更新:NL:不同层的激活函数不同

使用NAS搜索参数
重新设计耗时层结构
- 减少第一个卷积层的卷积核个数
- 精简Last Stage

SENet
就是通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征。
- Squeeze每个通道压成一个标量,一般可以用下采样
- 再做一个Excitation操作,可以用Fc层来完成
- 在乘到featuremap,作为这层的输出,传给下一层
Squeeze
- 把一个通道压缩成一个标量,比如C×1×1的
- 可以考虑全局的特征

这里面Global pooling是Squeeze 操作,后面是为了减少参数且获得更好的非线性参数
Excitation
通过参数为每个channel生成权重,这里两个FC和sigmoid就算Ex操作
代码
这里的代码就是用SENet的Basicblock替换了原有残差块ResNet18,主要就是在两层的卷积后,加入了
class BasicBlock(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super(BasicBlock, self).__init__()
self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=3, stride=stride, padding=1, bias=False)
self.bn1 = nn.BatchNorm2d(out_channels)
self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=3, stride=1, padding=1, bias=False)
self.bn2 = nn.BatchNorm2d(out_channels)
# shortcut的输出维度和输出不一致时,用1*1的卷积来匹配维度
self.shortcut = nn.Sequential()
if stride != 1 or in_channels != out_channels:
self.shortcut = nn.Sequential(
nn.Conv2d(in_channels, out_channels, kernel_size=1, stride=stride, bias=False),
nn.BatchNorm2d(out_channels))
# 在 excitation 的两个全连接
self.fc1 = nn.Conv2d(out_channels, out_channels//16, kernel_size=1)
self.fc2 = nn.Conv2d(out_channels//16, out_channels, kernel_size=1)
#定义网络结构
def forward(self, x):
#feature map进行两次卷积得到压缩
out = F.relu(self.bn1(self.conv1(x)))
out = self.bn2(self.conv2(out))
# Squeeze 操作:global average pooling
w = F.avg_pool2d(out, out.size(2))
# Excitation 操作: fc(压缩到16分之一)--Relu--fc(激到之前维度)--Sigmoid(保证输出为 0 至 1 之间)
w = F.relu(self.fc1(w))
w = F.sigmoid(self.fc2(w))
# 重标定操作: 将卷积后的feature map与 w 相乘
out = out * w
# 加上浅层特征图
out += self.shortcut(x)
#R elu激活
out = F.relu(out)
return out
这个代码的block基本就是下图结构,使用了Squeeze和Excitation,使得featuremap变为按权重调整后的样子。
对比下ResNet18,也就是未应用SE的模型,大概提高了2个百分点。
代码作业
论文

这篇论文主要介绍了一种新的model,使用3d卷积和2d卷积相结合处理高光谱图像分类问题。
网络的结构和参数图如下 
作者做了一些实验,发现单纯的2d卷积网络或者3d卷积网络,效果都不是很好。最终找到了一个HybridSN模型效果最好,这种模型是把3d卷积和2d卷积混合在一起,主要是考虑了空间光谱和光谱的互补信息。
最终得到一个结论, HybridSN 模型基本上分别以 3D 和 2D 卷积的形式结合了空间光谱和光谱的互补信息,比当时最先进的方法在三个基准数据集上的实验结果都更好。且所提出的模型在计算效率上比 3D-CNN 模型更好,而且只需要少量数据就很好的结果。
代码
class HybridSN(nn.Module):
def __init__(self):
super(HybridSN, self).__init__()
self.conv1 = nn.Sequential(
nn.Conv3d( 1, 8, (7, 3, 3)),
nn.BatchNorm3d(8))
self.conv2 = nn.Sequential(
nn.Conv3d( 8, 16, (5, 3, 3)),
nn.BatchNorm3d(16))
self.conv3 = nn.Sequential(
nn.Conv3d( 16, 32, (3, 3, 3)),
nn.BatchNorm3d(32))
self.conv4 = nn.Sequential(
nn.Conv2d( 576, 64, 3),
nn.BatchNorm2d(64))
self.fc1 = nn.Linear(in_features=18496, out_features=256)
self.fc2 = nn.Linear(in_features=256, out_features=128)
self.fc3 = nn.Linear(in_features=128, out_features=class_num)
self.drop = nn.Dropout(p=0.4)
def forward(self, x):
x = F.relu(self.conv1(x))
x = F.relu(self.conv2(x))
x = F.relu(self.conv3(x))
x = x.reshape(x.shape[0], -1, 19, 19)
x = F.relu(self.conv4(x))
x = x.reshape(x.shape[0],-1)
x = F.relu(self.drop(self.fc1(x)))
x = F.relu(self.drop(self.fc2(x)))
x = self.fc3(x)
return x
跑了100个epoch后,准确率大概在97.3%左右,但是每次的分类结果不一样。
思考题
- 思考3D卷积和2D卷积的区别
A:2d卷积对平面进行运算,而3D一般以空间的形式进行运算。这里面的3D卷积和2D卷积相比,多了一个深度通道,这个深度通道可以获取更多的信息,比如视频的连续帧和立体图像的分割等。比如使用VGG进行视频数据比较,3D版本明显好于2D版本。3D卷积
我觉得这两张图可以很好的解释区别。

- 训练网络,然后多测试几次会发现每次分类的结果都不一样,请思考为什么?
由于fc层使用了dropout,会导致网络节点部分失活,每次的节点是随机的。
而使用了net.eval()代表测试时,batchNorm层,dropout层等用于优化训练而添加的网络层会被关闭,从而使得测试结果不会变化。
net.train()#训练前加
net.eval()#测试前加

可以看到加上之后,结果就一致了,且加上之后预测的结果也更好了。
- 如果想要进一步提升高光谱图像的分类性能,可以如何改进?
我觉得可以利用SENet网络,把SENet模块添加到model中**
这里我去掉了SEnet模块中的残差结构和卷积层,只保留了SE部分,然后把SElayer加入了HybridSN的models里面,放在2d卷积的后面。
class SElayer(nn.Module):
def __init__(self, in_channels, out_channels, stride=1):
super(SElayer, self).__init__()
# 在 excitation 的两个全连接
self.fc1 = nn.Conv2d(out_channels, out_channels//16, kernel_size=1)
self.fc2 = nn.Conv2d(out_channels//16, out_channels, kernel_size=1)
#定义网络结构
def forward(self, x):
# Squeeze 操作:global average pooling
w = F.avg_pool2d(x,x.size(2))
# Excitation 操作: fc(压缩到16分之一)--Relu--fc(激到之前维度)--Sigmoid(保证输出为 0 至 1 之间)
w = F.relu(self.fc1(w))
w = F.sigmoid(self.fc2(w))
out = out * w
#R elu激活
out = F.relu(out)
return out
class HybridSN(nn.Module):
def __init__(self):
super(HybridSN, self).__init__()
self.conv1 = nn.Sequential(
nn.Conv3d( 1, 8, (7, 3, 3)),
nn.BatchNorm3d(8))
self.conv2 = nn.Sequential(
nn.Conv3d( 8, 16, (5, 3, 3)),
nn.BatchNorm3d(16))
self.conv3 = nn.Sequential(
nn.Conv3d( 16, 32, (3, 3, 3)),
nn.BatchNorm3d(32))
self.conv4 = nn.Sequential(
nn.Conv2d( 576, 64, 3),
nn.BatchNorm2d(64))
self.SElayer = SElayer(64,64)
self.fc1 = nn.Linear(in_features=18496, out_features=256)
self.fc2 = nn.Linear(in_features=256, out_features=128)
self.fc3 = nn.Linear(in_features=128, out_features=class_num)
self.drop = nn.Dropout(p=0.4)
def forward(self, x):
x = F.relu(self.conv1(x))
x = F.relu(self.conv2(x))
x = F.relu(self.conv3(x))
x = x.reshape(x.shape[0], -1, 19, 19)
x = F.relu(self.conv4(x))
x = self.SElayer(x)
x = x.reshape(x.shape[0],-1)
x = F.relu(self.drop(self.fc1(x)))
x = F.relu(self.drop(self.fc2(x)))
x = self.fc3(x)
return x
这是变换前后的结果
- 初始结果

- 加入net.eval()

- 加入SE模块

可以看到,初试的准确率是97.3%;加了一个net.eval()和net.train()后达到了98.33%,提升了1%;最后应用SElayer,准确率达到了98.62%,继续提高了0.3%;成功提升了高光谱图像的分类性能。
边栏推荐
- CDH6.3.2开启kerberos认证
- Web Server 设置缓存响应字段的一些推荐方案
- ScrollView嵌套RecyclerView滚动冲突
- Cookie和Session使用
- LeetCode 899 Ordered queue [lexicographical order] HERODING's LeetCode road
- 科普大佬说 | 黑客帝国与6G有什么关系?
- FR9811S6 SOT-23-6 23V, 2A Synchronous Step-Down DC/DC Converter
- Simple implementation of a high-performance clone of Redis using .NET (1)
- 【TypeScript】为什么要选择 TypeScript?
- Who is more popular for hybrid products, depending on technology or market?
猜你喜欢

Analysis of the idea of the complete knapsack problem

用于发票处理的 DocuWare,摆脱纸张和数据输入的束缚,自动处理所有收到的发票

跨链桥协议 Nomad 遭遇黑客攻击,损失超 1.5 亿美元

2022年五面蚂蚁、三面拼多多、字节跳动最终拿offer入职拼多多

Babbitt | Metaverse daily must-read: Players leave, platforms are shut down, and the digital collection market is gradually cooling down. Where is the future of the industry?...

Polymorphism in detail (simple implementation to buy tickets system simulation, covering/weight definition, principle of polymorphism, virtual table)

如何检索IDC研究报告?

87.(cesium之家)cesium热力图(贴地形)
![[LeetCode—Question 2 Sum of Two Numbers Detailed Code Explanation ] The source code is attached, which can be copied directly](/img/19/a3f58d5a1150d99571205a7e2f7345.png)
[LeetCode—Question 2 Sum of Two Numbers Detailed Code Explanation ] The source code is attached, which can be copied directly

基于PHP7.2+MySQL5.7的回收租凭系统
随机推荐
C#/VB.NET 从PDF中提取表格
在 Chrome 开发者工具里通过 network 选项模拟网站的离线访问模式
试题G:单词分析 ← 第十一届蓝桥杯大赛第二场省赛赛题
MySQL数据库实战(1)
Activiti产生的背景和作用
微信多开批处理(自动获取安装路径)
成为优秀架构师必备技能:怎样才能画出让所有人赞不绝口的系统架构图?秘诀是什么?快来打开这篇文章看看吧!...
C - 为什么指针常常初始化为 NULL?
谷歌实用插件分享
Binary search tree (search binary tree) simulation implementation (there is a recursive version)
LyScript implements memory stack scanning
Dva.js 新手入门指南
Cookie和Session使用
微信小程序获取用户手机号码
Advanced use of MySQL database
【MySQL功法】第4话 · 和kiko一起探索MySQL中的运算符
【二分查找详解外加递归写法】附有全部代码
LeetCode——622.设计循环队列
[华为云在线课程][SQL语法入门][学习笔记]
嵌入式软件组件经典架构与存储器分类