目录
前言
书接上文。
一、大模型激活函数
参考大模型结构细节。
1、ReLU
原始的Transformer采用的是ReLU,后面的T5,OPT采用的激活函数也是ReLU,此时 FFN 可以表示为:
F
F
N
(
x
,
W
1
,
W
2
,
b
1
,
b
2
)
=
R
e
L
U
(
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x,W_{1},W_{2},b_{1},b_{2})=ReLU(xW_{1}+b_{1})W_{2}+b_{2}
FFN(x,W1,W2,b1,b2)=ReLU(xW1+b1)W2+b2
2、GeLU
GPT-1、GPT-2、GPT-3、BLOOM采用的激活函数就是GeLU(Gaussian Error Linear Unit)。GeLU的表达式如下:
G
e
L
U
(
x
)
=
x
Φ
(
x
)
GeLU(x)=x\Phi(x)
GeLU(x)=xΦ(x)
其中:
Φ
(
x
)
=
∫
−
∞
x
e
−
t
2
/
2
2
π
d
t
\Phi(x)=\int_{-\infty}^{x}\frac{e^{-t^{2}/2}}{\sqrt{2\pi}}dt
Φ(x)=∫−∞x2πe−t2/2dt
原论文中给出了GeLU的两个近似计算:
x
Φ
(
x
)
≈
x
σ
(
1.702
x
)
x\Phi(x)\approx x\sigma(1.702x)
xΦ(x)≈xσ(1.702x)
其中
σ
\sigma
σ是
s
i
g
m
o
i
d
sigmoid
sigmoid函数。或者:
x
Φ
(
x
)
≈
1
2
x
[
1
+
t
a
n
h
(
2
π
(
x
+
0.044715
x
3
)
)
]
x\Phi(x)\approx \frac{1}{2}x[1+tanh(\sqrt\frac{2}{\pi}(x+0.044715x^{3}))]
xΦ(x)≈21x[1+tanh(π2(x+0.044715x3))]
此时 FFN 可以表示为:
F
F
N
(
x
,
W
1
,
W
2
,
b
1
,
b
2
)
=
G
e
L
U
(
x
W
1
+
b
1
)
W
2
+
b
2
FFN(x,W_{1},W_{2},b_{1},b_{2})=GeLU(xW_{1}+b_{1})W_{2}+b_{2}
FFN(x,W1,W2,b1,b2)=GeLU(xW1+b1)W2+b2
3、GLU
GLU Variants Improve Transformer提出,可以利用门控线形单元:GLU(Gated Linear Units)对激活函数进行改进。首先,GLU的基本形式是:对输入做双线性变换(多了一个矩阵 V),并且其中一个添加
s
i
g
m
o
i
d
sigmoid
sigmoid变换:
G
L
U
(
x
,
W
,
V
,
b
,
c
)
=
σ
(
x
W
+
b
)
⊗
(
x
V
+
c
)
GLU(x,W,V,b,c)=\sigma(xW+b)\otimes(xV+c)
GLU(x,W,V,b,c)=σ(xW+b)⊗(xV+c)
此时 FFN 可以表示为:
F
F
N
(
x
,
W
1
,
W
2
,
V
,
b
1
,
b
2
,
c
)
=
(
σ
(
x
W
1
+
b
1
)
⊗
(
x
V
+
c
)
)
W
2
+
b
2
FFN(x,W_{1},W_{2},V,b_{1},b_{2},c)=(\sigma(xW_{1}+b_{1})\otimes(xV+c))W_{2}+b_{2}
FFN(x,W1,W2,V,b1,b2,c)=(σ(xW1+b1)⊗(xV+c))W2+b2
4、GeGLU
将GLU中的
s
i
g
m
o
i
d
sigmoid
sigmoid换成GeLU激活函数,就得到了GLU的一个变体:GeGLU,GLM-130B采用的激活函数就是GeGLU,具体表达式如下所示:
G
e
G
L
U
(
x
,
W
,
V
,
b
,
c
)
=
G
e
L
U
(
x
W
+
b
)
⊗
(
x
V
+
c
)
GeGLU(x,W,V,b,c)=GeLU(xW+b)\otimes(xV+c)
GeGLU(x,W,V,b,c)=GeLU(xW+b)⊗(xV+c)
此时 FFN 可以表示为:
F
F
N
(
x
,
W
1
,
W
2
,
V
,
b
1
,
b
2
,
c
)
=
(
G
e
L
U
(
x
W
1
+
b
1
)
⊗
(
x
V
+
c
)
)
W
2
+
b
2
FFN(x,W_{1},W_{2},V,b_{1},b_{2},c)=(GeLU(xW_{1}+b_{1})\otimes(xV+c))W_{2}+b_{2}
FFN(x,W1,W2,V,b1,b2,c)=(GeLU(xW1+b1)⊗(xV+c))W2+b2
5、SwiGLU
将GLU中的
s
i
g
m
o
i
d
sigmoid
sigmoid换成另一种激活函数,就得到了GLU的又一个变体:SwiGLU,LLaMA采用的激活函数就是SwiGLU,具体表达式如下所示:
S
w
i
G
L
U
(
x
,
W
,
V
,
b
,
c
)
=
S
w
i
s
h
β
(
x
W
+
b
)
⊗
(
x
V
+
c
)
SwiGLU(x,W,V,b,c)=Swish_{\beta}(xW+b)\otimes(xV+c)
SwiGLU(x,W,V,b,c)=Swishβ(xW+b)⊗(xV+c)
此时 FFN 可以表示为:
F
F
N
(
x
,
W
1
,
W
2
,
V
,
b
1
,
b
2
,
c
)
=
(
S
w
i
s
h
β
(
x
W
1
+
b
1
)
⊗
(
x
V
+
c
)
)
W
2
+
b
2
FFN(x,W_{1},W_{2},V,b_{1},b_{2},c)=(Swish_{\beta}(xW_{1}+b_{1})\otimes(xV+c))W_{2}+b_{2}
FFN(x,W1,W2,V,b1,b2,c)=(Swishβ(xW1+b1)⊗(xV+c))W2+b2
其中,
S
w
i
s
h
β
(
x
)
=
x
⋅
σ
(
β
x
)
Swish_{\beta}(x)=x\cdot\sigma(\beta x)
Swishβ(x)=x⋅σ(βx),
β
\beta
β是指定的常数,一般为1。相较于原始的ReLU激活函数,由于涉及到多一维度的线性表示,所以会面临着带来参数量新增和计算量增加。而LLaMA中怎么克服这一点的呢?LLaMA是把SwiGLU中的
W
1
、
W
2
、
V
W_{1}、W_{2}、V
W1、W2、V的矩阵维度从
(
d
i
m
,
d
i
m
)
(dim, dim)
(dim,dim)变成
(
d
i
m
,
2
3
d
i
m
)
(dim, \frac{2}{3}dim)
(dim,32dim),从而打平参数量和计算量。
二、位置编码
1、旋转位置编码
旋转位置编码(Rotary Position Embedding,RoPE)来源于苏剑林的Rotary Transformer。传统的位置编码通常是在输入时与token embedding进行加和,在进行后续Attention计算时,公式如下:
Q
K
T
=
X
W
Q
⋅
W
K
T
X
T
+
X
W
Q
⋅
W
K
T
P
T
+
P
W
Q
⋅
W
K
T
X
T
+
P
W
Q
⋅
W
K
T
P
T
O
=
A
⋅
V
=
A
⋅
(
X
W
V
+
P
W
V
)
\begin{aligned} QK^{T}&=XW_{Q}\sdot W_{K}^{T}X^{T}+XW_{Q}\sdot W_{K}^{T}P^{T}+PW_{Q}\sdot W_{K}^{T}X^{T}+PW_{Q}\sdot W_{K}^{T}P^{T}\\ O&=A\sdot V=A\sdot(XW_{V}+PW_{V}) \end{aligned}
QKTO=XWQ⋅WKTXT+XWQ⋅WKTPT+PWQ⋅WKTXT+PWQ⋅WKTPT=A⋅V=A⋅(XWV+PWV)
其中
A
=
s
o
f
t
m
a
x
(
Q
K
T
d
k
)
A=softmax(\frac{QK^{T}}{\sqrt{d_{k}}})
A=softmax(dkQKT)是注意力矩阵,
X
X
X是输入的token embedding,
P
P
P是position embedding。
事实上,位置向量不一定非要加在输入的token embedding上才能起作用,由上式可知,只要在
Q
Q
Q、
K
K
K矩阵上加上位置编码,同样可以作用在注意力矩阵
A
A
A上,进而作用在
V
V
V上。旋转位置编码就是采用的这种思想。
- 传统位置编码:Bert和Transformer。
- Bert是可训练位置编码,缺点是不具备任何的外推性质,输入长度设定之后,无法改变;
- Transformer是三角式位置编码,缺点是不具备远程衰减性,虽然位置编码的内积具备远程衰减性( p i T p i + k p_{i}^{T}p_{i+k} piTpi+k随着 k k k的增大,有衰减趋势),但是上式中的 p i W Q ⋅ W K T p i + k T p_{i}W_{Q}\sdot W_{K}^{T}p^{T}_{i+k} piWQ⋅WKTpi+kT不具备衰减性,再论大模型位置编码及其外推性(万字长文)。
- 旋转位置编码公式:对于
Q
Q
Q的第
m
m
m个向量
q
q
q、
K
K
K的第
n
n
n个向量
k
k
k(
m
m
m和
n
n
n是索引,从0开始),通过以下方法注入位置编码:
- 二维:假定词嵌入维度是2维。
f ( q , m ) = ( c o s ( m θ ) − s i n ( m θ ) s i n ( m θ ) c o s ( m θ ) ) ( q 1 q 2 ) = x m W q e i m θ f(q,m)= \begin{pmatrix} cos(m\theta) & -sin(m\theta) \\ sin(m\theta) & cos(m\theta) \end{pmatrix} \begin{pmatrix} q_{1} \\ q_{2} \end{pmatrix} =x_{m}W_{q}e^{im\theta} f(q,m)=(cos(mθ)sin(mθ)−sin(mθ)cos(mθ))(q1q2)=xmWqeimθ
f ( k , n ) = ( c o s ( n θ ) − s i n ( n θ ) s i n ( n θ ) c o s ( n θ ) ) ( k 1 k 2 ) = x n W k e i n θ f(k,n)= \begin{pmatrix} cos(n\theta) & -sin(n\theta) \\ sin(n\theta) & cos(n\theta) \end{pmatrix} \begin{pmatrix} k_{1} \\ k_{2} \end{pmatrix} =x_{n}W_{k}e^{in\theta} f(k,n)=(cos(nθ)sin(nθ)−sin(nθ)cos(nθ))(k1k2)=xnWkeinθ
其中, q = ( q 1 q 2 ) q=\begin{pmatrix} q_{1} \\ q_{2} \end{pmatrix} q=(q1q2)是 Q Q Q的第 m m m个向量, k = ( k 1 k 2 ) k=\begin{pmatrix} k_{1} \\ k_{2} \end{pmatrix} k=(k1k2)是 K K K的第 n n n个向量, f ( q , m ) f(q,m) f(q,m)、 f ( k , n ) f(k,n) f(k,n)分别是经过旋转位置编码后的 q q q和 k k k。可以发现,旋转位置编码其实就是对 q q q和 k k k分别乘以了一个旋转矩阵(向量乘以旋转矩阵后,模(向量大小)不变,方向改变),这就是为什么叫做旋转式位置编码的原因。此时 Q K T QK^{T} QKT的计算公式为(仅以 q q q和 k k k相乘为例):
( q 1 q 2 ) ( c o s ( ( m − n ) θ ) − s i n ( ( m − n ) θ ) s i n ( ( m − n ) θ ) c o s ( ( m − n ) θ ) ) ( k 1 k 2 ) \begin{pmatrix} q_{1} & q_{2} \end{pmatrix} \begin{pmatrix} cos((m-n)\theta) & -sin((m-n)\theta) \\ sin((m-n)\theta) & cos((m-n)\theta) \end{pmatrix} \begin{pmatrix} k_{1} \\ k_{2} \end{pmatrix} (q1q2)(cos((m−n)θ)sin((m−n)θ)−sin((m−n)θ)cos((m−n)θ))(k1k2) - 多维:上面的计算是假定词嵌入维度是2维,而对于
d
≥
2
d\ge2
d≥2的通用情况,则是将
q
q
q向量中的元素按照两两一组分组,每组应用同样的旋转操作,具体计算公式如下:
f ( q , m ) = ( c o s ( m θ 0 ) − s i n ( m θ 0 ) 0 0 ⋯ 0 0 s i n ( m θ 0 ) c o s ( m θ 0 ) 0 0 ⋯ 0 0 0 0 c o s ( m θ 1 ) − s i n ( m θ 1 ) ⋯ 0 0 0 0 s i n ( m θ 1 ) c o s ( m θ 1 ) ⋯ 0 0 ⋮ ⋮ ⋮ ⋮ ⋱ ⋮ ⋮ 0 0 0 0 ⋯ c o s ( m θ d / 2 − 1 ) − s i n ( m θ d / 2 − 1 ) 0 0 0 0 ⋯ s i n ( m θ d / 2 − 1 ) c o s ( m θ d / 2 − 1 ) ) ( q 0 q 1 q 2 q 3 ⋮ q d − 2 q d − 1 ) f(q,m)= \begin{pmatrix} cos(m\theta_{0}) & -sin(m\theta_{0}) & 0 & 0 & \cdots & 0 & 0 \\ sin(m\theta_{0}) & cos(m\theta_{0}) & 0 & 0 & \cdots & 0 & 0 \\ 0 & 0 & cos(m\theta_{1}) & -sin(m\theta_{1}) & \cdots & 0 & 0 \\ 0 & 0 & sin(m\theta_{1}) & cos(m\theta_{1}) & \cdots & 0 & 0 \\ \vdots & \vdots & \vdots & \vdots & \ddots & \vdots & \vdots \\ 0 & 0 & 0 & 0 & \cdots & cos(m\theta_{d/2-1}) & -sin(m\theta_{d/2-1}) \\ 0 & 0 & 0 & 0 & \cdots & sin(m\theta_{d/2-1}) & cos(m\theta_{d/2-1}) \\ \end{pmatrix} \begin{pmatrix} q_{0} \\ q_{1}\\ q_{2}\\ q_{3}\\ \vdots\\ q_{d-2}\\ q_{d-1} \end{pmatrix} f(q,m)= cos(mθ0)sin(mθ0)00⋮00−sin(mθ0)cos(mθ0)00⋮0000cos(mθ1)sin(mθ1)⋮0000−sin(mθ1)cos(mθ1)⋮00⋯⋯⋯⋯⋱⋯⋯0000⋮cos(mθd/2−1)sin(mθd/2−1)0000⋮−sin(mθd/2−1)cos(mθd/2−1) q0q1q2q3⋮qd−2qd−1
其中, θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=10000−2j/d, j ∈ { 0 , 1 , … , d / 2 − 1 } j\in \{0,1,\dots,d/2-1\} j∈{0,1,…,d/2−1}。 k k k的计算类似,这里不予展示。 - 高效计算:由于上述旋转矩阵的稀疏性,所以直接用矩阵乘法来实现会很浪费算力,推荐通过下述方式来实现RoPE:
f ( q , m ) = ( q 0 q 1 q 2 q 3 ⋮ q d − 2 q d − 1 ) ⊗ ( c o s ( m θ 0 ) c o s ( m θ 0 ) c o s ( m θ 1 ) c o s ( m θ 1 ) ⋮ c o s ( m θ d / 2 − 1 ) c o s ( m θ d / 2 − 1 ) ) + ( − q 1 q 0 − q 3 q 2 ⋮ − q d − 1 q d − 2 ) ⊗ ( s i n ( m θ 0 ) s i n ( m θ 0 ) s i n ( m θ 1 ) s i n ( m θ 1 ) ⋮ s i n ( m θ d / 2 − 1 ) s i n ( m θ d / 2 − 1 ) ) f(q,m)= \begin{pmatrix} q_{0} \\ q_{1}\\ q_{2}\\ q_{3}\\ \vdots\\ q_{d-2}\\ q_{d-1} \end{pmatrix}\otimes \begin{pmatrix} cos(m\theta_{0}) \\ cos(m\theta_{0}) \\ cos(m\theta_{1}) \\ cos(m\theta_{1}) \\ \vdots \\ cos(m\theta_{d/2-1}) \\ cos(m\theta_{d/2-1}) \\ \end{pmatrix}+ \begin{pmatrix} -q_{1} \\ q_{0}\\ -q_{3}\\ q_{2}\\ \vdots\\ -q_{d-1}\\ q_{d-2} \end{pmatrix}\otimes \begin{pmatrix} sin(m\theta_{0}) \\ sin(m\theta_{0}) \\ sin(m\theta_{1}) \\ sin(m\theta_{1}) \\ \vdots \\ sin(m\theta_{d/2-1}) \\ sin(m\theta_{d/2-1}) \\ \end{pmatrix} f(q,m)= q0q1q2q3⋮qd−2qd−1 ⊗ cos(mθ0)cos(mθ0)cos(mθ1)cos(mθ1)⋮cos(mθd/2−1)cos(mθd/2−1) + −q1q0−q3q2⋮−qd−1qd−2 ⊗ sin(mθ0)sin(mθ0)sin(mθ1)sin(mθ1)⋮sin(mθd/2−1)sin(mθd/2−1) - 直观展示:论文中有个很直观的图片展示了旋转变换的过程。
- 内积计算:
< f ( q , m ) , f ( k , n ) > = < f q ( x m , m ) , f k ( x n , n ) > = g ( x m , x n , m − n ) = R e [ ( x m W q ) ( x n W k ) ∗ e i ( m − n ) θ ] \begin{aligned} <f(q, m),f(k,n)>=<f_{q}(x_{m},m),f_{k}(x_{n},n)>=g(x_{m},x_{n},m-n)=Re[(x_{m}W_{q})(x_{n}W_{k})^{*}e^{i(m-n)\theta}] \end{aligned} <f(q,m),f(k,n)>=<fq(xm,m),fk(xn,n)>=g(xm,xn,m−n)=Re[(xmWq)(xnWk)∗ei(m−n)θ] - 远程衰减:RoPE形式上和传统transformer的三角式位置编码有点相似,只不过三角式位置编码是加性的,而RoPE可以视为乘性的。在
θ
i
\theta_{i}
θi的选择上,RoPE 同样沿用了三角式位置编码的方案,即
θ
j
=
1000
0
−
2
j
/
d
\theta_{j}=10000^{-2j/d}
θj=10000−2j/d,
j
∈
{
0
,
1
,
…
,
d
/
2
−
1
}
j\in\{0,1,\dots,d/2-1\}
j∈{0,1,…,d/2−1},它可以带来一定的远程衰减性。如下图所示:
从图中我们可以看到随着相对距离的变大,内积结果有衰减趋势的出现。因此,选择 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=10000−2j/d,确实能带来一定的远程衰减性。论文中还试过以 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=10000−2j/d为初始化,将 θ j \theta_{j} θj视为可训练参数,然后训练一段时间后发现 θ j \theta_{j} θj并没有显著更新,因此干脆就直接固定 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=10000−2j/d了。 - RoPE实践:后续看看LLaMA、ChatGLM的源码。旋转位置编码RoPE源码-ChatGLM系列
-
ChatGLM:ChatGLM是二维位置编码,每个 q q q、 k k k向量前一半的位置添加一种位置编码,后一半位置添加另一种位置编码,每一种位置编码都融合旋转位置编码;
- 细节:ChatGLM在执行旋转位置编码时,采用的是如下的变换方式,没有按照传统的RoPE模式。注意,这里的
d
d
d是前一半位置的维度大小。
- 细节:ChatGLM在执行旋转位置编码时,采用的是如下的变换方式,没有按照传统的RoPE模式。注意,这里的
d
d
d是前一半位置的维度大小。
-
ChatGLM2:ChatGLM2取消了二维位置编码,每个 q q q、 k k k向量只有前一半的位置添加了旋转位置编码,后一半的位置不做任何处理;旋转位置编码的计算方式同ChatGLM;
-
ChatGLM3:基本和ChatGLM2保持一致;
-
LLaMA:实现了传统的RoPE模式(苏剑林版本的旋转位置编码)。
-
- 优缺点:
- 优点:RoPE是通过绝对位置编码实现相对位置编码,优点是这种方法不仅可以处理位置信息,还可以处理距离信息,因为旋转操作可以很好地反映出元素之间的相对位置关系;
- 缺点:缺点是它需要更多的计算资源,因为旋转操作比简单的向量加法更复杂。
- 参考资料:十分钟读懂旋转编码(RoPE)、一文看懂LLaMA中的旋转式位置编码。
- 二维:假定词嵌入维度是2维。
2、长上下文外推方案
- 背景:虽然RoPE理论上可以编码任意长度的绝对位置信息,但是实验发现RoPE仍然存在外推问题,即测试长度超过训练长度之后,模型的效果会有显著的崩坏,具体表现为困惑度等指标显著上升。对此,就有很多人提出了如何扩展LLM的Context长度,力争通过非常少的长文本微调,就可以让已有的LLM处理长文本。
- 原始公式:上文介绍的RoPE原始公式。
f ( q / k , m ) = f q / k ( x m , m , θ i ) = x m W q / k e i m θ i \begin{aligned} f(q/k, m)=f_{q/k}(x_{m},m,\theta_{i})=x_{m}W_{q/k}e^{im\theta_{i}} \end{aligned} f(q/k,m)=fq/k(xm,m,θi)=xmWq/keimθi - 通用公式:长下文外推方案,基本是对
g
(
m
)
,
h
(
θ
i
)
g(m),h(\theta_{i})
g(m),h(θi)采用不同形式。
f q / k ( x m , g ( m ) , h ( θ i ) ) \begin{aligned} f_{q/k}(x_{m},g(m),h(\theta_{i})) \end{aligned} fq/k(xm,g(m),h(θi)) - 方案:
- Position Interpolation(PI):位置插值/线性内插。
- 背景:简单粗暴,均匀拉伸上下文长度到预训练窗口内;
- 公式:
L
L
L是原始上下文长度,
L
′
L^{'}
L′是扩展上下文长度。
g ( m ) = m L L ′ h ( θ i ) = θ i \begin{aligned} &g(m)=m\frac{L}{L^{'}}\\ &h(\theta_{i})=\theta_{i} \end{aligned} g(m)=mL′Lh(θi)=θi
- NTK-Aware Interpolation:非线性缩放,介于直接外推和线性内插之间的平滑方法。
- 背景:PI损失了低维的信息,采用高频(低维)外推,低频(高维)内插;
- 公式:
α
=
L
′
L
\alpha=\frac{L^{'}}{L}
α=LL′,
d
d
d是隐藏层维度。
g ( m ) = m h ( θ i ) = ( 10000 ∗ α d d − 2 ) − 2 i d \begin{aligned} &g(m)=m\\ &h(\theta_{i})=(10000*\alpha^{\frac{d}{d-2}})^{-\frac{2i}{d}} \end{aligned} g(m)=mh(θi)=(10000∗αd−2d)−d2i - 说明: i = 0 i=0 i=0时,与 α \alpha α无关,所以也就是直接外推;当 i = d / 2 − 1 i=d/2-1 i=d/2−1时,则变成了线性内插方案。
- NTK-by-parts Interpolation:基于波长的分段插值策略,NTK-Aware Interpolation升级版。
- 背景:向量的不同分量,他们对网络的影响有所不同(低频表示相对位置,高频表示绝对位置),需要进行区分;
- 公式:
α
=
L
′
L
\alpha=\frac{L^{'}}{L}
α=LL′,
r
(
i
)
=
L
λ
i
r(i)=\frac{L}{\lambda_{i}}
r(i)=λiL,
λ
i
=
2
π
θ
i
\lambda_{i}=\frac{2\pi}{\theta_{i}}
λi=θi2π是波长,实验表明,对于LLaMA系列模型,
β
1
=
1
\beta_{1}=1
β1=1,
β
2
=
32
\beta_{2}=32
β2=32,效果最好。
g ( m ) = m h ( θ i ) = ( 1 − γ ( r ( i ) ) θ i α ) + γ ( r ( i ) ) θ i γ ( r ( i ) ) = { 0 if r ( i ) < β 1 1 if r ( i ) ≥ β 2 r ( i ) − β 1 β 2 − β 1 otherwise \begin{aligned} &g(m)=m\\ &h(\theta_{i})=(1-\gamma(r(i))\frac{\theta_{i}}{\alpha})+\gamma(r(i))\theta_{i}\\ &\gamma(r(i))= \begin{cases} 0& \text{if} \ \ \ r(i)<\beta_{1}\\ 1& \text{if} \ \ \ r(i)≥\beta_{2}\\ \frac{r(i)-\beta_{1}}{\beta_{2}-\beta_{1}}& \text{otherwise} \end{cases} \end{aligned} g(m)=mh(θi)=(1−γ(r(i))αθi)+γ(r(i))θiγ(r(i))=⎩ ⎨ ⎧01β2−β1r(i)−β1if r(i)<β1if r(i)≥β2otherwise - 说明:
- 如果维度 i i i的波长 λ i \lambda_{i} λi远小于上下文长度 ,就不插值只外推;
- 如果波长 λ i ≥ \lambda_{i}≥ λi≥上下文长度,就只插值不外推;
- 中间的部分就同时存在两种,类似NTK-aware interpolation。
- Dynamic NTK interpolation:动态适配插值比例, NTK-Aware Interpolation升级版。
- 背景:无论线性插值还是NTK-Aware Interpolation,都是通过使用一个固定的系数,对原RoPE做了一个缩放,这样会有一些局限,已解码的长度还没有达到训练长度时,就使用 α \alpha α来修改base,可能带来一些损失;
- 公式:
α
=
l
L
\alpha=\frac{l}{L}
α=Ll,
α
^
=
m
a
x
(
1
,
α
)
\hat{\alpha}=max(1,\alpha)
α^=max(1,α),
L
L
L是原始上下文长度,
l
l
l是当前上下文长度。
g ( m ) = m h ( θ i ) = ( 10000 ∗ α ^ d d − 2 ) − 2 i d \begin{aligned} &g(m)=m\\ &h(\theta_{i})=(10000*\hat{\alpha}^{\frac{d}{d-2}})^{-\frac{2i}{d}} \end{aligned} g(m)=mh(θi)=(10000∗α^d−2d)−d2i
- YaRN:Yet another RoPE extensioN method,NTK-by-parts插值技术结合温度系数缩放。
- 背景:无论是Position Interpolation还是NTK类方法,本质都是通过减小旋转弧度,降低旋转速度,来达到长度扩展的目的。这将导致位置之间的旋转弧度差距变小,向量之间的距离变得比原来更近,向量之间的点乘变大,破坏模型原始的注意力分布;
- 公式:
α
=
L
′
L
\alpha=\frac{L^{'}}{L}
α=LL′,
g
(
m
)
g(m)
g(m)和
h
(
θ
i
)
h(\theta_{i})
h(θi)的公式和NTK-by-parts是一致的,只是在计算注意力分数时,增加温度系数。
q m T k n d → q m T k n t d , 1 t = 0.1 ln α + 1 \begin{aligned} \frac{q_{m}^{T}k_{n}}{\sqrt{d}}\rightarrow\frac{q_{m}^{T}k_{n}}{t\sqrt{d}},\sqrt{\frac{1}{t}}=0.1\ln\alpha+1 \end{aligned} dqmTkn→tdqmTkn,t1=0.1lnα+1
- Position Interpolation(PI):位置插值/线性内插。
三、模型结构综述
模型名称 | 模型结构 | 上下文长度扩展方案 |
---|---|---|
Qwen2.5 | 嵌入层:nn.Embedding QwenBlock: RMSNorm +Attention +RMSNorm +MLP 归一化层: RMSNorm lm_head: nn.Linear | YaRN |
GLM-4 | nn.Embedding GLMBlock: RMSNorm +Attention +RMSNorm +MLP 归一化层: RMSNorm lm_head: nn.Linear | - |
LLaMA3.3 | nn.Embedding LLaMABlock: RMSNorm +Attention +RMSNorm +MLP 归一化层: RMSNorm lm_head: nn.Linear | YaRN |
DeepSeek-V3 | 嵌入层:nn.Embedding DeepSeekBlock: RMSNorm +Attention(MLA) +RMSNorm +MLP(MoE) 归一化层: RMSNorm lm_head: nn.Linear | YaRN |
Internlm3 | 嵌入层:nn.Embedding InternlmBlock: RMSNorm +Attention +RMSNorm +MLP 归一化层: RMSNorm lm_head: nn.Linear | - |
模型名称 | 模型结构 | 训练方式 |
---|---|---|
InternVL-2.5-8B | Internlm2.5-7B + InternViT | stage1: MLP训练 stage1.5: ViT+MLP训练 stage2: ViT+MLP+LLM训练 |
MiniCPM-V-2.6-8B | SigLip-400M + Qwen2-7B | - |
MiniCPM-o-2.6-8B | SigLip-400M + Whisper-medium-300M + ChatTTS-200M + Qwen2.5-7B | stage1: 视觉/音频训练 stage2: 全模态训练 stage3: 全模态SFT+DPO |
Qwen2.5-VL | Qwen2.5 + ViT | stage1: ViT训练 stage2: 全参数训练 stage3: SFT+DPO,冻结ViT |
四、Decoder-only模型
1、生成任务
- 有条件文本生成:进行文本生成任务时,给定前置的生成条件,例如输入是:给定文本内容:春天真美好,进行故事续写;
- 无条件文本生成:进行文本生成任务时,不给定前置的生成条件,例如输入是:写一篇作文。
2、推理流程
- Casual LM:
- 原始输入构成:对于类GPT模型,无论是有条件文本生成任务,还是无条件文本生成任务,都是将原始输入整体喂入模型;
- 新输入构成:一个一个的生成token,生成的token会拼接在原始输入后面,构成新的输入喂入模型,继续生成新的token;
- Attention计算:输入之间满足Mask Attention机制(后面的token可以看见前面的token,前面的token无法看到后面的token);
- token生成:新token的生成机制,是将输出层的最后一列logits拿去做全词表分类;而最终选取哪个词进行输出,有多种方式,参考下面的解码生成方式。
- Prefix LM:
- 原始输入构成:对于类GLM模型,无论是有条件文本生成任务,还是无条件文本生成任务,都是将原始输入整体喂入模型;
- 新输入构成:一个一个的生成token,生成的token会拼接在原始输入后面,构成新的输入喂入模型,继续生成新的token;
- Attention计算:输入之间满足Prefix Attention机制(原始输入token之间可以互相看见,新拼接的token只能看见前面的token,看不到后面的token);
- token生成:新token的生成机制,是将输出层的最后一列logits拿去做全词表分类;最终选取哪个词进行输出,有多种方式,参考下面的解码生成方式。
3、解码生成方式
- Greedy Search:贪婪搜索。
- 方式:每个时间步都选择概率最大的词;
- 参数设置:
do_sample = False, num_beams = 1
; - 缺点:
- 生成文本重复;
- 不支持生成多条结果。 当
num_return_sequences
参数设置大于1时,代码会报错,说greedy search不支持这个参数大于1。
- Beam Search:束搜索,对贪心策略的一种改进,当num_beams = 1时会退化成贪心搜索策略。
- 方式:每个时间步选择概率最高的num_beams个词;
- 参数设置:
do_sample = False, num_beams > 1
; - 缺点:虽然结果比贪心搜索更流畅,但是仍然存在生成重复的问题。
- Top-K sampling:
- 方式:每个时间步,会保留top-k个token,然后对top-k个token的概率重新归一化,最后在重新归一化后的这k个token中进行采样;
- 参数:
do_sample = True, num_beams = 1
,设定top_k
; - 缺点:在分布陡峭的时候仍会采样到概率小的token,或者在分布平缓的时候只能采样到部分可用token;
- Top-P sampling:
- 方式:每个时间步,按照token出现的概率由高到底排序,当概率之和大于top-p的时候,就不取后面的样本了。然后对取到的这些token的概率重新归一化后,进行采样;
- 参数:
do_sample = True, num_beams = 1
,设定top-p
,在0-1之间取值; - 备注:top-p采样方法往往与top-k采样方法结合使用,每次选取两者中最小的采样范围进行采样,可以减少预测分布过于陡峭时采样到极小概率token的几率。
- Temperature sampling:
- 方式:温度调整严格来说不是一种采样方式,只是一种概率改变方法,需要与其他采样方式相结合才可以发挥作用。具体来说,温度调整通过在
s
o
f
t
m
a
x
softmax
softmax中添加温度系数
t
t
t来改变每个token输出的概率:
s o f t m a x ( x i ) = e x i / t ∑ j = 1 n e x j / t softmax(x_{i})=\frac{e^{x_{i}/t}}{\sum_{j=1}^{n}e^{x_{j}/t}} softmax(xi)=∑j=1nexj/texi/t
其中, n n n是词表大小, x j x_{j} xj表示词表中每个token对应的logits值, x i x_{i} xi是当前token的logits值, t t t是温度系数。 - 参数:
temperature
; - 备注:由上面公式可知,当
t
t
t趋近于0时,会增加token之间概率的差值,所有token的概率分布会更陡峭,如下图所示。如果采用top-p采样模式,那么最终输出的token可选范围会缩小(因为只需要更少的token,概率和即可满足条件),模型输出更稳定;当
t
t
t趋近于无穷大时,会降低大概率token之间概率的差值,所有token的概率分布会更平缓,也就是说,最终输出的token可选范围会增大,模型输出随机性更大。
- 方式:温度调整严格来说不是一种采样方式,只是一种概率改变方法,需要与其他采样方式相结合才可以发挥作用。具体来说,温度调整通过在
s
o
f
t
m
a
x
softmax
softmax中添加温度系数
t
t
t来改变每个token输出的概率:
五、三种训练方式
- Pre-training(预训练):是利用各种语料训练一个语言模型,这个模型已经拥有足够的基础知识,具备强大的基础能力;
- Fine-Tuning(微调):是在Pre-trained的模型后面加一些简单的类似全连接的神经网络,用业务数据再训练一下,学习业务知识;
- Post-training(后训练):可以包括SFT和RLHF两部分,参考大语言模型 Pre-training 和 Post-training 范式的最新趋势;
- Contiune Pre-training(增量预训练):是预训练的二阶段,预训练是从0到1的训练一个语言模型,Contiune Pre-training是在预训练后的模型上,再进行一次预训练。参考浅谈Continue Pre-training。
总结
了解LLM,再看这一篇就够了!!!