Transformer详解

前言

在17年,自然语言处理领域还在被RNN统治,当时的seq2seq任务还是用带encoder-decoder结构的RNN。然而RNN天然具有一个缺点:计算效率低。

随后的transformer也是encoder-decoder结构,但是其中信息关联采用了attention机制,而不是RNN的循环机制。

transformer一经提出,就横扫了以往的各种RNN变体,随后,人工智能社区陷入了万物transformer的时代,甚至引领了cv领域一段时间。

随后因为transformer(实际上是其中的attention)计算效率高,能极大缩短训练时间,大公司开始搜集更多的数据,用更多的算力,去训练更大的transformer,结果不经意间开启了大模型时代。目前的LLM几乎都是transformer的变体,通过学习transformer来入门大模型是很自然的。

这篇笔记从以下几个方面详细介绍transformer:

  • 什么是seq2seq?
  • 什么是attention,attention到底比RNN好在哪?
  • 把transformer看成黑盒,训练任务是什么?
  • transformer模型结构:
    • word embedding && positional embedding
    • self-attention && multi-head attention && cross attention
    • layer normalization
    • FFN|MLP
  • 论文中的一些笔记

背景

什么是seq2seq?

在现实世界,有一种场景,输入一个长度为\(l_i\)的序列,输出一个长度\(l_j\)的序列。

在NLP中,一段话按照单词为单位转换成一个序列。

例如,翻译任务:”机/器/学/习“ -> ”machine/learning“,长度为4的序列被翻译成了长度为2的序列;或者对话,”太/阳/从/哪/边/升/起“->”东/边“,输入长度为7的序列,输出长度2的序列。

这类任务就被称为seq2seq任务,这类模型也可以称为seq2seq模型。

为什么要划分出这类任务,自然是因为传统的模型不能处理不等长度的序列。简单说明一下,典型的神经网络如下图,这里把每个单词变成一个数值\(x_i\),要训练的参数是输入结点和中间结点之间的权重\(w_{ij}\)。如果输入结点增加,就会多出来一些未知参数。

一文弄懂神经网络中的反向传播法——BackPropagation - 知乎

为了解决这个问题,不把单词看成数值,而是变成固定长度\(d\)的向量\(\bold{x}_i\)。这样就可以把一段\(l\)个单词的句子看成\(X=[\bold{x}_1,…,\bold{x}_{l}]^T \in R^{l\times d}\),然后全连接层的权重就是\(W^{d\times d}\),这样全连接层就是每个单词(一个向量)依次进行线性变换。

我们知道序列之间存在着相互关系,例如一个单词的含义在不同的句子中可能也会不同。上面的简单的全连接中,单词之间是完全独立的,不会进行信息交换,所以也就不会捕获序列中单词之间的关系。

怎么捕获单词之间的关系——RNN

循环神经网络(Recurrent Neural Networks, RNN)提供了一种方法。如下图所示。

image-20230918233130134

每个单词(向量)在处理时,还要接受上一个单词处理后的中间结果。这样每个单词都能获得前面所有单词的信息。然后为了能处理变长序列,上面每层模块共享参数,或者说就是同一个模块。有关RNN的讲解,我是看的完全解析RNN, Seq2Seq, Attention注意力机制 - 知乎 (zhihu.com)

上面的模型只是能处理变长的序列,但是并不能处理seq2seq任务,因为上面的模型明显只能输出等长的序列。想要做seq2seq,需要调整成下面的结构。

img

举个例子:”机/器/学/习“->”machine“,在预测”machine“的时候,参考了”机/器/学/习“的信息,随后预测”learning“,模型接下来还会预测,预测到”“符号,表示预测终止。

RNN的缺点

基于RNN的encoder-decoder模型(简称RNN)虽然可以处理seq2seq任务,但是有很多缺点:

  • RNN基于时序,并行性差。也就是要一个个去处理单词。
  • 容易丢失远距离的信息。单词信息在链上会逐渐衰减。

当时有工作采用了CNN的方式来解决”丢失远距离信息“的问题,但是在长序列上,CNN需要增加卷积层才能看到整个序列。

Transformer

Attention

参考大佬的文章动图轻松理解Self-Attention(自注意力机制) - 知乎 (zhihu.com)

我这里描述一下过程:

现在有一个序列\(X=[\bold{x}_1,…,\bold{x}_{l}]^T \in R^{l\times d}\),这些token(就是单词对应的向量)经过三个线性变换映射成三个序列:\(Q=XW_q,K=XW_k,V=xW_v\),其中\(W_q,W_k,W_v\in R^{d\times d}\),因此\(Q,K,V\in R^{l\times d}\)。

然后计算\(Softmax(\frac{QK^T}{\sqrt{d}})\)得到一个得分矩阵\(S\in R^{l\times l}\)。得分矩阵中的元素\(s_{ij}\)表示\(q_i\)和\(k_j\)之间的相似度,这个相似度是用\(q_ik_j^T\)计算得到的。这个值越高,就表明\(x_i\)与\(x_j\)的关系较紧密,那么当我们处理\(x_i\)时,就要多考虑\(x_j\)。怎么多考虑,就是把这个得分当作是权重,也就是\(S·V\in R^{l\times d}\)。这个结果\(V_{out}\)还要再经过一个全连接层,也就是\(V_{out}W_o+b_o\)

上面线性代数的部分,如果基础不牢很容易看不懂,我当时就没看懂。可以参考我下面一篇文章,会详细进行计算。

attention的计算可以并行。因此极大提高了计算效率。总的来说,在并行时间内,只做了四个矩阵计算。

模型结构

image-20230919003011702

Input Embedding

上图中的Inputs是原始句子分词后的one-hot编码序列,设为\(X=[x_1,…,x_l]^{T}\),其中\(x_i\)是one-hot编码,例如有一个大小为\(V\)的词表,\(x_i\)对应的单词在词表中的序号为\(j\),那么\(x_i[j]=1\),其余为0。因此\(X\in R^{l\times V}\)

而Input Embedding可以看作是一个不带偏差的线性层,即\(W_E \in R^{V\times d}\),其中\(d\)表示映射后的向量维度。映射过程可以看成\(T=XW_E,T\in R^{l\times d}\)。

因为\(X\)中每一行都是一个单词对应的one-hot编码(向量),这个向量乘\(W_E\)的时候,其实就是按对应位置选择\(W_E\)的某一行向量。

所以也可以把\(W_E\)看成一个向量的查询表,那么\(X\)中的元素也不必是one-hot编码,也可以是一个数字,这个数字就是单词在词表中的序号。这样\(x_i=j\),那么映射过程就变成了T=W_E[X]

总之,我们得到了\(T_E=[t_1,…,t_l]^T\in R^{l\times d}\)。

Input Embedding层可以是训练的,也可以是固定的。如果是可训练的,该层就是一个无偏差的线性层,transformer使用的是这种。

Positional Embedding

序列中天然具有时序信息,在前一步的input embedding中,每个单词之间的处理都是独立的,此时还没有包含时序信息。并且attention也不像rnn结构天然具有能处理时序。因而在上一步得到的\(T_E\)中每个位置还要加上一个能够表示当前位置的信息(一个数值),这就是positional embedding。

位置信息有两种,绝对位置信息和相对位置信息。

transformer使用的是绝对位置信息,就是说固定位置的信息是固定的,例如位置3的位置信息永远是0.1(举个例子)。

transformer使用的是Sinusoidal编码。整个过程是,先将文本分词然后embedding,然后计算positional矩阵,将embedding加上这个矩阵,然后进入attention。编码矩阵计算如下:

\(p_k=\begin{cases} p_{k,2i}=\sin(k/10000^{2i/d}) \\ p_{k,2i+1}=\cos(k/10000^{2i/d}) \end{cases}\)

于是得到位置编码\(P=[p_1,…,p_l]^T\in R^{l\times d}\),然后\(T=T_E+P\)。

Multi-Head Attention

CNN具有多通道的优点,每个通道识别不同的pattern,论文提出了multi-head attention,可以模拟CNN的多通道。

从文字描述来看,过程是这样:

  • 有多个QKV转换矩阵,假设有两个head,那么\(W_q\)矩阵就有两个,分别是\(W_{q1},W_{q2}\in R^{d\times d/2}\),于是得到两个query:\(Q_1,Q_2\in R^{l\times d/2}\)。KV同理。
  • 现在每个头都有单独的QKV,例如头1有\(Q_1,K_1,V_1\)。
  • 然后在head内做attention:\(V_{out1}=Softmax(\frac{Q_1K_1^T}{\sqrt{d}})·V_1\in R^{l\times d/2}\),同理\(V_{out2}\in R^{l\times d/2}\)。
  • 将两个输出拼接,\(V_{out}=concat(V_{out1},V_{out2})\in R^{l\times d}\),然后经过一个输出层\(T_{out}=V_{out}W_o\in R^{l\times d}\)

实际上可以转换成:

  • 有一个\(W_q\in R^{d\times d},Q=TW_q\)。KV同理。
  • 现在把\(Q\)划分为多个head,设置head数为h,这样维度从\([l,d]\)变换为\([l,h,d/h]\)。为了后续在每个头内执行attention,还要变换到\([h,l,d/h]\)。KV同理。
  • 然后\(V_{out}=Softmax(\frac{QK^T}{\sqrt{d}})·V\),维度为\([h,l,d/h]\)。
  • 最后再将\([h,l,d/h]\)变换为\([l,d]\),然后经过输出层。

Add&Norm

假设输入attention的是\(T_0\),输出的是\(T_{out}=Attention(T_0)\),那么Add表示\(T_1=T_0+T_{out}\)。这是为了不丢失原始信息。

Norm指Layer Normalization。

Batch Norm是在一个批量中的所有样本的特征的一个维度上做Norm。在NLP中,是对每个句子的第一个(第二个、三个…)词的切片,一个矩阵,然后对这个矩阵的特征进行缩放。例如一个batch中的每个句子的第一个token的第一个维度。

Layer Norm是在一个样本中的所有特征之间做Norm。在NLP中,是对每个句子进行切片。是对一个句子的一个token内进行缩放。

img

如果要对\(T=[t_1,…,t_l]^T\)做layer normalization,每个元素独立处理。

例如\(t_1=[t_{11},…,t_{1d}]{T}\),那么正则化就是\(\hat{t}_{1i}=\frac{t_{1i}-\mu}{\sqrt{\sigma2+\epsilon}}\)。

FeedForward

一个带隐层的神经网络,一共两个线性层,隐层的维数为\(4d\),激活函数为ReLU。公式为:\(FFN(T)=\max(0,TW_1+b_1)W_2+b_2\)。

其中\(W_1\in R^{d\times 4d},W_2\in R^{4d\times d}\)。

Cross Attention

decoder中的第二个attention层就是cross attention。在self-attention中,QKV都是由X线性变换得到的,而cross attention中,Q是由X线性变换得到,而KV则是由Y线性变换得到的。

Embeddings && Output Linear

transformer中有两个embedding层,encoder和decoder各一个,这两层共享参数。并且模型最后输出的结果还要经过一个输出层,该层的目的是为了将d维的向量映射成V维的向量,该向量经过softmax后可以看成一个概率分布,表示预测单词的各概率。

Masked Attention

不管是RNN还是transformer,在做seq2seq任务时都是采用逐个词预测的方式,直到预测到终止符。

在训练时,为了提高计算效率,采用了并行预测的方式。举个例子:”机/器/学/习“->”machine/learning“的训练过程分为三步,这三步同时进行:

  • ”机/器/学/习“->”machine“
  • ”机/器/学/习/machine“->”learning“
  • ”机/器/学/习/machine/learning“->”“

怎么实现这个并行过程,就是用到了mask机制。

在attention中会计算\(QKT\),mask是一个01矩阵,维度是\([l,l]\)。然后将\(QKT\)和mask两个矩阵做计算,这个计算是:如果mask一个位置的元素是1,那么就将\(QK^T\)中对应位置的元素替换为无限小,如果是0就不变。

替换完后会进行softmax,这样被替换为无限小的部分softmax就会变成0。

Mask影响了什么

彻底理解mask才能彻底理解decoder的细节。

添加了mask后,decoder输入" / machine / learning",它们对应的输出对应于”machine / learning / “。其中bos是begin of seqence,eos是end of seqence。

在decoder中,每个位置输入对应的输出是下一个单词的预测。decoder中每个单词只能看到前面的信息。

在计算损失的时候,是将每个位置的输出(softmax后的一个概率分布),也就是多个概率分布拼接起来,然后和多个one-hot编码的拼接做cross entropy。

其他

  1. 在Attention中的\(\frac{QK^T}{\sqrt{d}}\)中,除以\(\sqrt{d}\)的目的是为了让softmax更平滑。softmax的一方面可以将一个向量变成一个概率分布。另一方面会将小的数字概率变得更小,大的数字概率变得更大,在\(QK_T\)中,计算结果会因为d的增加而增加,为了减小维度d的影响,所以要除以\(\sqrt{d}\)。
  2. 暂时还想不到。

最后

感谢你们的阅读和喜欢,我收藏了很多技术干货,可以共享给喜欢我文章的朋友们,如果你肯花时间沉下心去学习,它们一定能帮到你。

因为这个行业不同于其他行业,知识体系实在是过于庞大,知识更新也非常快。作为一个普通人,无法全部学完,所以我们在提升技术的时候,首先需要明确一个目标,然后制定好完整的计划,同时找到好的学习方法,这样才能更快的提升自己。

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

一、全套AGI大模型学习路线

AI大模型时代的学习之旅:从基础到前沿,掌握人工智能的核心技能!

img

二、640套AI大模型报告合集

这套包含640份报告的合集,涵盖了AI大模型的理论研究、技术实现、行业应用等多个方面。无论您是科研人员、工程师,还是对AI大模型感兴趣的爱好者,这套报告合集都将为您提供宝贵的信息和启示。

img

三、AI大模型经典PDF籍

随着人工智能技术的飞速发展,AI大模型已经成为了当今科技领域的一大热点。这些大型预训练模型,如GPT-3、BERT、XLNet等,以其强大的语言理解和生成能力,正在改变我们对人工智能的认识。 那以下这些PDF籍就是非常不错的学习资源。

img

四、AI大模型商业化落地方案

img

五、面试资料

我们学习AI大模型必然是想找到高薪的工作,下面这些面试题都是总结当前最新、最热、最高频的面试题,并且每道题都有详细的答案,面试前刷完这套面试题资料,小小offer,不在话下。
在这里插入图片描述

这份完整版的大模型 AI 学习资料已经上传CSDN,朋友们如果需要可以微信扫描下方CSDN官方认证二维码免费领取【保证100%免费

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 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、付费专栏及课程。

余额充值