在之前的博客中,讨论了LLMs的训练数据及数据调度方法。这篇博客将聚焦于LLMs的另一个重要方面:模型架构。由于模型架构的复杂性和多样性,我将写一篇双语博客。这个版本是中文的,明天将发布英文版本(数据部分也将以中文发布一次)。这篇博客基于Datawhale学习文件和一个写的很好的综述。
Transformer架构已成为创建各种LLMs的主导框架,使得语言模型的参数规模能够扩展到数百亿甚至数千亿。总体而言,当前LLMs的主要架构大致可分为三种类型:编码器-解码器、因果解码器和前缀解码器。在下面的总结表中可以看到:
对于预训练LLMs来说,训练的稳定性是一个重大挑战。标准化是一种广泛使用的策略,用于解决这一问题并稳定神经网络的训练。在最初的Transformer中,使用了LayerNorm。然而,已经提出了几种高级的标准化技术作为LayerNorm的替代方案,例如RMSNorm和DeepNorm。
除了标准化方法,标准化位置在LLM中也起着关键作用。通常有三种标准化位置的选择:post-LN、pre-LN和sandwich-LN。
在前馈网络中正确设置激活函数对于获得良好性能至关重要。GeLU激活在现有的LLM中被广泛使用。此外,GeLU的变体在最新的LLM中也被使用,特别是SwiGLU和GeGLU的变体,在实践中通常能够获得更好的性能。然而,与GeLU相比,它们在前馈网络中需要额外的参数(约50%)。
由于Transformer中的自注意力模块是置换等变的,因此使用位置嵌入(PE)来注入序列的绝对或相对位置信息进行建模。
绝对位置嵌入:在最初的Transformer中,使用了绝对位置嵌入。在编码器和解码器的底部,绝对位置嵌入被添加到输入嵌入中。在最初的Transformer中提出了绝对位置嵌入的两个变体,即正弦和学习位置嵌入,后者在现有的预训练语言模型中通常被使用。
相对位置嵌入:与绝对位置嵌入不同,相对位置嵌入是基于键和查询之间的偏移量生成的。Transformer-XL引入了相对位置嵌入的一种流行变体。注意分数的计算已经修改,引入了与相对位置对应的可学习嵌入。
旋转位置嵌入 (RoPE): 它涉及根据每个关键或查询的绝对位置设置特定的旋转矩阵。可以使用相对位置信息计算键和查询之间的得分。RoPE将查询和关键中的每个连续对元素组合为一个维度,从而使原始长度为d的嵌入得到 d 2 \frac{d}{2} 2d? 维度。对于每个维度 i ∈ { 1 , . . . , d 2 } i \in \{1,...,\frac{d}{2}\} i∈{1,...,2d?},涉及的元素对将根据旋转角度 t ? θ i t·\theta_i t?θi? 进行旋转,其中 t t t 表示位置索引, θ i \theta_i θi?是该维度中的基础。在正弦位置嵌入之后,RoPE将基础 θ i \theta_i θi? 定义为基数b(默认设置为10000)的幂:
Θ = { θ i = b ? 2 ( i ? 1 ) / d ∣ i ∈ { 1 , 2 , … , d / 2 } } \Theta = \{\theta_i = b^{-2(i-1)/d}|i\in \{1,2,\dots,d/2\}\} Θ={θi?=b?2(i?1)/d∣i∈{1,2,…,d/2}}
此外,一项最近的研究定义了每个维度所需旋转一个周期(2π)的距离,称为波长:
λ i = 2 π b 2 ( i ? 1 ) / d = 2 π / θ i \lambda_i = 2 \pi b^{2(i-1)/d}= 2\pi/\theta_i λi?=2πb2(i?1)/d=2π/θi?
由于其出色的性能和长期衰减特性,RoPE已被广泛应用于最新的LLMs中。基于RoPE,xPos增强了Transformer的平移不变性和长度外推能力。在旋转角度向量的每个维度上,xPos引入了一种特殊的指数衰减,随着基数的增长而减小,从而在距离增加时减轻了训练过程中的不稳定性。
因为其重要性和复杂性,有一篇博客说的挺好的,可以看看这个博客: https://zhuanlan.zhihu.com/p/647109286。【注意:大量数学推导】
ALiBi: 该方法旨在增强Transformer的外推能力。类似于相对位置嵌入,它使用基于键和查询之间距离的惩罚来偏置注意力得分。与相对位置嵌入方法不同,ALiBi中的惩罚分数是预定义的,没有任何可训练参数。实证结果表明,ALiBi在长序列上优于几种流行的位置嵌入方法。此外,已经证明ALiBi还可以增强BLOOM中的训练稳定性。
注意力机制是Transformer的关键部分,使序列中的tokens能够相互作用并计算输入和输出序列的表示。
总之,现有文献建议采用以下详细配置以实现更强的泛化能力和训练稳定性:选择预RMSNorm进行层归一化,并选择SwiGLU或GeGLU作为激活函数。此外,建议不要在嵌入层后立即使用LN,因为这可能会导致性能下降。关于位置嵌入,RoPE或ALiBi是更好的选择,特别是对于长序列的更好性能。
END