【深度学习中的注意力机制4】11种主流注意力机制112个创新研究paper+代码——时序注意力(Stride Attention)

【深度学习中的注意力机制4】11种主流注意力机制112个创新研究paper+代码——时序注意力(Stride Attention)

【深度学习中的注意力机制4】11种主流注意力机制112个创新研究paper+代码——时序注意力(Stride Attention)



1. 起源与提出

时序注意力(Temporal Attention)是为处理时序数据提出的一种注意力机制,最早出现在与序列数据相关的任务中,例如自然语言处理、时间序列预测、视频分析等。传统的序列模型,如RNN、LSTM、GRU等,虽然能够捕捉时序数据中的依赖关系,但在处理长序列时容易出现梯度消失和长期依赖问题。此外,这些模型通常会对序列中的每一个时间步一视同仁,无法对不同时间步的重要性进行有效建模。

为了缓解这些问题,时序注意力机制被提出,旨在通过加权机制来选择性地关注序列中的重要时间步。它能够根据序列中不同时间步的特征,动态地调整注意力权重,从而聚焦于对任务最为关键的部分。时序注意力的出现让序列模型在处理长序列时更加灵活,也改善了模型在长期依赖问题上的表现。

2. 原理

时序注意力的核心思想是为序列数据中的每一个时间步分配不同的权重,依据这些权重来计算输出。具体来说,时序注意力机制通过计算查询(Query)、键(Key)和值(Value)之间的相似性,确定每个时间步的重要性,并据此加权求和,最终产生输出。

假设我们有一个时序输入序列 X = [ x 1 , x 2 , . . . . x T ] X=[x_1,x_2,....x_T] X=[x1,x2,....xT],其中 T T T 是时间步数,输入维度为 d d d。通过时序注意力机制,我们可以为每个时间步分配一个注意力权重:

  • 查询、键、值:将输入序列映射为查询 Q Q Q、键 K K K 和值 V V V
  • 注意力权重:通过查询和键的点积,得到时间步之间的相似度,然后通过 softmax 归一化得到注意力权重。
  • 加权求和:使用注意力权重对值 V V V 进行加权求和,得到加权后的输出序列。

具体步骤如下:

  • 查询(Q):代表当前时间步的信息。
  • 键(K):代表每个时间步的特征向量。
  • 值(V):代表每个时间步的输出。

时序注意力的关键是利用查询和键的点积来衡量不同时间步之间的相似性,并通过 softmax 函数归一化得到每个时间步的权重,进而对值进行加权求和,生成最终输出。

3. 发展

时序注意力是自注意力机制的一种扩展,逐渐被应用于各种需要处理时序数据的领域,包括:

  • 自然语言处理:如机器翻译、文本摘要生成等任务中,时序注意力机制帮助模型更好地理解句子中各个单词的重要性。
  • 时间序列预测:在金融、气象、能源等领域,时序注意力能够捕捉到时间序列中的长期依赖关系。
  • 视频分析:视频中的每一帧都可以被看作一个时间步,时序注意力能够帮助模型选择性地关注重要的帧,忽略不相关的部分。

近年来,基于Transformer的模型大幅度推动了时序注意力的应用。例如,TimeSformer模型在视频分类中就使用了时序注意力来处理时序关系。

4. 代码实现

下面是一个基于时序注意力机制的简化实现,使用PyTorch框架来演示如何处理时序数据。

import torch
import torch.nn as nn
import torch.nn.functional as F

class TemporalAttention(nn.Module):
    def __init__(self, d_model):
        super(TemporalAttention, self).__init__()
        self.d_model = d_model  # 输入特征的维度
        
        # 查询、键、值的线性层
        self.wq = nn.Linear(d_model, d_model)
        self.wk = nn.Linear(d_model, d_model)
        self.wv = nn.Linear(d_model, d_model)
        
        # 最终输出的线性层
        self.fc = nn.Linear(d_model, d_model)
    
    def forward(self, x):
        # 输入 x: [batch_size, seq_len, d_model]
        batch_size, seq_len, d_model = x.shape
        
        # 计算查询Q、键K、值V
        Q = self.wq(x)  # [batch_size, seq_len, d_model]
        K = self.wk(x)  # [batch_size, seq_len, d_model]
        V = self.wv(x)  # [batch_size, seq_len, d_model]
        
        # 计算注意力分数: Q与K的点积, 然后除以sqrt(d_model)
        attention_scores = torch.matmul(Q, K.transpose(-2, -1)) / torch.sqrt(torch.tensor(d_model, dtype=torch.float32))
        
        # 使用softmax进行归一化处理,得到注意力权重
        attention_weights = F.softmax(attention_scores, dim=-1)  # [batch_size, seq_len, seq_len]
        
        # 使用注意力权重对V进行加权求和
        attention_output = torch.matmul(attention_weights, V)  # [batch_size, seq_len, d_model]
        
        # 通过输出线性层
        output = self.fc(attention_output)  # [batch_size, seq_len, d_model]
        
        return output, attention_weights

# 示例使用
batch_size = 2
seq_len = 10
d_model = 16

# 随机初始化输入
x = torch.rand(batch_size, seq_len, d_model)

# 实例化时序注意力层
temporal_attention_layer = TemporalAttention(d_model)
output, attention_weights = temporal_attention_layer(x)

print("输出:", output)
print("注意力权重:", attention_weights)

5. 代码逐句解释

1. 导入库:

import torch
import torch.nn as nn
import torch.nn.functional as F

导入PyTorch库,其中nn用于构建神经网络层,F用于一些常用的函数,如softmax

2. class TemporalAttention(nn.Module): 定义时序注意力类,继承自torch.nn.Module。该类包含了时序注意力机制的所有步骤。

3. __init__(self, d_model): 初始化时序注意力层:

  • d_model:输入特征的维度。
  • 定义了用于生成查询(Q)、键(K)和值(V)的线性层 wqwkwv
  • 最后定义了一个输出线性层 fc,将注意力输出映射回输入维度。

4. forward(self, x): 前向传播函数:

  • 输入 x 的形状为 [batch_size, seq_len, d_model],其中 seq_len 是时间步的数量,d_model 是特征维度。

  • 线性变换Q, K, V: 将输入 x 通过线性层映射为查询 Q、键 K 和值 V,形状均为 [batch_size, seq_len,d_model]

  • 计算注意力分数: 通过查询 Q 和键 K 的点积来计算注意力分数。为了防止数值过大,除以 d − m o d e l \sqrt{d-model} dmodel 进行缩放。

  • softmax归一化: 使用 softmax 函数对注意力分数进行归一化,得到每个时间步的注意力权重。

  • 加权求和: 使用注意力权重对值 V 进行加权求和,得到注意力输出。

  • 输出层: 通过线性层 self.fc 将注意力输出映射回输入维度。

5. 示例使用:

  • 随机初始化输入张量 x,形状为 [batch_size, seq_len, d_model]

  • 实例化时序注意力层,并通过 temporal_attention_layer(x) 进行前向传播,输出包括注意力输出和注意力权重。

6. 总结

时序注意力通过对序列数据中每个时间步进行加权,使模型能够根据任务需求动态关注不同的时间步。这种机制极大地增强了序列模型在处理长依赖任务中的表现,并在自然语言处理、时间序列预测和视频分析等领域得到了广泛应用。

好的,以下是一个将注意力机制加到CNN网络中的实例代码,使用的数据集为CIFAR-10。 ```python import torch import torch.nn as nn import torch.nn.functional as F import torch.optim as optim import torchvision import torchvision.transforms as transforms # 定义注意力机制 class Attention(nn.Module): def __init__(self, in_channels, out_channels, kernel_size=1): super(Attention, self).__init__() self.conv1 = nn.Conv2d(in_channels, out_channels, kernel_size=kernel_size, stride=1, padding=0, bias=False) self.conv2 = nn.Conv2d(out_channels, out_channels, kernel_size=kernel_size, stride=1, padding=0, bias=False) self.conv3 = nn.Conv2d(out_channels, out_channels, kernel_size=kernel_size, stride=1, padding=0, bias=False) self.bn1 = nn.BatchNorm2d(out_channels) self.bn2 = nn.BatchNorm2d(out_channels) self.bn3 = nn.BatchNorm2d(out_channels) self.relu = nn.ReLU(inplace=True) def forward(self, x): residual = x out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.conv3(out) out = self.bn3(out) out += residual out = self.relu(out) return out # 定义CNN网络 class CNN(nn.Module): def __init__(self): super(CNN, self).__init__() self.conv1 = nn.Conv2d(3, 64, 3, stride=1, padding=1, bias=False) self.bn1 = nn.BatchNorm2d(64) self.relu = nn.ReLU(inplace=True) self.attention1 = Attention(64, 64) self.pool1 = nn.MaxPool2d(2, 2) self.conv2 = nn.Conv2d(64, 128, 3, stride=1, padding=1, bias=False) self.bn2 = nn.BatchNorm2d(128) self.attention2 = Attention(128, 128) self.pool2 = nn.MaxPool2d(2, 2) self.conv3 = nn.Conv2d(128, 256, 3, stride=1, padding=1, bias=False) self.bn3 = nn.BatchNorm2d(256) self.attention3 = Attention(256, 256) self.pool3 = nn.MaxPool2d(2, 2) self.fc = nn.Linear(256 * 4 * 4, 10) def forward(self, x): out = self.conv1(x) out = self.bn1(out) out = self.relu(out) out = self.attention1(out) out = self.pool1(out) out = self.conv2(out) out = self.bn2(out) out = self.relu(out) out = self.attention2(out) out = self.pool2(out) out = self.conv3(out) out = self.bn3(out) out = self.relu(out) out = self.attention3(out) out = self.pool3(out) out = out.view(-1, 256 * 4 * 4) out = self.fc(out) return out # 加载数据集 transform_train = transforms.Compose([ transforms.RandomCrop(32, padding=4), transforms.RandomHorizontalFlip(), transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) transform_test = transforms.Compose([ transforms.ToTensor(), transforms.Normalize((0.5, 0.5, 0.5), (0.5, 0.5, 0.5)) ]) trainset = torchvision.datasets.CIFAR10(root='./data', train=True, download=True, transform=transform_train) trainloader = torch.utils.data.DataLoader(trainset, batch_size=128, shuffle=True, num_workers=2) testset = torchvision.datasets.CIFAR10(root='./data', train=False, download=True, transform=transform_test) testloader = torch.utils.data.DataLoader(testset, batch_size=128, shuffle=False, num_workers=2) # 定义损失函数和优化器 criterion = nn.CrossEntropyLoss() optimizer = optim.SGD(net.parameters(), lr=0.1, momentum=0.9, weight_decay=5e-4) # 训练网络 net = CNN() device = torch.device("cuda:0" if torch.cuda.is_available() else "cpu") net.to(device) for epoch in range(100): running_loss = 0.0 for i, data in enumerate(trainloader, 0): inputs, labels = data inputs, labels = inputs.to(device), labels.to(device) optimizer.zero_grad() outputs = net(inputs) loss = criterion(outputs, labels) loss.backward() optimizer.step() running_loss += loss.item() if i % 100 == 99: print('[%d, %5d] loss: %.3f' % (epoch + 1, i + 1, running_loss / 100)) running_loss = 0.0 print('Finished Training') ``` 在这个CNN网络中,我们使用了三个注意力机制,分别应用于三个卷积层。在每个卷积层的输出和输入加和时应用注意力机制,以增强网络对重要信息的关注。 请注意,这只是一个简单的示例,实际应用中,注意力机制的设计需要根据具体问题进行调整。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

985小水博一枚呀

祝各位老板前程似锦!财源滚滚!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值