一、循环神经网络RNN
循环神经网络RNN(Recurrent Neural Network)是一种专门设计用于处理序列数据的神经网络模型,通过引入“循环结构”捕捉序列中的时间或顺序依赖关系,广泛应用于需要上下文信息的任务(如自然语言处理、视频分析、基于历史数据的股价预测)
1.核心公式
(1)隐藏状态:
(2) 输出:
其中:
2.流程图
3.RNN的局限性
(1) 无法并行计算:每个隐藏状态的计算依赖于上一个隐藏状态的计算结果
(2)无法捕捉长期依赖:信息会随着时间步的增加而逐渐稀释,如对于那些在句尾存储着重要信息的语句处理效果差
(3)梯度消失:(梯度公式与反向传播的相关推导见我的上一篇文章: 基于CNN卷积神经网络的交通标志识别系统(万字详解))基础的RNN网络与VGG网络非常相似,上下层之间的输入输出都基于
二、门控循环单元 GRU
为了解决RNN网络无法捕捉长期依赖和梯度消失的问题,2014年由Cho等人提出了门控循环单元GRU(Gated Recurrent Unit),将原来上下层的递推公式由
1.流程图
2.门控单元的具体计算过程
图中四个核心计算公式:
①最终隐藏状态
②更新门
③重置门
④候选隐藏状态
其中
下图为矩阵拼接乘法与Hadamard积的计算演示
三、长短期记忆网络 LSTM
LSTM是为了解决RNN网络无法捕捉长期依赖和梯度消失的问题,并且早在1997年就被提出。LSTM与GRU虽然目的相同,但由于结构上的不同,它们都有各自的优势区间和应用场景,简单来说,GRU可以看作是LSTM的轻量化版本(详细对比分析见目录 三—3)
1.流程图
区别于GRU中的2种门控单元(更新门、重置门),LSTM引入了3种门控单元(遗忘门、输入门、输出门)和1种细胞状态。在长短期记忆网络LSTM中,细胞状态
实例分析(结合流程图和下方的计算公式图理解)
场景:假设我们需要在一间教室连续进行两场考试(数学、英语),考试前完全没有任何准备,属于裸考,但在每场考试开始之前有20分钟的复习时间。
我们可以将长期记忆
(1)初始时
(2)在第二场考试的前20分钟期间进行学习,使得
2.具体计算过程
图中核心公式如下:
隐藏状态
输出门
细胞状态
候选细胞状态
输入门
遗忘门
3.GRU与LSTM对比分析
(1)训练速度、存储空间占用率:从参数量来看,GRU含有3组权重矩阵,而LSTM含有4组权重矩阵,同层数同维度下,GRU参数量约为LSTM的75%,所以GRU计算量更低,训练速度更快,需要的存储空间资源更少。并且GRU只通过隐藏状态传递历史信息,没有细胞状态,拥有更简明的体系结构,也会使收敛速度更快。
(2)粒度(敏感or鲁棒):我们从上述公式发现,GRU的候选隐藏状态
而LSTM的细胞状态
正是这种融合与门控先后顺序的差异,使得GRU与LSTM拥有了不同的粒度:细粒度的GRU能通过重置门对历史信息进行更为细致的控制(如在上文“屋子很大但很脏”的褒贬性判断任务中,当输入
(3)长期依赖中的稳定性:由于LSTM加入了记忆细胞,长期记忆
(4)缓解梯度消失:区别于传统RNN网络中基于
四、transformer模型
如果说GRU与LSTM是在RNN的基础上进行的改良模型,那transformer模型则彻底抛弃了 “隐藏状态” 这种逐层传递的机制,而是引入了位置编码来感知上下文,因此transformer模型拥有了并行计算的能力;同时transformer引入残差网络和注意力机制来分别解决梯度消失和权重分配的问题。
对于transformer模型,我将以总分的形式进行介绍,先展示transformer的流程图,再详细说明各组分的细节。
1.transformer的流程图
transformer模型由编码器与解码器构成,下面以翻译任务(将英文“are you ok ?” 翻译为中文 “你还好吗?” )为例,介绍编码器与解码器的结构和作用。
[1] 编码器的结构图
编码器将英文“are you ok ?” 作为输入,经过词嵌入、位置编码、自注意力、前馈神经网络的处理后,最终输出一个融合了位置信息、上下文语义的编码矩阵,图例如下:
注:实际上,transformer编码器的输出会在权重矩阵
[2] 解码器的结构图
解码器将已预测的词汇(模型推理阶段)或真实翻译结果(模型训练阶段)作为输入,经过词嵌入、位置编码、掩码自注意力、交叉注意力、前馈神经网络的处理后,最终输出下一个预测的词汇(Transformer模型是逐词汇生成的,在推理阶段,每次运行一次解码器就会生成一个词,并将该词作为输入的一部分继续生成下一个词)
[3] Transformer结构图
单编码器和单解码器构成的Transformer:
原论文中的transformer结构图(图中的“N×”表示Transformer可以由N个编码器和N个解码器组成,以增强模型表达能力):
多编码器和多解码器的Transformer简图:
[4] transformer流程图
该部分将忽略transformer的内部构造,专注于说明transformer的流程。
(1)训练阶段
transformer在训练阶段的目标是计算模型预测结果与真实结果之间的损失值,再根据反向传播优化参数。transformer会在训练阶段将真实结果作为解码器的输入,并通过掩码(Mask)确保在预测第
由于在训练阶段,解码器的输入不依靠上一次的输出,而是直接将真实结果作为输入,且有掩码(Mask)控制输入,所以transformer在训练阶段可以使用并行算法,一次性就把所有目标单词都预测出来。这样做有两个好处,一是并行计算能够加快网络的训练速度;二是在训练过程中直接投喂给解码器正确的结果而不是上一时刻的预测值(因为训练时上一时刻的预测值可能是错误的),可以让训练更快收敛。
下图以翻译任务(将英文 “Are you ok?” 翻译为中文, 真实结果为“你还好吗?”,模型预测结果“你干什么?”)为例,说明transformer在训练阶段的流程:
注:实际上,transformer在训练阶段将真实结果的每一个词汇经过词嵌入形成一个词向量,之后将所有词向量拼接为一个矩阵,实现一次性输入;通过Mask矩阵实现一次性掩码;最终输出矩阵的每一行对应着一个预测词汇的概率分布,预测的一系列词汇通过该概率矩阵一次性生成(即并行计算通过矩阵实现)
(2)推理阶段
transformer在推理阶段为逐词生成,即每一次根据编码器的输入和已预测的输出推理出下一个词汇。其中,模型的输出会拼接到下一次解码器的输入中,这种操作称为 “自回归”(使用自回归进行推理的原因见 4-4-3 交叉注意力机制)
注:输入标志<start>表示模型开始推理,输出标志<end>表示模型推理结束。
2.词嵌入
[1] 词嵌入的目的
词嵌入是将人类可识别的语言转为向量,以便计算机进行存储、运算等操作。向量中不同的维度可以分别存储词汇的不同属性,举例如下:
但在模型实际运行时,词向量的维度往往是几百维或更高,每个维度的具体数值也很难直观的对应到某个具体的属性上,这些数值通常会被反向传播优化,以便最小化损失。
[2] 词嵌入的流程图
词嵌入分为创建过程和查询过程,创建过程旨在构造一个存储着所有词汇对应的词向量的嵌入矩阵,这里称之为全局嵌入矩阵;查询过程会根据输入文本的索引查询全局嵌入矩阵,得到输入嵌入矩阵,其存储着输入文本中词汇对应的词向量。
(1)语料库的选择
语料库是自然语言处理中用于训练、测试或分析模型的结构化文本数据集合,可以是原始文本(如书籍、网页、对话记录)或标注数据。语料库的质量和规模直接影响模型性能(对于通用语言模型一般需要大规模、多领域、多语言的语料库进行训练;对于专业领域任务,如医学、法律等需要权威性专业化的论文、刊物作为语料库进行训练)
(2)词汇表的构建
词汇表负责记录词汇到索引的映射,一般流程为:数据清洗 → 分词 → 词频统计 → 添加特殊标记 → 生成映射。
① 在数据清洗阶段,会将语料库中的文本进行统一大小写、去除HTML标签等操作。
② 在分词阶段,会将语句划分为词汇,目前主流分词策略有 “词级” 和 “子词级” 两种方式。“词级” 分词策略会按空格或标点将句子分割为完整的单词;而 “子词级” 分词策略会在“词级”的基础上将单词拆分为更小的子词单元(如将 ‘unhappy’ 拆分为 ‘un’ 和 ‘happy’ )
③ 在词频统计和添加特殊标记阶段,会统计所有词/子词的出现频率,低频词(如在语料库中出现的频率小于5次的生僻字或罕见的人名)将会被统一标记为 [UNK],可以在基本不影响语义的情况下节约存储空间,并且可以防止输入未知词汇时模型由于找不到对应索引而崩溃。
④ 在生成映射阶段,会将词汇按照词频降序排序后映射到索引上。特殊标记( 如[UNK] ) 通常排在最前,映射到的索引值最小;高频词次之;低频词排最后,映射到的索引值最小。这种映射方式能将高频词集中映射到全局嵌入矩阵的上半方,我们就可以根据局部性原理,将存储着高频词词向量的这部分嵌入矩阵常驻到cache或内存中,极大提高访问效率。
(3)全局嵌入矩阵的生成方式:
① 随机初始化:如将嵌入矩阵的所有参数随机采样于正态分布后,直接通过transformer的反向传播优化。
此训练方法需通过反向传播从头优化所有参数(包括嵌入矩阵),所以想要达到理想效果,必须拥有大量的已标注数据(transformer模型本体的训练属于有监督学习),并且收敛速度较慢;
transformer模型本体的编码器数量一般小于Bert中编码器的数量,导致词汇对上下文的融合能力较弱,此外,由于transformer模型本体一般都以具体的下游任务为导向,数据总量与多样性均不足,并且有明确标注的数据可能在一词多义的情况下导致过拟合(例如模型在测试时遇到低频语义时,可能错误应用高频语义),所以该方法对多义词的处理效果差,即词向量的动态性差。
② 通过 Word2Vec 或 Bert 预训练:通过词嵌入模型根据语料库预训练生成全局嵌入矩阵,之后再通过transformer的反向传播进行微调。(注:目前,基于窗口滑动的Word2Vec模型由于只能捕捉局部上下文信息而被淘汰;而基于transformer编码器的Bert模型可以捕捉全局上下文信息,被更广泛的使用。更多词嵌入模型详解见新一期博客)
此训练方法在预训练阶段要对大规模的语料库进行无监督学习,在transformer反向传播微调阶段需要少量标注数据进行有监督学习。通过Bert训练的模型对上下文的融合能力强,多义词的处理效果好,泛化能力强,但在预训练阶段需要大量计算资源作为支持。
③ 迁移学习:直接复用其他类似任务训练好的嵌入矩阵,之后再通过transformer的反向传播进行微调。
此方法适用于训练样本少、计算资源不足的场景,通过迁移学习节省预训练所需的计算资源,且收敛速度优于直接随机初始化。但其要求源任务与目标任务有较高的相似度,且两者的嵌入维度也需严格匹配。
3.位置编码
RNN网络通过隐藏状态的逐层传递来捕捉序列信息,而在Transformer模型中,注意力机制只能通过计算词与词之间的相关性来捕捉上下文信息,但忽略了词的位置顺序,所以需要位置编码为每个位置生成独特的向量,使模型能够区分不同位置的词,从而理解序列的时序或空间结构。
[1] 编码公式
偶数维度编码公式:
奇数维度编码公式:
其中
下图是一个六维位置编码的计算过程:
在位置编码的学习过程中,我主要有两点疑惑:
(1)为什么输入嵌入矩阵与位置编码直接相加,而不是拼接或其他操作?
答:在线性变换的作用下,相加可以视为一种特殊的拼接操作,如下图,当拼接操作中的
根据Transformer的原始论文《Attention Is All You Need》以及后续的实验复现结果来看,在训练数据丰富的情况下,加法操作简单且有效,因为Transformer模型拥有了足够多的参数,使其能够理解被加法操作融合后的词义与位置信息。
(2)位置编码的公式是怎么得到的?
见本文[4.3.2] “ 位置编码的演变历程 ” ,原文来自 https://zhuanlan.zhihu.com/p/454482273 ,本文做了更直观的总结与逻辑上的补充说明。
[2] 位置编码的演变历程
在这部分我会先用图片的形式直观展示位置编码的演变历程,之后再对各部分进行详细解释,属于 “总分” 结构。
(1)整型值标记法
将词汇0的位置标记为整数0,将词汇1的位置标记为整数1...... ,以此类推。
① 无界性:随着序列长度的增加,词汇数量越多,用于标记位置的整型值会越来越大。这会导致模型在推理阶段可能遇见比训练时所用的序列更长的序列,不利于模型的泛化。
(2)[0,1]范围标记法
将位置值的范围限制在[0, 1]之内,比如:3词汇序列的位置信息表示为[0, 0.5, 1] ; 4词汇序列的位置信息表示为[0, 0.33, 0.69, 1]
① 有界性:位置值的范围被限制在[0, 1]之内。
② 单调性:该方法中每个词汇的位置编码是单调递增的,正是由于 “[0,1]范围标记法” 既有界又单调的特性,每一次的编码步长都要根据序列长度进行调整,这会导致随着序列长度的改变,每个词汇的绝对位置不能固定,词汇与词汇间的距离(相对位置)也不能固定,模型在推理阶段可能遇见与训练时所用的序列长度不同的序列,序列中每个词汇的绝对位置与相对位置也随之变为一个陌生的数值,这会很不利于模型的泛化。
(3)二进制多维标记法
使用二进制标记词向量的各个维度,形成位置编码(该位置编码的维度等于词向量的维度,比如常见的512维词向量就可以支持长度为
① 有界性:从单个维度看,编码只有0或1两种结果,其被限制在[0, 1]之内,实现了有界性,解决了 “整型值标记法” 中由于推理序列长度超界而产生的泛化问题 。
② 单维周期性:从单个维度看,每个维度中0与1的规律变换可以视为一个周期函数,即单维周期性。周期性是对 “[0,1]范围标记法” 中单调性的改进,使得在有界的情况下,为序列中每个词汇提供固定的绝对位置与相对位置成为可能。但单维的周期性很容易导致不同位置的词汇出现编码重合的问题,所以我们采用多维不同频来缓解重合问题。
③ 多维不同频:从多个维度看,每个维度之间01变换的频率不同(以上图为例:维度2中,01变换频率最快,该维度对应的周期函数的周期最短;维度0中,01变换频率最慢,该维度对应的周期函数的周期最长)。正是这种频率上的差异,使得不同维度下的周期函数能够进行差异化表达,(同频多维表达的信息量等于单维,如同频三维只能表达000和111两种信息,与单维表达的0和1没有本质区别),既保证了周期性,又增加了信息容量,极大缓解了单维周期函数的重合问题。
单维周期性与多维不同频两者结合起来,使位置编码拥有了固定的绝对位置与相对位置,解决了 “[0,1]范围标记法” 中由于 “有界+单调” 限定位置必须可变而导致的泛化问题。
但是, “二进制多维标记法” 为每个词汇分配的虽然是固定的位置,但这些位置是离散分布的,导致位置信息的表达效果并不好。
④ 离散性:单维离散,每一个维度采用二进制作为周期函数,非0即1,没有中间量,这种不连续的跳变不符合真实情况(真实的位置信息往往是连续的),不利于模型学习。多维离散,相邻位置的词汇在空间上可能相距过远,(如相邻两词汇的位置编码从0111变为1000),不符合 “相邻词汇在多维空间上也相邻” 的期望,同样不利于模型学习。
(4)引入正弦函数sin
由前文可知,目前我们需要引入一个既有界又连续的周期函数,那我们最熟悉的正弦函数sin 就能同时满足这些条件。同时引入sin函数同样要保证 “多维不同频” 来缓解了单一维度中周期函数的重合问题,下面是其中一种引入方式:
其中
图例如下:
① 有界性
② 单维周期性
③ 多维不同频
④ 连续性:正弦函数sin 保证了单维的连续性,每一个单维上的连续性保证了多维空间上的连续性(这里的连续性非数学意义上的严格的连续性,仅仅指相邻词汇的位置编码在空间上也相邻的特性),符合真实情况的连续变换有助于提高模型的理解表达能力。
上述为引入sin函数的方法之一,我们可以从它的三维曲线图中发现,靠近序列前侧的词汇的位置编码(白黄色点标注于图中)与靠近序列后侧的词汇的位置编码(棕黑色点标注于图中)在这个三维空间上距离非常近,导致空间曲线形成闭环,反映在编码上就代表前后词汇的编码重合了。
其主要原因是低维周期函数的频率高周期短,而高维周期函数的频率低周期长,一旦最低频率的周期函数在其本身所处的维度下发生重合,那整体就可能重合。(”二进制多维标记法“ 就是一个最简单的多维不同频周期函数的例子,000、001、010......111,此时再加入一个词汇,其位置编码就又变为了000,与第一个词汇的位置编码重合)
这是多维周期函数在空间上的重合问题,本质是目前的维度数以及每个维度设计的频率差异不足以表示足够多的信息量来覆盖整个输入序列。这种问题在维度数少,各个维度的周期函数频率高(实际上,主要看频率最低的那个维度,即木桶效应),序列长度长时,更容易产生。
为了解决这个问题,在维度数和序列长度一定时,我们必须尽可能保证频率最低的那个维度的频率足够的小,所以Transformer模型使用了
其中,
(5)正余弦交替表示法
为了将相对位置通过线性变换显示的表示出来,我们将位置编码进一步更新为正余弦交替表示法。
期望公式:
其中
注:为了促成这种线性变换,我们对频率也作了一些微调,把原来的
最终形成了transformer中使用的位置编码的形式。
4.注意力机制
注意力机制是一种模仿人类视觉和认知系统的方法,它允许神经网络在处理输入数据时集中注意力于最重要的部分,从众多信息中选出对当前任务目标更加关键的信息。Transformer中的注意力机制实际上是对输入序列的不同位置分配不同的权重。
[1] 自注意力
自注意力的输入为:输入嵌入矩阵与位置编码之和。
自注意力的输出为:经过注意力加权融合了上下文信息的感知矩阵。
具体公式与流程如下:
(1)生成 Q、K、V 矩阵
查询矩阵 Query:
键矩阵 Key:
值矩阵 Value:
其中
假设输入的序列为 " are you ok ? ",计算图例如下(红框为单个词汇的演变过程,可见在生成 Q、K、V 矩阵阶段,词汇仅与权重矩阵交互,而词汇与词汇之间并不交互)
注:由于Transformer中残差连接的加法操作,注意力机制的输出与原始输入的维度必须相同,若维度在计算途中改变,则需在注意力机制之后,残差求和之前,添加一层线性变换用以统一维度。
(2)计算注意力权重(Q、K 矩阵)
注意力权重
其中
思考:为什么
矩阵是词向量的组合,矩阵的点积(矩阵点积就是矩阵乘法,注意与矩阵点乘区分,矩阵点乘一般指Hadamard积)可以拆分为向量的点积。假设有向量
(3)加权输出 (V矩阵)
自注意力的输出:上下文感知矩阵
[2] 掩码自注意力
掩码自注意力与自注意力机制的主要区别在注意力权重的计算上,掩码自注意机制引入掩码矩阵
掩码注意力权重:
掩码自注意力的输出:
其中
[3] 交叉注意力
交叉注意力是解码器与编码器交互的核心,其与自注意力的主要区别为Q、K、V矩阵的来源,如图所示:
从图中可见,查询矩阵Q来自解码器,键值矩阵K、V来自编码器。
交叉注意力的输出计算公式如下:
其中
该部分只有一点需要说明,为什么交叉注意力使用解码器的Q矩阵,编码器的K、V矩阵?
答:我们可以从transformer推理阶段的流程图解释。以翻译任务(将英文 “Are you ok?” 翻译为中文“你还好吗?”)为例。
我们在 [4—4—1 自注意力] 中探讨了为什么
[4] 多头注意力
为了增强模型捕捉多样化特征的能力,我们将Q,K,V 矩阵分别投影到不同的独立子空间中,我们将每一个独立的子空间称为一个头,不同的头将独立学习,关注不同的语义特征。(如对于 “猫现在坐在垫子上” 这句话,第一个头主要关注主谓关系,识别动作执行者 ”猫“ 与动作本身 ”坐“ ;第二个头主要关注空间位置信息,捕捉方位介词 ”上“ 与位置实体 ”猫“ ”垫子“ 的关系;第三个头主要关注时态信息 “正在”......)
下图为Transformer原论文中的多头注意力图例:
具体计算过程如下(假设总共分为n个头):
(1)Linear层:计算每个头的Q , K , V矩阵
其中
思考:为什么不直接把Q , K , V矩阵按照维度分割成n份,而是通过权重矩阵
如果直接分割为n份,那每一个头只能学习到原始信息分给它的那一小部分内容,每个头只能从局部信息中捕捉特征。但我们的目标是从全局信息中捕捉多样化的特征(局部特征),局部是修饰特征的,不是修饰原始信息的。而通过权重矩阵
(2)Scaled Dot_Prroduct Attention层:对每个头独立计算缩放点积注意力
其中
(3)Concat层:将各个头拼接并融合
其中
思考:仅拼接操作Concat 就已经能将head的维度还原为
拼接操作Concat 只是将不同头的输出简单堆叠,各头信息相互独立,缺乏交互,而
5.补充说明(敬请期待)
[1] 层归一化
(1)层归一化的作用
(2)层归一化公式
(3)为什么归一化会生成标准正态分布
(4)为什么标准正态分布有利于收敛
(5)为什么Transformer需要层归一化
(6)BN与LN
[2] 前馈神经网络
6.项目代码(敬请期待)
杂项 (读者止步)
维度0 维度1 维度2
词汇0
词汇1
词汇2
词汇3
(
(
[
[
[