注意力机制——Self-Attention Networks(SANet)

自注意力机制(self-attention)是一种基于注意力机制的神经网络模型,主要用于自然语言处理任务中。它在Transformer模型中被广泛使用,能够对输入序列中的每个元素计算其与其他元素之间的关系,并使用这些关系来更好地表示输入序列。

在自注意力机制中,每个元素都是一个向量表示,例如,在语言处理中,可以将每个单词的嵌入向量作为输入序列中的元素。然后,为了计算每个元素与其他元素之间的关系,自注意力机制引入了三个矩阵:查询矩阵(query matrix)、键矩阵(key matrix)和值矩阵(value matrix)。这些矩阵可以通过线性变换从输入序列中的每个元素中提取出特征。

用pytorch实现self-attention:

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

class SelfAttention(nn.Module):
    def __init__(self, input_size, hidden_size):
        super(SelfAttention, self).__init__()
        
        self.query = nn.Linear(input_size, hidden_size)
        self.key = nn.Linear(input_size, hidden_size)
        self.value = nn.Linear(input_size, hidden_size)
        
    def forward(self, x):
        # 计算Q、K、V
        q = self.query(x)
        k = self.key(x)
        v = self.value(x)
        
        # 计算Self-Attention矩阵
        attn_weights = torch.bmm(q, k.transpose(1, 2))
        attn_weights = F.softmax(attn_weights, dim=-1)
        
        # 使用Self-Attention矩阵对V进行加权平均
        attn_output = torch.bmm(attn_weights, v)
        
        return attn_output

在上面的代码中,我们定义了一个SelfAttention类,该类继承自nn.Module。在__init__()函数中,我们定义了querykeyvalue三个线性层,分别用于计算查询、键和值的向量。在forward()函数中,我们首先计算qkv向量,然后使用torch.bmm()函数计算Self-Attention矩阵,并使用F.softmax()函数对Self-Attention矩阵进行归一化。最后,我们使用torch.bmm()函数将Self-Attention矩阵与值向量v进行矩阵乘积,并返回加权平均后的输出。

可以使用以下代码创建一个SelfAttention实例并进行测试:

input_size = 128
hidden_size = 64
batch_size = 32
seq_len = 10

sa = SelfAttention(input_size, hidden_size)

x = torch.randn(batch_size, seq_len, input_size)
output = sa(x)

print(output.size())  # 输出:torch.Size([32, 10, 64])

在上面的代码中,我们创建了一个SelfAttention实例,并使用torch.randn()函数生成一个随机输入张量x,张量的大小为(32, 10, 128),其中32是批量大小,10是序列长度,128是特征维数。最后,我们将x传递给sa实例,并将输出存储在output张量中。我们打印output的大小,以确保输出大小与预期相同。

self-attention在网络中实现:

import torch
import torch.nn as nn

class MyModel(nn.Module):
    def __init__(self, input_size, hidden_size, num_classes):
        super(MyModel, self).__init__()
        
        # 定义Self-Attention模块
        self.self_attn = nn.MultiheadAttention(hidden_size, num_heads=8)
        
        # 定义前向神经网络
        self.fc1 = nn.Linear(input_size, hidden_size)
        self.relu = nn.ReLU()
        self.fc2 = nn.Linear(hidden_size, num_classes)
        
    def forward(self, x):
        # 使用Self-Attention模块进行特征提取
        x, _ = self.self_attn(x, x, x)
        
        # 经过前向神经网络进行分类
        x = self.fc1(x)
        x = self.relu(x)
        x = self.fc2(x)
        
        return x

在上面的代码中,我们定义了一个名为MyModel的神经网络,该网络包含一个Self-Attention模块和一个前向神经网络。在__init__()函数中,我们首先定义了一个nn.MultiheadAttention实例,并将其存储在self.self_attn中。接下来,我们定义了一个前向神经网络,其中包含一个输入层fc1、一个ReLU激活函数和一个输出层fc2。在forward()函数中,我们将输入张量x传递给Self-Attention模块,并使用x作为查询、键和值,以从输入中提取特征。然后,我们使用前向神经网络对特征进行分类,并返回输出张量x

可以使用以下代码创建一个MyModel实例并进行测试:

input_size = 128
hidden_size = 64
num_classes = 10
batch_size = 32
seq_len = 10

model = MyModel(input_size, hidden_size, num_classes)

x = torch.randn(seq_len, batch_size, input_size)
output = model(x)

print(output.size())  # 输出:torch.Size([10, 32, 10])

在上面的代码中,我们创建了一个MyModel实例,并使用torch.randn()函数生成一个随机输入张量x,张量的大小为(10, 32, 128),其中10是序列长度,32是批量大小,128是特征维数。最后,我们将x传递给model实例,并将输出存储在output张量中。我们打印output的大小,以确保输出大小与预期相同。

猜你喜欢

转载自blog.csdn.net/weixin_50752408/article/details/129587866