PyTorch 多头注意力机制实现详解及代码示例
多头注意力机制是一种常用的神经网络结构,主要用于处理序列数据。在该结构中,输入数据经过多个注意力头和线性变换后,得到多个输出结果。这种结构可以提高模型的表达能力,提高模型的性能。
下面是使用 PyTorch 实现多头注意力机制的示例代码:
import torch
import torch.nn as nn
class MultiHeadAttention(nn.Module):
def __init__(self, d_model, n_heads):
super(MultiHeadAttention, self).__init__()
self.d_model = d_model
self.n_heads = n_heads
self.d_k = d_model // n_heads
# 定义线性层
self.query_linear = nn.Linear(d_model, d_model)
self.key_linear = nn.Linear(d_model, d_model)
self.value_linear = nn.Linear(d_model, d_model)
self.out_linear = nn.Linear(d_model, d_model)
def forward(self, x, mask=None):
batch_size = x.size(0)
# 分别对输入数据进行线性变换
query = self.query_linear(x).view(batch_size, -1, self.n_heads, self.d_k).transpose(1,2)
key = self.key_linear(x).view(batch_size, -1, self.n_heads, self.d_k).transpose(1,2)
value = self.value_linear(x).view(batch_size, -1, self.n_heads, self.d_k).transpose(1,2)
# 计算注意力分数
scores = torch.matmul(query, key.transpose(-2, -1)) / torch.sqrt(torch.tensor(self.d_k).float())
if mask is not None:
mask = mask.unsqueeze(1)
scores = scores.masked_fill(mask == 0, -1e9)
attn_weights = nn.functional.softmax(scores, dim=-1)
# 计算注意力输出
attn_output = torch.matmul(attn_weights, value)
attn_output = attn_output.transpose(1, 2).contiguous().view(batch_size, -1, self.d_model)
# 对输出结果进行线性变换
output = self.out_linear(attn_output)
return output, attn_weights
该代码实现了一个 MultiHeadAttention 类,其中 d_model 表示输入数据的维度,n_heads 表示注意力头的个数。在 forward 函数中,首先对输入数据进行线性变换,然后计算注意力分数,最后计算注意力输出并进行线性变换。
在计算注意力分数时,可以通过 mask 参数来控制注意力权重的计算,例如在机器翻译中,可以通过 mask 来掩盖掉目标语言中未来的词。
在使用多头注意力机制时,可以通过将多个 MultiHeadAttention 模块串联起来来实现,例如:
class TransformerBlock(nn.Module):
def __init__(self, d_model, n_heads, dropout=0.1):
super(TransformerBlock, self).__init__()
self.attention = MultiHeadAttention(d_model, n_heads)
self.dropout1 = nn.Dropout(dropout)
self.norm1 = nn.LayerNorm(d_model)
self.linear1 = nn.Linear(d_model, 4*d_model)
self.dropout2 = nn.Dropout(dropout)
self.linear2 = nn.Linear(4*d_model, d_model)
self.norm2 = nn.LayerNorm(d_model)
def forward(self, x, mask=None):
attn_output, attn_weights = self.attention(x, mask)
x = self.norm1(x + self.dropout1(attn_output))
linear_output = self.linear2(self.dropout2(nn.functional.relu(self.linear1(x))))
output = self.norm2(x + self.dropout2(linear_output))
return output
该代码实现了一个 TransformerBlock 类,其中包含了一个 MultiHeadAttention 模块和两个线性变换层。在 forward 函数中,首先使用 MultiHeadAttention 计算注意力输出,然后进行残差连接和归一化操作,接着对注意力输出进行线性变换,最后再进行残差连接和归一化操作。通过将多个 TransformerBlock 串联起来,可以构建一个完整的 Transformer 模型。
原文地址: https://www.cveoy.top/t/topic/ocZC 著作权归作者所有。请勿转载和采集!