当前位置:   article > 正文

Datawhale AI 夏令营(NLP方向)2024 2期 笔记3

Datawhale AI 夏令营(NLP方向)2024 2期 笔记3

一、认识Transformer模型

Transformer模型是一种在自然语言处理(NLP)领域中革命性的架构,它首次出现在2017年的论文《Attention is All You Need》中。这个模型设计用于序列到序列的任务,如机器翻译,但其影响远远超出了这个范围,现在被广泛应用于各种NLP任务和其他序列建模场景。

1. 基本组成部分

编码器(Encoder)

编码器由多个相同的层堆叠组成,每一层通常包含两个子层:

  1. 多头自注意力机制(Multi-head Self-Attention):这个机制允许模型同时关注输入的不同部分,即在不同的“注意力头”中进行并行处理,这增强了模型捕获不同粒度信息的能力。
  2. 前馈神经网络(Feed Forward Network):这是一个简单的全连接神经网络,用于进一步处理自注意力层的输出。

解码器(Decoder)

解码器也有多个相同的层,每层包括三个子层:

  1. 掩码的多头自注意力机制(Masked Multi-head Self-Attention):在解码器中,为了保证预测的顺序性,使用掩码机制来阻止当前位置访问未来位置的信息。
  2. 多头注意力机制(Multi-head Attention):这部分允许解码器关注编码器的输出,实现编码器和解码器之间的交互。
  3. 前馈神经网络:与编码器相同,用于进一步处理信息。

位置编码(Positional Encoding)

因为Transformer没有内置的顺序概念(不像RNN那样有时间步的概念),所以需要添加位置编码来让模型理解输入序列中每个词的位置。位置编码通常是一个固定的函数,能够为序列中的每个位置生成一个唯一的向量。

下面给出构建模型的示例代码。

  1. class PositionalEncoding(nn.Module):
  2. def __init__(self, d_model, dropout=0.1, max_len=5000):
  3. super(PositionalEncoding, self).__init__()
  4. self.dropout = nn.Dropout(p=dropout)
  5. pe = torch.zeros(max_len, d_model)
  6. position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
  7. div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-math.log(10000.0) / d_model))
  8. pe[:, 0::2] = torch.sin(position * div_term)
  9. pe[:, 1::2] = torch.cos(position * div_term)
  10. pe = pe.unsqueeze(0).transpose(0, 1)
  11. self.register_buffer('pe', pe)
  12. def forward(self, x):
  13. x = x + self.pe[:x.size(0), :]
  14. return self.dropout(x)
  15. class TransformerModel(nn.Module):
  16. def __init__(self, src_vocab, tgt_vocab, d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout):
  17. super(TransformerModel, self).__init__()
  18. self.transformer = nn.Transformer(d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, dropout)
  19. self.src_embedding = nn.Embedding(len(src_vocab), d_model)
  20. self.tgt_embedding = nn.Embedding(len(tgt_vocab), d_model)
  21. self.positional_encoding = PositionalEncoding(d_model, dropout)
  22. self.fc_out = nn.Linear(d_model, len(tgt_vocab))
  23. self.src_vocab = src_vocab
  24. self.tgt_vocab = tgt_vocab
  25. self.d_model = d_model
  26. def forward(self, src, tgt):
  27. # 调整src和tgt的维度
  28. src = src.transpose(0, 1) # (seq_len, batch_size)
  29. tgt = tgt.transpose(0, 1) # (seq_len, batch_size)
  30. src_mask = self.transformer.generate_square_subsequent_mask(src.size(0)).to(src.device)
  31. tgt_mask = self.transformer.generate_square_subsequent_mask(tgt.size(0)).to(tgt.device)
  32. src_padding_mask = (src == self.src_vocab['<pad>']).transpose(0, 1)
  33. tgt_padding_mask = (tgt == self.tgt_vocab['<pad>']).transpose(0, 1)
  34. src_embedded = self.positional_encoding(self.src_embedding(src) * math.sqrt(self.d_model))
  35. tgt_embedded = self.positional_encoding(self.tgt_embedding(tgt) * math.sqrt(self.d_model))
  36. output = self.transformer(src_embedded, tgt_embedded,
  37. src_mask, tgt_mask, None, src_padding_mask, tgt_padding_mask, src_padding_mask)
  38. return self.fc_out(output).transpose(0, 1)

PositionalEncoding

初始化方法 __init__
  • 参数:

    • d_model: 模型的维度。
    • dropout: dropout比率,默认值为0.1。
    • max_len: 最大序列长度,默认值为5000。
  • 功能:

    • 创建一个nn.Dropout层。
    • 计算位置编码矩阵pe,其大小为max_len×d_model。这个矩阵是通过正弦和余弦函数计算出来的,用于给输入序列添加位置信息。
    • pe矩阵转换形状并注册为模型的缓冲区,以便在后续的前向传播中使用。
前向传播方法 forward
  • 参数: x,输入张量。
  • 功能:
    • 将位置编码pe与输入张量x相加。
    • 通过dropout层处理相加后的结果,返回处理后的张量。

TransformerModel

初始化方法 __init__
  • 参数:

    • src_vocab, tgt_vocab: 源语言和目标语言的词汇表。
    • d_model: 模型的维度。
    • nhead: 多头注意力机制的头数。
    • num_encoder_layers, num_decoder_layers: 编码器和解码器的层数。
    • dim_feedforward: 前馈网络的维度。
    • dropout: dropout比率。
  • 功能:

    • 创建nn.Transformer实例,这是Transformer模型的核心部分。
    • 创建源语言和目标语言的嵌入层src_embeddingtgt_embedding
    • 创建PositionalEncoding实例,用于添加位置信息。
    • 创建输出层fc_out,用于将Transformer的输出转换为目标语言的词汇表大小。
前向传播方法 forward
  • 参数: src, tgt,分别是源序列和目标序列的张量。
  • 功能:
    • 调整srctgt的维度,使其符合Transformer的输入要求。
    • 生成掩码矩阵src_masktgt_mask,用于控制自注意力机制中的信息流。
    • 根据src_vocabtgt_vocab生成src_padding_masktgt_padding_mask,用于忽略填充符号。
    • 使用嵌入层和位置编码层处理srctgt
    • 将处理后的srctgt作为输入传入transformer,得到输出。
    • 输出通过fc_out层,转换成目标语言词汇表大小的张量,再调整维度后返回。

 上述示例代码继承PyTorch的nn.Module类,通过调用nn.Transformer中封装的编码器(encoder)和解码器(decoder)的实现,包括多头自注意力机制(Multi-head Self-Attention)、位置前馈网络(Position-wise Feed-Forward Networks)以及残差连接层归一化等组件。从而高效地实现模型的构建。

2. 工作过程

对于Transformer模型的详细工作过程,由于其复杂性,不做出详细分析。

下面给出对其工作过程的大致概括。

输入序列处理

  1. 嵌入(Embedding)

    • 每个输入词或标记被转换为其对应的嵌入向量。这些嵌入向量通常预训练或随模型训练更新,捕捉词义和上下文信息。
  2. 位置编码(Positional Encoding)

    • 添加位置编码以告知模型词在序列中的相对位置,弥补Transformer无固有序列处理方式的不足。

编码器(Encoder)

  1. 多头自注意力(Multi-Head Self-Attention)

    • 编码器层含多头自注意力机制,允许模型在处理序列时考虑所有词的影响,而非仅限于相邻词。
    • 多头注意力机制将注意力机制分为多个独立“头”,关注输入的不同方面。
  2. 前馈神经网络(Feed-Forward Network)

    • 数据通过前馈神经网络,通常由两个线性层组成,中间可能有激活函数如ReLU。
  3. 残差连接与层归一化(Residual Connections & Layer Normalization)

    • 残差连接直接将层输入加到输出上,缓解梯度消失,简化模型训练。
    • 层归一化在每层输出处应用,保持数值稳定,加速训练。

解码器(Decoder)

  1. 掩码多头自注意力(Masked Multi-Head Self-Attention)

    • 解码器含多头自注意力,使用掩码防止模型访问未来位置信息,确保预测仅基于之前信息。
  2. 编码器-解码器注意力(Encoder-Decoder Attention)

    • 允许解码器关注编码器输出,更好地理解输入序列,生成相关输出。
  3. 前馈神经网络与残差连接/层归一化

    • 解码器中的这些组件与编码器中的相似,用于进一步特征处理。

输出

  1. 线性层与Softmax

    • 解码器输出通过线性层,经Softmax函数生成每个可能词的概率分布,预测序列中下一个词。
  2. 生成序列

    • 生成模式下,模型逐词生成输出序列,每次预测后将新词添加至序列,直至结束标记或达最大序列长度。

 由于个人因素,本篇笔记仅写到此,内容较少,分析较浅,后续会做更新和维护。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/爱喝兽奶帝天荒/article/detail/862369
推荐阅读
相关标签
  

闽ICP备14008679号