Transformer详解

简介:


  本文在论文的基础上结合代码来对Transformer进行详细的解释,根据Transformer的流程顺序对其中涉及的技术原理结合代码进行详细地阐述。同时,尽可能地去解释这些功能产生了什么作用。

Transformer的结构图
Transformer的运行流程如上图所示,输入一串字符通过encoder层得到一个结果,将这个结果送到每一层的DECODER中,最后通过DECODER输出目标结果。

在这里插入图片描述
上图是论文《attention is all you need》中所展示的transformer结构图,本文以从左往右、从下往上的顺序进行分析。


Encoder:

class Encoder(nn.Module):
    def __init__(self, 
                 input_dim,hid_dim,n_layers, n_heads,pf_dim,dropout, device,
                 max_length = 100):
        super().__init__()

        self.device = device
        
        self.tok_embedding = nn.Embedding(input_dim, hid_dim)
        self.pos_embedding = nn.Embedding(max_length, hid_dim)
        
        self.layers = nn.ModuleList([EncoderLayer(hid_dim, n_heads,pf_dim,
                                                  dropout,device) 
                                     for _ in range(n_layers)])
        
        self.dropout = nn.Dropout(dropout)
        
        self.scale = torch.sqrt(torch.FloatTensor([hid_dim])).to(device)
        
    def forward(self, src, src_mask):
        
        #src = [batch size, src len]
        #src_mask = [batch size, src len]
        
        batch_size = src.shape[0]
        src_len = src.shape[1]
        
        pos = torch.arange(0, src_len).unsqueeze(0).repeat(batch_size, 1).to(self.device)
        
        #pos = [batch size, src len]
        
        src = self.dropout((self.tok_embedding(src) * self.scale) + self.pos_embedding(pos))
        
        #src = [batch size, src len, hid dim]
        
        for layer in self.layers:
            src = layer(src, src_mask)
            
        #src = [batch size, src len, hid dim]
            
        return src

输入字符串首先被向量化乘上 d m o d e l \sqrt{d_{model}} dmodel (维度),这一步骤应该是用来降低position encoding对原有向量的影响。另外,trg(Decoder的输入)和src(Encoder的输入)共享embedding层的权重,这样做可以减少运算所需要的内存。

由于德语和英语同属日耳曼语言,有很多相同的subword有着相似的含义。如果两种语言没有多少共同的subword(比如中英),使用共享词表也并不会有什么性能损失(由于词表变大,速度上可能有微小的损失),因为对于encoder和decoder而言都只有对应的语言的embedding会被激活. [1]

然后利用positional encodings给输入向量加上位置信息(代码中参考了Bert,直接加上pos_embedding),这是因为self-attention无法像RNN和CNN一样可以直接利用sequence的顺序,所以需要对向量进行一个处理,即,词向量与对应的位置向量相加,让transformer也可以利用sequence的顺序信息。在加上位置信息后dropout,dropout在transformer中多次出现,它可以抑制模型过拟合。

dropout根据一定的概率 p p p 临时隐藏一些神经网络节点(输入输出节点除外),这些被隐藏的网络节不参与这一批样本的训练,未被隐藏的节点正常更新参数。在训练结束后,重新随机隐藏部分节点。dropout通过隐藏部分节点形成一个“新”的神经网络,整个过程相当于对很多个不同的神经网络取平均。 而不同的网络产生不同的过拟合,一些互为“反向”的拟合相互抵消就可以达到整体上减少过拟合。同时,dropout程序导致两个神经元不一定每次都在一个dropout网络中出现。(这样权值的更新不再依赖于有固定关系的隐含节点的共同作用,阻止了某些特征仅仅在其它特定特征下才有效果的情况)。 迫使网络去学习更加鲁棒的特征 (这些特征在其它的神经元的随机子集中也存在)[2]

PositionalEncoding

这一部分的代码来源于 The Annotated Transformer

class PositionalEncoding(nn.Module):
    "Implement the PE function."
    def __init__(self, d_model, dropout, max_len=5000):
        super
  • 2
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Transformer 是一种用于自然语言处理任务的深度学习模型,它是由 Google 在 2017 年提出的。相比于传统的循环神经网络和卷积神经网络Transformer 采用了全新的 Encoder-Decoder 架构,使用了自注意力机制(Self-Attention Mechanism)来处理输入序列,从而在机器翻译、文本摘要、对话生成等任务上取得了很好的效果。 Transformer 本质上是一个 Encoder-Decoder 架构,其中 Encoder 和 Decoder 都是由多个相同的层堆叠而成。每个层都包含了两个子层,分别是 Multi-Head Attention 和 Feed Forward Neural Network。其中 Multi-Head Attention 是 Transformer 的核心,它使用了自注意力机制来计算输入序列中每个词与其他词之间的关系,从而更好地捕捉上下文信息。 Transformer 的训练过程分为两个阶段:第一阶段是无监督的预训练,使用大量的无标注数据来训练模型;第二阶段是有监督的微调,使用有标注的数据来微调模型,使其适应特定的任务。 下面是一个简单的 Transformer 模型的实现代码: ```python import torch import torch.nn as nn import torch.nn.functional as F class Transformer(nn.Module): def __init__(self, input_dim, hidden_dim, output_dim, num_layers, num_heads, dropout): super().__init__() self.embedding = nn.Embedding(input_dim, hidden_dim) self.encoder_layers = nn.ModuleList([EncoderLayer(hidden_dim, num_heads, dropout) for _ in range(num_layers)]) self.decoder_layers = nn.ModuleList([DecoderLayer(hidden_dim, num_heads, dropout) for _ in range(num_layers)]) self.fc_out = nn.Linear(hidden_dim, output_dim) self.dropout = nn.Dropout(dropout) self.scale = torch.sqrt(torch.FloatTensor([hidden_dim])).to(device) def forward(self, src, trg, src_mask, trg_mask): src_len, batch_size = src.shape trg_len, batch_size = trg.shape src_pos = torch.arange(0, src_len).unsqueeze(1).repeat(1, batch_size).to(device) trg_pos = torch.arange(0, trg_len).unsqueeze(1).repeat(1, batch_size).to(device) src = self.dropout((self.embedding(src) * self.scale) + src_pos) trg = self.dropout((self.embedding(trg) * self.scale) + trg_pos) for layer in self.encoder_layers: src = layer(src, src_mask) for layer in self.decoder_layers: trg = layer(trg, src, trg_mask, src_mask) output = self.fc_out(trg) return output ```

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值