Transformer是一种基于自注意力机制的神经网络架构,用于处理序列到序列的任务,如机器翻译和语音识别等。相比于传统的循环神经网络和卷积神经网络,Transformer能够并行计算,从而加快训练速度。
Transformer的核心结构由两个主要部分组成:编码器和解码器。编码器将输入序列映射为一系列高维向量表示,而解码器则将这些向量转换为输出序列。
编码器由多个相同的层组成,其中每个层包含两个子层:多头自注意力机制和前馈神经网络。多头自注意力机制允许网络在每个位置上将输入序列的不同部分关联起来,从而提取有意义的信息。前馈神经网络将自注意力机制的输出进行非线性转换。
解码器也由多个相同的层组成,其中每个层包含三个子层:多头自注意力机制、编码器-解码器注意力机制和前馈神经网络。编码器-解码器注意力机制将编码器的输出与解码器的输入相关联,使解码器能够根据编码器的信息生成准确的输出。
位置编码Positional Embedding是一种在Transformer模型中用来为输入序列中的每个位置添加信息的技术。由于Transformer模型没有使用循环神经网络或卷积神经网络来处理序列,因此需要一种方式来表示序列中不同位置的相对位置信息。位置编码通过为每个位置分配一个固定的向量表示,使得在输入序列中的不同位置的相对距离能够被模型所感知。
多头注意力Multi-Head Attention是Transformer模型中的一个关键组成部分,它允许模型同时将输入序列中的不同部分的注意力集中在不同的方面。通过将输入序列进行线性变换,再进行分割,并在每个分割后的部分上执行注意力操作,多头注意力能够在不同的位置上并行计算,并学习到更丰富的表示。
Masked Multi-Head Attention是多头注意力的一种变体,它在注意力计算过程中引入了一个掩码机制。在计算注意力权重时,掩码将一些特定的位置或区域屏蔽掉,使得模型无法在注意力计算中考虑这些位置或区域。这在处理序列任务中非常有用,例如在自然语言处理中进行语言建模时,可以使用掩码来防止模型在当前位置之后的信息泄露到当前位置。
前馈神经网络是Transformer模型中的另一个重要组件,它在每个位置上对输入进行非线性映射。前馈神经网络由两个线性变换和一个激活函数组成,其中第一个线性变换将输入投影到一个更大的维度空间,然后经过激活函数后再通过第二个线性变换进行投影回原来的维度。前馈神经网络能够引入非线性,并增加模型的表达能力。
Layer Normalization是一种用于归一化神经网络中每层输入的技术。与Batch Normalization(批归一化)不同,Layer Normalization是在每个样本的特征维度上进行归一化,而不是在每个批次上进行归一化。通过减去每个样本的均值并除以方差,Layer Normalization可以解决神经网络中不同输入之间的分布差异的问题。
以下是一个简化的Transformer的代码示例:
import torch
import torch.nn as nn
import torch.nn.functional as F
class Transformer(nn.Module):
def __init__(self, input_dim, output_dim, num_layers, num_heads, hidden_dim):
super(Transformer, self).__init__()
self.encoder = Encoder(input_dim, num_layers, num_heads, hidden_dim)
self.decoder = Decoder(output_dim, num_layers, num_heads, hidden_dim)
self.linear = nn.Linear(hidden_dim, output_dim)
def forward(self, src, tgt):
enc_output = self.encoder(src)
dec_output = self.decoder(tgt, enc_output)
output = self.linear(dec_output)
return F.softmax(output, dim=-1)
class Encoder(nn.Module):
def __init__(self, input_dim, num_layers, num_heads, hidden_dim):
super(Encoder, self).__init__()
self.layers = nn.ModuleList([EncoderLayer(num_heads, hidden_dim) for _ in range(num_layers)])
self.norm = nn.LayerNorm(hidden_dim)
def forward(self, src):
x = src
for layer in self.layers:
x = layer(x)
return self.norm(x)
class EncoderLayer(nn.Module):
def __init__(self, num_heads, hidden_dim):
super(EncoderLayer, self).__init__()
self.self_attention = MultiHeadAttention(num_heads, hidden_dim)
self.feed_forward = nn.Sequential(
nn.Linear(hidden_dim, hidden_dim * 4),
nn.ReLU(),
nn.Linear(hidden_dim * 4, hidden_dim)
)
self.norm = nn.LayerNorm(hidden_dim)
def forward(self, x):
x = self.self_attention(x)
x = self.feed_forward(x)
return self.norm(x)
class Decoder(nn.Module):
def __init__(self, output_dim, num_layers, num_heads, hidden_dim):
super(Decoder, self).__init__()
self.layers = nn.ModuleList([DecoderLayer(output_dim, num_heads, hidden_dim) for _ in range(num_layers)])
self.norm = nn.LayerNorm(hidden_dim)
def forward(self, tgt, enc_output):
x = tgt
for layer in self.layers:
x = layer(x, enc_output)
return self.norm(x)
class DecoderLayer(nn.Module):
def __init__(self, output_dim, num_heads, hidden_dim):
super(DecoderLayer, self).__init__()
self.self_attention = MultiHeadAttention(num_heads, hidden_dim)
self.enc_dec_attention = MultiHeadAttention(num_heads, hidden_dim)
self.feed_forward = nn.Sequential(
nn.Linear(hidden_dim, hidden_dim * 4),
nn.ReLU(),
nn.Linear(hidden_dim * 4, hidden_dim)
)
self.norm = nn.LayerNorm(hidden_dim)
def forward(self, x, enc_output):
x = self.self_attention(x)
x = self.enc_dec_attention(x, enc_output)
x = self.feed_forward(x)
return self.norm(x)
class MultiHeadAttention(nn.Module):
def __init__(self, num_heads, hidden_dim):
super(MultiHeadAttention, self).__init__()
self.num_heads = num_heads
self.hidden_dim = hidden_dim
self.head_dim = hidden_dim // num_heads
self.q_linear = nn.Linear(hidden_dim, hidden_dim)
self.k_linear = nn.Linear(hidden_dim, hidden_dim)
self.v_linear = nn.Linear(hidden_dim, hidden_dim)
self.out_linear = nn.Linear(hidden_dim, hidden_dim)
def forward(self, x):
batch_size, seq_len, _ = x.size()
q = self.q_linear(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
k = self.k_linear(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
v = self.v_linear(x).view(batch_size, seq_len, self.num_heads, self.head_dim).transpose(1, 2)
scores = torch.matmul(q, k.transpose(-2, -1)) / self.head_dim**0.5
attn_weights = F.softmax(scores, dim=-1)
weighted_values = torch.matmul(attn_weights, v)
x = weighted_values.transpose(1, 2).contiguous().view(batch_size, seq_len, self.hidden_dim)
x = self.out_linear(x)
return x
此代码示例实现了一个基本的Transformer模型,包括编码器、解码器和多头自注意力机制等核心组件。