1. 论文阅读与视频学习
1.1 MobileNet
MobileNet 移动端轻量级CNN,大大减少模型参数和运算量
- Depthwise Convolution 大大减少运算量和参数数量
- 增加超参数α(width multiplier) β(resolution multiplier)
DW卷积:卷积核channel=1 输入特征矩阵channel=卷积核个数=输出特征矩阵channel
MobileNet v2
- Inverted Residuals 倒残差结构
- Linear Bottlenecks
1.2 MobileNet V3
更新Block:加入了注意力机制,更新了激活函数
使用NAS搜索参数
重新设计耗时层结构 :减少第一个卷积层的卷积核个数;精简Last Stage
swish激活函数太复杂,更换为h-sigmoid激活函数。
1.3 ShuffleNet
ShuffleNet的核心思想在于通过通道重排改善分组卷积造成的跨组信息流通障碍。
1.4 SENet
Squeeze-and-Excitation Networks (简称SENet)。显式地建模特征通道之间的相互依赖关系。采用了一种全新的“特征重标定”策略。通过学习的方式来自动获取到每个特征通道的重要程度,然后依照这个重要程度去提升有用的特征并抑制对当前任务用处不大的特征。SE 模块可以嵌入到现在几乎所有的网络结构中。如SE-BN-Inception、SE-ResNet、SE-ReNeXt、SE-Inception-ResNet-v2等。
Squeeze 操作,将每个二维的特征通道变成一个实数,这个实数某种程度上具有全局的感受野,并且输出的维度和输入的特征通道数相匹配,使得靠近输入的层也可以获得全局的感受野。
Excitation 操作,通过参数来为每个特征通道生成权重,其中参数被学习用来显式地建模特征通道间的相关性。
Reweight的操作,将Excitation的输出的权重看做是进过特征选择后的每个特征通道的重要性,然后通过乘法逐通道加权到先前的特征上,完成在通道维度上的对原始特征的重标定。
2. 代码作业
##定义 HybridSN 类
class_num = 16
class HybridSN(nn.Module):
def __init__(self, num_classes=16):
super(HybridSN, self).__init__()
# conv1:(1, 30, 25, 25), 8个 7x3x3 的卷积核 ==>(8, 24, 23, 23)
self.conv1 = nn.Conv3d(1, 8, (7, 3, 3))
# conv2:(8, 24, 23, 23), 16个 5x3x3 的卷积核 ==>(16, 20, 21, 21)
self.conv2 = nn.Conv3d(8, 16, (5, 3, 3))
# conv3:(16, 20, 21, 21),32个 3x3x3 的卷积核 ==>(32, 18, 19, 19)
self.conv3 = nn.Conv3d(16, 32, (3, 3, 3))
# conv3_2d (576, 19, 19),64个 3x3 的卷积核 ==>((64, 17, 17)
self.conv3_2d = nn.Conv2d(576, 64, (3,3))
# 全连接层(256个节点)
self.dense1 = nn.Linear(18496,256)
# 全连接层(128个节点)
self.dense2 = nn.Linear(256,128)
# 最终输出层(16个节点)
self.out = nn.Linear(128, num_classes)
self.drop = nn.Dropout(p=0.4)
self.soft = nn.LogSoftmax(dim=1)
# 激活函数ReLU
self.relu = nn.ReLU()
def forward(self, x):
out = self.relu(self.conv1(x))
out = self.relu(self.conv2(out))
out = self.relu(self.conv3(out))
out = out.view(-1, out.shape[1] * out.shape[2], out.shape[3], out.shape[4])
out = self.relu(self.conv3_2d(out))
out = out.view(out.size(0), -1)
out = self.dense1(out)
out = self.drop(out)
out = self.dense2(out)
out = self.drop(out)
out = self.out(out)
out = self.soft(out)
return out
3D卷积就是输入图像的3维,把卷积核改成三维,3D卷积与2D卷积中的多通道卷积相似,但是多了一个depth维度。
3. 思考题
1.训练HybridSN,然后多测试几次,会发现每次分类的结果都不一样,请思考为什么?
应该是Dropout会随机选取不同的节点,每次选取的节点不同,特征学习不同,因此结果不同。
2.如果想要进一步提升高光谱图像的分类性能,可以如何改进?
通过对高光谱图像进行预处理,如去噪、增强对比度和直方图均衡化等,可以提高图像的质量和清晰度,有利于提取更具区分度的特征。
在HybridSN中,可以尝试使用其他激活函数,如LeakyReLU、ReLU-6等,来替代原有的ReLU,以提高模型的性能。
3.depth-wise conv 和 分组卷积有什么区别与联系?
DW卷积在各个输入通道上进行卷积操作,以提取空间特征;然后,逐点卷积通过1×1卷积核将深度上的特征映射到新的特征空间。深度可分离卷积可以有效减少计算量和参数量,对于模型轻量化和节约计算资源非常有用。
分组卷积将输入特征图分割成多个较小的子组,并对每个子组进行独立的卷积操作。这样可以增加网络的宽度和深度,从而提取更多的特征信息。不同的子组可以学习到不同的特征,然后将它们融合在一起,能够更好地表达输入数据的特性,从而提升准确率。
可以看到,DW卷积和分组卷积在实现方式上有一定差异,但它们都是为了减少计算量和参数量,提高模型的效率。
4.SENet 的注意力是不是可以加在空间位置上?
图像上的SENet本质上是计算一种通道权重,CBAM计算了通道权重+空间权重。它包含通道注意力模块和空间注意力模块。
参考链接:cv中Attention的奇妙旅途——讲讲Self-Attention, SENet和CBAM | Hexo
5.在 ShuffleNet 中,通道的 shuffle 如何用代码实现?
# 将通道均匀打乱,111222 -> 121212
def channel_shuffle(x: Tensor, groups: int) -> Tensor:
batchsize, num_channels, height, width = x.size()
channels_per_group = num_channels // groups
# reshape
x = x.view(batchsize, groups, channels_per_group, height, width)
x = torch.transpose(x, 1, 2).contiguous()
# flatten
x = x.view(batchsize, -1, height, width)
return x