【Transformer原理解析】

7 篇文章 0 订阅

Transformer是一种基于自注意力机制(Self-Attention Mechanism)的深度学习模型,它在自然语言处理(NLP)领域取得了显著的成就,特别是在机器翻译任务中。以下是Transformer原理的简要介绍以及使用PyTorch实现的代码示例。

Transformer原理:

  1. 编码器-解码器架构:Transformer模型由编码器(Encoder)和解码器(Decoder)组成,每个部分都由多个相同的层(Layer)堆叠而成。
  2. 自注意力机制:每个编码器和解码器层都包含自注意力模块,允许模型在处理序列时同时考虑序列内的各个位置。
  3. 多头注意力:为了捕获不同类型的信息,自注意力机制被分解为多个“头”(Heads),每个头学习序列的不同部分。
  4. 位置编码:由于Transformer缺乏循环或卷积结构,因此引入位置编码来提供序列中词汇的位置信息。
  5. 前馈网络:在自注意力之后,每个编码器和解码器层都包含一个前馈网络,用于进一步处理数据。
  6. 残差连接和层归一化:每个子层(自注意力和前馈网络)的输出都加上其输入,然后进行层归一化,有助于梯度的流动。
  7. 输出线性层和softmax:在解码器的最后,一个线性层将输出映射到最终的词汇空间,通常伴随着softmax激活函数用于概率分布。

PyTorch代码示例:

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

class TransformerModel(nn.Module):
    def __init__(self, src_vocab_size, tgt_vocab_size, d_model, num_heads, num_layers, d_ff, max_len, dropout):
        super(TransformerModel, self).__init__()
        # 定义词嵌入层
        self.src_embedding = nn.Embedding(src_vocab_size, d_model)
        self.tgt_embedding = nn.Embedding(tgt_vocab_size, d_model)
        # 定义位置编码层
        self.pos_encoder = PositionalEncoding(d_model, max_len, dropout)
        self.pos_decoder = PositionalEncoding(d_model, max_len, dropout)
        # 定义编码器和解码器层
        encoder_layer = nn.TransformerEncoderLayer(d_model, num_heads, d_ff, dropout)
        self.transformer_encoder = nn.TransformerEncoder(encoder_layer, num_layers)
        decoder_layer = nn.TransformerDecoderLayer(d_model, num_heads, d_ff, dropout)
        self.transformer_decoder = nn.TransformerDecoder(decoder_layer, num_layers)
        # 定义输出线性层
        self.linear = nn.Linear(d_model, tgt_vocab_size)
        # 定义dropout
        self.dropout = nn.Dropout(dropout)

    def forward(self, src, tgt):
        # 编码器的前向传播
        src = self.dropout(self.src_embedding(src) * math.sqrt(d_model))
        src = self.pos_encoder(src)
        out = self.transformer_encoder(src)
        # 解码器的前向传播
        tgt = self.dropout(self.tgt_embedding(tgt) * math.sqrt(d_model))
        tgt = self.pos_decoder(tgt)
        out = self.transformer_decoder(tgt, out)
        out = self.linear(out)
        return F.softmax(out, dim=-1)

# 假设参数
src_vocab_size = 1000
tgt_vocab_size = 1000
d_model = 512
num_heads = 8
num_layers = 6
d_ff = 2048
max_len = 100
dropout = 0.1

# 实例化模型
model = TransformerModel(src_vocab_size, tgt_vocab_size, d_model, num_heads, num_layers, d_ff, max_len, dropout)

# 随机生成示例输入
src = torch.randint(src_vocab_size, (1, max_len))
tgt = torch.randint(tgt_vocab_size, (1, max_len))

# 前向传播
output = model(src, tgt)
print(output)

自注意力机制

自注意力机制(Self-Attention Mechanism)是Transformer模型的核心组成部分,它允许模型在序列的不同位置间直接计算注意力,从而捕捉序列内部的长距离依赖关系。自注意力机制特别适用于处理序列数据,如自然语言处理任务中的文本序列。

自注意力机制的原理:

  1. 计算表示:对于输入序列中的每个元素(如单词或字符),模型首先计算其查询(Query)、键(Key)、值(Value)的表示。
  2. 计算注意力分数:对于序列中的每一对元素,模型计算它们之间的注意力分数。这通常通过计算查询向量和键向量之间的点积来实现,然后通常对结果进行缩放(例如,除以键向量的维度的平方根)。
  3. 应用softmax函数:将得到的注意力分数通过softmax函数转换为概率分布,这一步确保了对每个元素的注意力权重是归一化的。
  4. 计算加权和:使用上一步得到的注意力权重对相应的值(Value)向量进行加权求和,得到加权的表示。
  5. 输出:得到的加权表示可以经过一些后续处理(如线性变换和非线性激活函数),以产生最终的输出。

自注意力机制的优势:

  • 捕捉长距离依赖:自注意力机制可以很容易地捕捉序列中任意两个元素之间的关系,无论它们之间的距离有多远。
  • 并行化:与循环神经网络(RNN)相比,自注意力机制可以高效地在多个序列元素上并行计算,这使得模型训练更快。
  • 灵活性:自注意力机制可以很容易地调整以适应不同的任务和数据类型。

PyTorch中的自注意力实现示例:

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

class SelfAttention(nn.Module):
    def __init__(self, embed_size, heads):
        super(SelfAttention, self).__init__()
        self.embed_size = embed_size
        self.heads = heads
        self.head_dim = embed_size // heads

        assert (
            self.head_dim * heads == embed_size
        ), "Embedding size needs to be divisible by heads"

        self.values = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.keys = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.queries = nn.Linear(self.head_dim, self.head_dim, bias=False)
        self.fc_out = nn.Linear(heads * self.head_dim, embed_size)

    def forward(self, values, keys, query, mask):
        N = query.shape[0]
        value_len, key_len, query_len = values.shape[1], keys.shape[1], query.shape[1]

        # Split the embedding into 'heads' number of heads
        values = values.reshape(N, value_len, self.heads, self.head_dim)
        keys = keys.reshape(N, key_len, self.heads, self.head_dim)
        queries = query.reshape(N, query_len, self.heads, self.head_dim)

        values = self.values(values)
        keys = self.keys(keys)
        queries = self.queries(queries)

        # Einsum does matrix multiplication for query*keys for each training example
        # with a specific head
        attention = torch.einsum("nqhd,nkhd->nhqk", [queries, keys])

        if mask is not None:
            attention = attention.masked_fill(mask == 0, float("-1e20"))

        # Apply softmax activation to the attention scores
        attention = F.softmax(attention / (self.embed_size ** (1 / 2)), dim=3)

        out = torch.einsum("nhql,nlhd->nqhd", [attention, values]).reshape(
            N, query_len, self.heads * self.head_dim
        )

        # Combine the attention heads together
        out = self.fc_out(out)

        return out

  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

stsdddd

你的鼓励将是我创作的最大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值