注意力机制(1)

昨天差不多八点四十五才开始玩游戏,我感觉学习效率提高了很多,我睡觉也早了点。
我昨天看了一下卷积的代码,我感觉那个代码很粗糙,学习率我调来调去,准确率最高才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
而经过压缩之后,64
4+4=260,4*64+64=320,总共加起来也不过是个580,直接下降了一个量级,而且我问了deepseek之后它告诉我,科学的参数压缩效果很好。
我差不多了解了,这个注意力模块就是对卷积生成的张量对它进行了处理,有了新的权重矩阵。这个新的权重矩阵则是由全局池化和局部池化得来的。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值