机器学习周记(第十四周:Transformer续)2023.10.23~2023.10.29

目录

摘要

ABSTRACT

1 文献阅读

2 Decoder

2.1 Masked Self-attention

2.2 End Autoregression

2.3 Non-autoregressive(NAT)

2.3.1 AT v.s. NAT

3 Encoder-Decoder

4 Training

5 Tips

5.1 Copy Machanism

5.2 Guided Attention

5.3 Beam Search

5.4 BLEU score

5.5 Scheduled Sampling——Solve exposure bias

6 相关代码

总结


摘要

  本周完成了Transformer内容的学习,理解了Decoder中的注意力掩码机制以及Encoder和Decoder之间的连接方式,同时还了解了运用Transformer的一些小技巧来简化模型训练和提高模型性能。最终运用所学知识完成了一个简单的Transformer模型的定义。

  本周还阅读了一篇文献,从文献中了解到了对于多变量长时间序列数据缺失的插补办法,主要用到的模型是自注意力机制。

ABSTRACT

This week, We completed the study of Transformer content, gaining an understanding of the attention masking mechanism in the Decoder and the connection method between the Encoder and Decoder. Additionally, We familiarized ourself with some tricks for simplifying model training and improving model performance using Transformers. Finally, We applied the knowledge gained to define a simple Transformer model.

We also read a literature piece this week, from which we learned about an imputation method for missing multivariate long time series data, primarily utilizing a self-attention model.

1 文献阅读

论文题目:SAITS: Self-attention-based imputation for time series

论文摘要:时间序列中缺少数据是一个普遍存在的问题,它给高级分析带来了障碍。一个流行的解决方案是插补,其中的基本挑战是确定应该填写哪些值。该文提出一种基于自注意机制的多变量时间序列缺失值插补方法 SAITS。通过联合优化方法进行训练,SAITS 从两个 Diagonally-masked Self-attention(DMSA)块的加权组合中学习缺失值。DMSA 显式捕获时间步长之间的时间依赖关系和特征相关性,从而提高插补准确性和训练速度。同时,加权组合设计使 SAITS 能够根据注意力图和缺失信息,为来自两个 DMSA 块的学习表示动态分配权重。大量的定量和定性实验表明,SAITS 在时间序列插补任务上有效地优于最先进的方法,并揭示了 SAITS 在现实世界中不完整的时间序列数据上提高模式识别模型学习性能的潜力。

论文背景:多变量时间序列数据在许多应用领域中无处不在,例如交通、经济、医疗保健和气象学等。然而,由于各种原因,包括收集传感器故障,通信错误和意外故障,在现实世界环境中的时间序列中通常会看到缺失值这些缺失值损害了数据的可解释性,并对高级分析和模式识别任务(例如分类和聚类)提出了挑战。要学习这种不完整的时间序列,在建模之前提前思考如何处理缺失的部分是不可避免的一步。

过去方案:传统的缺失值处理方法分为两类。一种是删除,即删除部分观察到的样本或特征。然而,删除会使数据不完整,并可能产生有偏差的参数估计。另一种是数据插补,估计观测值的缺失数据。与删除相比,插补有两个主要优点:

① 删除会引入偏差,而正确指定的插补估计是无偏差的。

② 被删除的部分观测到的数据可能仍然具有信息量,对分析有帮助。

插补的问题是应该填写什么值。大量的先前工作从统计学和机器学习方法来解决这个问题,例如线性回归、平均/中位数平均和k-最近邻算法。然而,它们中的大多数都需要对缺失数据进行强有力的假设。这种假设可能会引入影响分析结果的强烈偏差。最近,许多文献利用深度学习来解决插补问题。

缺失值可分为三种类型:(1)完全随机缺失(Missing completely at random,MCAR),缺失值独立于任何其他值;(2)随机缺失(Missing at random,MAR),缺失值仅取决于观测到的值;(3)缺失不是随机的(Missing not at random,MNAR),缺失值取决于观测到和未观测到的值。

论文方案:本文提出了一种新的插值模型Self-Attention-based Imputation for Time Series(SAITS)。SAITS模型是由两个DMSA块加权组合而成。本文工作的重点是MCAR案例,这是插值领域大多数文献的标准。本文统一抽样独立缺失的值,并将其作为人为缺失引入,以评估本文中使用的所有插补方法。通过插补和重构的联合优化训练方法来学习缺失值。

SAITS模型总体架构

Diagonally-masked self-attention(DMSA):DMSA公式如下

使用这些对角线掩码,在t这一步看不到自己,被禁止为自己的估计做出贡献。因此,它们的估计仅取决于其他输入值(T-1)时间步长。这种机制使DMSA能够仅用一次注意力操作即可捕获高维空间中时间步之间的时间依赖关系和特征相关性。

Diagonally-masked Multi-head Attention(DiagMaskedMHA):DiagMaskedMHA公式如下

在引入了对角线掩码后,注意力图的对角线上的条目会被置为-\infty(实际运用中被置为-1\times 10^{9}),这样在通过softmax函数后,对角线上的注意力权重会趋近于0。

2 Decoder

  上一周的学习中,通过Decoder总体架构图可以发现,它并不只使用了常规的多头自注意力机制,同时还使用了一种被称之为Masked Multi-Head Attention的多头自注意力机制。

2.1 Masked Self-attention

  常规的Self-attention每一个输出都会考虑所有的输入,而Masked Self-attention则不同。在Masked Self-attention中,每一个输出只考虑它对应位置输入之前的特征,即b_{i}只考虑a_{1}\sim a_{i}i\geq 1)。

  从具体内部运算上来描述Masked Self-attention,就是将b_{i}对应a_{i}q^{i}只与a_{1}\sim a_{i}k^{1}\sim k^{i}做运算,忽略a_{i+1}\sim a_{n}。以b_{2}为例描述运算过程:

  为什么需要Masked Self-attention?因为在Decoder中,a_{i}并不是同时被输入Self-attention中的,而是先输入a_{1},然后输入a_{2},以此类推。所以a_{i}对应的输出b_{i}只能考虑a_{i}之前被输入的特征。

2.2 End Autoregression

  至此,现存的最大的问题就是如何让机器自己决定输出结果的长度。因为如果不设计一个特殊的结束机制,那么按照之前Autoregression的方式,机器会永无止境的输出下去。

  所以,需要在softmax概率分布词表中加入一个Stop Token,当机器输出为Stop Token时相当于告诉机器,输出的结果到此为止。

2.3 Non-autoregressive(NAT)

  除了自回归的Decoder,有没有非自回归的Decoder呢?答案是有的,也就是接下来所说的Non-autoregressive(NAT) Decoder。

2.3.1 AT v.s. NAT

  AT与NAT之间存在较大的差异,AT的过程是从左到右依次生成输出,可以显式地捕捉输出与输出之间从左到右的单向依赖,知道上文所有的输出,来预测当前输出。而NAT不像AT一样从左到右依次顺序地生成输出,而是同时生成一整个结果。也就是说,NAT假设了整个生成结果之间的输出与输出是互相独立的。

  NAT的方式也涉及到机器如何自己决定输出长度的问题。一种方案是在Encoder中加入对Decoder输出长度的预测,Decoder接收到Encoder中输出长度的预测值从而决定BEGIN的个数。另一种方案是让Decoder输出一个长度非常长的结果,在这个结果中从左至右找到第一个Stop Token,将这个Stop Token后面的输出忽略掉。

Advantage of NAT:NAT是平行计算输出的,所以相较于AT拥有更快的训练速度。同时NAT香蕉预AT,它的输出长度更加可。

Disadvantage of NAT:NAT的性能表现通常比AT更差。

3 Encoder-Decoder

  最后需要解决的问题是Encoder和Decoder之间的连接方式。这里用到的是Cross Attention的方法,将Decoder中的一个输出乘上矩阵作为q,将Encoder的输出乘上矩阵作为kvqkv运算传入FC层得到最终的结果。

4 Training

  Transformer的训练过程可以看做是多个分类任务的聚合。例如输入一段语音信号,给这段信号一个标签,Decoder的每一次输出都和标签对应位置的文字做一次Cross Entropy,而模型训练的目标就是让总的Cross Entropy最小。

5 Tips

  在Transformer模型的训练中存在一些技巧,通过这些技巧可以让模型效率更高,表现更加。

5.1 Copy Machanism

  并不是所有情况下,Decoder都需要根据Encoder的输出来训练模型的输出,它可以直接复制模型输入中的某些部分来直接输出,比如说Chatbot中,用户进行自我介绍时说出的名字,机器可以直接复制名字来回应用户。而且很显然想要通过训练来输出用户的名字也是不现实的。

  再比如说论文总结,机器显然不太可能完全由自己输出一篇论文的总结,它需要在论文中复制关键信息来作为输出。

5.2 Guided Attention

  在一些任务中,输入输出是单调对齐(monotonically aligned)的,比如语音识别和语音合成(TTS),可能会出现计算attention score的顺序时混乱的情况,无法很好得到结果。Guided attention就是强迫attention有一个固定的形式,比如TTS问题需要从左往右计算attention,可以参考Monotonic Attention Location-aware attention。

5.3 Beam Search

  假设Transformer只有两个Token,其训练过程就是不断沿着概率最大的Token进行预测。这种方式运用的是贪心策略的思想,但是有时候,开头选中概率最大的分支,其最终结果不是很好,相反在开头选中较小概率的分支时,其结果反而更佳。因此需要虚弱贪心策略的影响,在Decoder中加入一些Noisy,在一般情况下,训练加入Noisy会带来更强的Robustness,而测试的时候不会加Noisy,有趣的是,在试时往Decode中加入Noise,反而会带来更好的语音合成效果。

5.4 BLEU score

  在训练的时候,采用minimize Cross Entropy的方式来优化模型参数,但是最终测试时,是去选择BLEU score来评价模型性能。为什么不能在训练的时候maximize BLEU score呢?这是因为BLUE score没有办法做微分。

5.5 Scheduled Sampling——Solve exposure bias

  最后来解决之前遗留的一个问题:当Decoder的输出是错误结果时,这个错误结果会作为接下来的输入,然后导致一步错、步步错。可以考虑的解决方案是给Decoder一些错误的词去训练。

6 相关代码

一个简单的Transformer模型的定义:

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

class PositionalEncoding(nn.Module):
    """
    位置编码器用于为输入序列中的每个位置添加一个表示位置信息的编码向量
    """
    def __init__(self, d_model, dropout=0.1, max_len=5000):
        super(PositionalEncoding, self).__init__()
        self.dropout = nn.Dropout(p=dropout)

        pe = torch.zeros(max_len, d_model)
        position = torch.arange(0, max_len, dtype=torch.float).unsqueeze(1)
        div_term = torch.exp(torch.arange(0, d_model, 2).float() * (-torch.log(torch.tensor(10000.0)) / d_model))
        pe[:, 0::2] = torch.sin(position * div_term)
        pe[:, 1::2] = torch.cos(position * div_term)
        pe = pe.unsqueeze(0).transpose(0, 1)
        self.register_buffer('pe', pe)

    def forward(self, x):
        """
        前向传播函数,用于将位置编码添加到输入序列张量中
        """
        x = x + self.pe[:x.size(0), :]
        return self.dropout(x)


class Transformer(nn.Module):
    """
    Transformer模型类,包括编码器、解码器以及位置编码器
    """
    def __init__(self, input_vocab, output_vocab, d_model, nhead, num_encoder_layers, num_decoder_layers, dim_feedforward, max_seq_length, pos_dropout, trans_dropout):
        super(Transformer, self).__init__()
        # 初始化Transformer模型
        self.transformer = nn.Transformer(d_model=d_model, nhead=nhead, num_encoder_layers=num_encoder_layers,
                                         num_decoder_layers=num_decoder_layers, dim_feedforward=dim_feedforward,
                                         dropout=trans_dropout, activation='relu', custom_encoder=None, custom_decoder=None)
        # 定义源语言和目标语言的嵌入层
        self.src_embed = nn.Embedding(input_vocab, d_model)
        self.tgt_embed = nn.Embedding(output_vocab, d_model)
        # 初始化位置编码器
        self.pos_encoder = PositionalEncoding(d_model, pos_dropout, max_seq_length)
        # 定义解码层
        self.decoder = nn.Linear(d_model, output_vocab)

    def forward(self, src, tgt, src_mask, tgt_mask):
        """
        前向传播函数,用于传递源语言、目标语言序列以及相应的掩码
        """
        # 对源语言序列应用嵌入和位置编码
        src = self.src_embed(src) * torch.sqrt(torch.tensor(self.d_model, dtype=torch.float))
        src = self.pos_encoder(src)
        # 对目标语言序列应用嵌入和位置编码
        tgt = self.tgt_embed(tgt) * torch.sqrt(torch.tensor(self.d_model, dtype=torch.float))
        tgt = self.pos_encoder(tgt)
        # 应用Transformer模型
        out = self.transformer(src, tgt, src_mask=src_mask, tgt_mask=tgt_mask)
        # 应用线性解码层
        out = self.decoder(out)
        # 应用对数softmax激活函数
        return F.log_softmax(out, dim=-1)

总结

  Transformer是一种非常强大的模型,尤其对NLP和序列数据处理来说。通过Transformer加深了我对Self-attention以及ED结构的理解。下一周将继续探索深度学习的其他知识。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值