机器学习周报第十周

摘要

Transformer是一种重要的深度学习模型,已在自然语言处理、图像处理等领域取得了显著成就。它引入了自注意力机制,通过自动学习输入序列中各个元素之间的关联性,实现了长距离依赖关系的建模。Transformer由编码器和解码器组成,每个模块都包含多头自注意力和前馈神经网络。Transformer的解码器模块是在生成输出序列时起作用的关键部分。解码器负责逐步生成目标序列中的每个元素,并在每个时间步骤中生成一个新的标记。self-attention也可以通过很多方法来加速计算。

Abstract

The Transformer is a significant deep learning model that has achieved remarkable success in various domains such as natural language processing and image processing. It introduces the self-attention mechanism, which automatically learns the relationships between different elements in the input sequence, enabling the modeling of long-range dependencies. The Transformer consists of an encoder and a decoder, each module containing multi-head self-attention and feedforward neural networks. The decoder module of the Transformer is a crucial component that operates during the generation of output sequences. It is responsible for progressively generating each element in the target sequence, producing a new token at each time step. Self-attention can also be accelerated using various techniques.

一、transformer

1.1 解码器(Decoder)

Decoder(解码器)是神经网络中的一个组件,主要用于将编码后的特征表示转换为目标序列或输出。在seq2seq任务中,编码器将输入序列转换为固定维度的向量,然后解码器将这个向量解码为目标序列。在机器翻译任务中,例如,编码器首先对源语言句子进行编码,然后解码器通过这个编码向量生成目标语言的翻译句子。解码器在生成每个目标语言的词时,会考虑之前已经生成的词,以及编码器传递过来的上下文信息。这样的设计使得解码器能够逐步生成合理的输出序列。

1.1.1 自回归解码器(Autoregressive Decoder)

Autoregressive Decoder(自回归解码器)简称AT,是一种在序列生成任务中常见的解码器类型,它用于逐步生成目标序列中的每个元素,其中每个元素的生成依赖于之前生成的元素。这种解码器通常用于生成离散序列,如自然语言文本或音频。
以语音识别为例,将一段声音序列输入编码器中,输出一段向量。接着给解码器一个特殊的符号,表示开始,然后给输出进行softmax,取值最大的为输出。下图中,汉字“机”为解码器的第一个输出。再将“机”作为解码器的下一个输入,重复上述步骤,依次得到“器”、“学”、“习”等输出。
在这里插入图片描述
编码器和解码器的内部结构如下图所示,解码器比编码器在中间多出了一部分,并且在第一层使用的是掩码多头注意力(Masked Multi-Head Attention),其余的结构基本相似。
在这里插入图片描述
Masked self-Attention和普通的self-attention相比,区别在于对于每个时间步,模型只能关注当前时间步及之前的元素。未来时间步的信息会被掩码,即将注意力权重置为较小的值(通常是0),从而阻止模型访问未来信息。这样,在生成序列的每个元素时,模型只会依赖于前面已生成的元素,而不会受到未来信息的影响。这也与自回归解码器的特性相符合。
在这里插入图片描述

1.1.2 非自回归解码器(non-autoregressive decoder)

非自回归解码器(non-autoregressive decoder)简称NAT,是一种在序列生成任务中使用的解码器,与传统的自回归解码器不同。在自回归解码器中,生成序列的每个元素都依赖于前面已生成的元素,因此需要逐个步骤地生成序列,导致生成速度较慢。而非自回归解码器尝试一次性并行地生成整个序列,而不需要等待前面元素的生成。这样可以显著加快生成速度,特别是在长序列的情况下。但NAT会面临不知道输出的长度的问题,该问题的解决方法有两种,第一种可以在输入中添加标记,来指示输出序列的期望长度。模型在训练过程中可以通过这个标记来预测输出序列的长度。第二种是给较长的输入,然后在输出中寻找中断点end的位置即可。
在这里插入图片描述

1.2 编码器和解码器传递信息

如下图所示,解码器中间部分被称为交叉注意力(cross attention)。交叉注意力的三个输入中,键(key)和值(value)来自编码器,查询来自解码器。
在这里插入图片描述
下图为交叉注意力的运行过程,首先在解码器的每个时间步,生成一个查询向量。这个查询向量用于寻找与当前解码器位置相关的编码器输入信息。对于编码器输入序列的每个时间步,生成键向量和值向量。通过点积计算查询向量与编码器每个位置的键向量之间的相似度,得到注意力权重。对计算得到的注意力权重进行softmax,以确保它们的总和为1,接着使用注意力权重对编码器的值向量进行加权求和,得到一个加权的编码器上下文向量。这个向量包含了编码器输入序列中与当前解码器位置相关的信息。
在这里插入图片描述

1.3 训练

如下图所示,真实的输出值可以看成一个独热编码。以“机”字为例,可以将每个汉字取值为一个向量,在该向量中,将“机”字所在的维度设为1,其他的维度设为0。而解码器的输出经过softmax归一化后,输出的是一个概率分布的值。将该模型的损失函数用交叉熵来表示,对真实的值和解码器输出的值做交叉熵,随着训练的进行,得到较小的损失函数的值。
在训练过程中,通常将真实的目标序列被用作解码器的输入,有点像一个“老师”在指导模型生成正确的输出,所以这种训练方式叫做 Teacher Forcing。这种训练方式可能导致模型在测试时不够稳健,因为它在训练过程中一直受到正确答案的指导。为了解决这一问题,需要在训练和解码阶段引入更多的随机性,可以故意给模型输入一些错误答案,以增强模型的适应性。
在这里插入图片描述

二、自注意力机制类别总结

2.1 自注意力机制存在的问题

注意力矩阵是一个正规化的矩阵,其行表示查询元素,列表示键元素。矩阵中的每个元素表示了查询与键之间的相似度或关联程度。在实际应用中,通常会对注意力矩阵进行进一步的加权求和操作,以获得最终的加权和值。在self-attention中,输入序列经过三个不同的线性变换生成三个矩阵,分别称为查询(Query)、键(Key)和值(Value)矩阵。这些矩阵用于计算注意力权重。对于每个查询元素,通过计算与所有键元素之间的相似度得到注意力分数,然后对这些分数进行归一化以得到注意力权重。这些注意力权重用于加权求和值矩阵,生成每个查询元素的加权和,这就是self-attention的输出。
但是当输入的长度过长,这个矩阵会变得很大,从而影响模型的效率。
在这里插入图片描述

2.2 加快自注意力机制处理速度

2.2.1 Local Attention

局部注意力(Local Attention)不是考虑序列中所有元素的关系,而是只考虑该元素前后两个元素的关系。这种方法可以减少计算量,提高效率,并且在一些任务中能够取得较好的效果。但是它能处理的范围较小,功能与CNN相似。
在这里插入图片描述

2.2.2 stride attention

stride attention与Local Attention相比,区别是stride attention并不是只取相邻的两个元素,而是取相隔较远的两个元素,如下图所示。在这里插入图片描述

2.2.3 global attention

如果关心的是整个sequence,那么可以用global attention。global attention加入一个特殊token到原始的sequence里面。在这里,global attention会做两件事情:
(1)每个特殊的token都加入每一个token,收集全局信息。
(2)每个特殊的token都被其他所有的token加入,以用来获取全局信息。
实现方法:第一种是把原来的sequence里面的某些向量选做special token。另外一种就是外加额外的token。如果要把外加token的矩阵attention matrix画出来,每一个cow行代表query,每一个column列代表key。下图中橘色两个横向的地方是有值的,都要计算attention,他们是特殊的token,要加入到所有的其他的key。那每一列的前两列也是有值的,他们也会加入到第一个和第二个位置。从下图可以看出来,每一个不是特殊token的query都要加入特殊token。而对于灰色的地方,他们没有值,互相之间就没有联系了。
在这里插入图片描述

2.2.4 clustering

聚类(Clustering)是一种无监督学习方法,旨在将相似的数据点分组成称为“簇”的集合。每个簇内的数据点彼此相似,而不同簇之间的数据点差异较大。如下图所示,将查询和键做分成不同种类的集合,每种集合用不同的颜色表示,而相同的集合属于同一个簇,他们之间彼此相似。
在这里插入图片描述
在分好类后,再将键和查询中属于同一类别的向量做点积运算,其余的直接将他们的权重设置为0。这样即可保留注意力矩阵中相似度较大的那些数,而忽略那些相似度较小的数据,使得该注意力矩阵与传统的注意力矩阵的差别不大,但是能加快运算的速度。
在这里插入图片描述

2.2.5 Linformer

在一个attention matrix里会有很多冗余的列。在这种情况下可以去掉重复的列,从而产生一个小的attention matrix来加快运算的速度。
在这里插入图片描述
详细做法如下图所示。从长度为N的键中选取K个代表性的键,再从长度为N的值中也选取K个代表性的值。将选取出来的键与查询做点积来计算两者的相似度,在将计算出的attention matrix与值计算注意力权重即可得到输出。在这里保持查询的长度不变,是因为改变该值可能会影响最终输出的长度。如果是做输入一个序列输出一个标签的实例,那么就会产生错误的结果。
在这里插入图片描述
在选择代表性的key的问题上,在一个文章compressed attention提出将一个很长的key序列使用CNN来扫过,key序列的长度就变短了,那这个就是代表性的key。在另一个文章linformer里面提出,输入的key序列可以看成是d✖N的矩阵,我们可以把这个key序列乘上一个N✖K的矩阵,然后就得到了d✖K的矩阵。那这个得到的新矩阵就是代表性key序列,这个方法其实是N个key序列的线性组合。
在这里插入图片描述

2.2.6 改变矩阵乘法的顺序

在自注意力机制中,改变矩阵乘法的顺序也可以做到加速运算。如下图所示,在第一个式子中,先计算 K T ∗ Q K^T*Q KTQ需要计算 N ∗ d ∗ N N*d*N NdN次,接着与V相乘需要计算 d ′ ∗ N ∗ N {d}'*N*N dNN次,总计算量为 ( d + d ′ ) N 2 (d+{d}')N^2 (d+d)N2次。在第二个式子中,先计算V和 K T K^T KT相乘需要计算 d ′ ∗ N ∗ d {d}'*N*d dNd次,再与Q相乘需要计算 d ′ ∗ N ∗ d {d}'*N*d dNd次,总计算量为2dd’N。上面的计算比下面的计算大很多。
在这里插入图片描述

三、多层感知机

import torch
from torch import nn
from d2l import torch as d2l

batch_size = 256
train_iter, test_iter = d2l.load_data_fashion_mnist(batch_size)

num_inputs, num_outputs, num_hiddens = 784, 10, 256

W1 = nn.Parameter(torch.randn(
    num_inputs, num_hiddens, requires_grad=True) * 0.01)
b1 = nn.Parameter(torch.zeros(num_hiddens, requires_grad=True))
W2 = nn.Parameter(torch.randn(
    num_hiddens, num_outputs, requires_grad=True) * 0.01)
b2 = nn.Parameter(torch.zeros(num_outputs, requires_grad=True))

params = [W1, b1, W2, b2]

def relu(X):
    a = torch.zeros_like(X)
    return torch.max(X, a)

def net(X):
    X = X.reshape((-1, num_inputs))
    H = relu(X@W1 + b1)  # 这里“@”代表矩阵乘法
    return (H@W2 + b2)

loss = nn.CrossEntropyLoss(reduction='none')

num_epochs, lr = 10, 0.1
updater = torch.optim.SGD(params, lr=lr)
d2l.train_ch3(net, train_iter, test_iter, loss, num_epochs, updater)


d2l.predict_ch3(net, test_iter)

输出为:
在这里插入图片描述
在这里插入图片描述

总结

通过编码-解码架构以及自注意力机制,我们能够高效地进行序列建模和自然语言处理任务。局部自注意力和信息传递机制有助于提高计算效率和模型性能,使得这些技术在实际应用中具有巨大的潜力。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值