昨天差不多八点四十五才开始玩游戏,我感觉学习效率提高了很多,我睡觉也早了点。
我昨天看了一下卷积的代码,我感觉那个代码很粗糙,学习率我调来调去,准确率最高才69%,甚至准确率会下降到60%。
我今天跑这个注意力的代码,听说它的效果会很好,就是这个加的注意力模块我有点听不懂
2
其实我现在蛮想打游戏的。可是我知道我离我的目标太远太远了。我想在研二达到毕业要求,然后研三考上事业编。如果我不努力学习,我就达不到这个目标,然后我毕业就会去送外卖当保安,然后我就变成小丑了,学习了这么多年,结果一事无成。所以我还能打游戏吗。学习吧,没有翅膀的孩子只能努力奔跑不是吗。
如果人生可以重来,我不会来上学,我会去当一个混吃等死的保安。
3
# 通道注意力模块
class ChannelAttention(nn.Module):
def __init__(self, in_channels, ratio=16):
super().__init__()
self.avg_pool = nn.AdaptiveAvgPool2d(1)
self.max_pool = nn.AdaptiveMaxPool2d(1)
self.fc = nn.Sequential(
nn.Linear(in_channels, in_channels // ratio),
nn.ReLU(),
nn.Linear(in_channels // ratio, in_channels),
nn.Sigmoid()
)
def forward(self, x):
avg_out = self.fc(self.avg_pool(x).view(x.size(0), -1))
max_out = self.fc(self.max_pool(x).view(x.size(0), -1))
return x * (avg_out + max_out).unsqueeze(2).unsqueeze(3)
针对这个通道注意力模块,我提出第一个问题,为什么要计算平均池化和最大池化。
我研究了一会,计算平均池化和最大池化的目的是为了更好的提取图片的信息,提高模型的准确率。从多方面提取图片的信息,有句话怎么说来着,兼听则明。
那我有第二个问题nn.Linear到底是干嘛的,最简单的理解,降维的,比如我输入两个参数a和b,aw1+bw2=c,这样就把两维降为一维。那么问题自然就来了,权重矩阵和偏置矩阵是从哪来的呢,自动生成的,或者全局平均池化或者全局最大池化就是为了这个。
4
# 基础卷积块
class ConvBlock(nn.Module):
def __init__(self, in_ch, out_ch):
super().__init__()
self.conv = nn.Sequential(
nn.Conv2d(in_ch, out_ch, 3, padding=1),
nn.BatchNorm2d(out_ch),
nn.ReLU(),
nn.MaxPool2d(2)
)
self.ca = ChannelAttention(out_ch)
def forward(self, x):
x = self.conv(x)
return self.ca(x)
前面那个注意力机制我看得有点眉目了,我现在看看它是怎么把注意力机制和卷积块融合到一块去的。
我现在可以理解卷积了,卷积核是随机生成的,不同的卷积核提取不同的特征,这样就能得出不同的模型,至于padding=1,则是因为对于一个33的卷积核来说,如果原张量也是33的,那么很显然,只能得到11的张量,所以要在边缘上加上一层,变成一个55的张量。这样用卷积核进行卷积之后就得到了3*3的结果,维度没有发生变化。边缘信息也得到提取了。
nn.MaxPool2d(2)
这个代码的作用是进行池化,我觉得主要是减少运算量吧。
5
# 完整网络
class AttentionCNN(nn.Module):
def __init__(self):
super().__init__()
self.net = nn.Sequential(
ConvBlock(3, 64),
ConvBlock(64, 128),
ConvBlock(128, 256),
nn.AdaptiveAvgPool2d(1),
nn.Flatten(),
nn.Linear(256, 10)
)
def forward(self, x):
return self.net(x)
这个代码最麻烦的地方在于它是一个复合代码,所以它函数层层调用给我调晕了。
我其实不理解为什么卷积层一定要归一化。我觉得这个通道注意力模块还是有点不太理解
ConvBlock(3, 64)
Convolution是卷积的意思,它就是调用我们的卷积函数嘛,输入3维,输出64维。为什么输入是3维,因为CIFAR10是图片数据集,所以一张图片可以看成是一个三维数组,3维的色彩向量,32*32的像素点。
其实卷积那块我看懂了,3维的输入64维的输出,无非就是64个卷积核嘛。就是后面注意力机制那一块,我没看懂
Input: [128,3,32,32]
↓
Conv2d: [128,64,32,32] # 通道扩展
↓
MaxPool:[128,64,16,16] # 分辨率减半
↓
CA模块: [128,64,16,16] # 通道加权
在CA模块里面,为什么要把64维降到4维,激活之后再升到64维?
nn.Linear(in_channels, in_channels // ratio),
nn.ReLU(),
nn.Linear(in_channels // ratio, in_channels),
我问了一下deepseek,答案是降低了运算量。
如果不降维的话,那就是6464+64(最后这个64是偏置矩阵)=4096
而经过压缩之后,644+4=260,4*64+64=320,总共加起来也不过是个580,直接下降了一个量级,而且我问了deepseek之后它告诉我,科学的参数压缩效果很好。
我差不多了解了,这个注意力模块就是对卷积生成的张量对它进行了处理,有了新的权重矩阵。这个新的权重矩阵则是由全局池化和局部池化得来的。