通俗易懂的LLM(下篇)

前言

  书接上文。

一、大模型激活函数

  参考大模型结构细节

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π et2/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 W1W2V的矩阵维度从 ( d i m , d i m ) (dim, dim) (dimdim)变成 ( 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=XWQWKTXT+XWQWKTPT+PWQWKTXT+PWQWKTPT=AV=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(dk QKT)是注意力矩阵, 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} piWQWKTpi+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((mn)θ)sin((mn)θ)sin((mn)θ)cos((mn)θ))(k1k2)
    • 多维:上面的计算是假定词嵌入维度是2维,而对于 d ≥ 2 d\ge2 d2的通用情况,则是将 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)0000sin(mθ0)cos(mθ0)000000cos(mθ1)sin(mθ1)0000sin(mθ1)cos(mθ1)000000cos(mθd/21)sin(mθd/21)0000sin(mθd/21)cos(mθd/21) q0q1q2q3qd2qd1
      其中, θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=100002j/d j ∈ { 0 , 1 , … , d / 2 − 1 } j\in \{0,1,\dots,d/2-1\} j{0,1,,d/21} 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)= q0q1q2q3qd2qd1 cos(mθ0)cos(mθ0)cos(mθ1)cos(mθ1)cos(mθd/21)cos(mθd/21) + q1q0q3q2qd1qd2 sin(mθ0)sin(mθ0)sin(mθ1)sin(mθ1)sin(mθd/21)sin(mθd/21)
    • 直观展示:论文中有个很直观的图片展示了旋转变换的过程。
      在这里插入图片描述
    • 内积计算
      < 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,mn)=Re[(xmWq)(xnWk)ei(mn)θ]
    • 远程衰减:RoPE形式上和传统transformer的三角式位置编码有点相似,只不过三角式位置编码是加性的,而RoPE可以视为乘性的。在 θ i \theta_{i} θi的选择上,RoPE 同样沿用了三角式位置编码的方案,即 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=100002j/d j ∈ { 0 , 1 , … , d / 2 − 1 } j\in\{0,1,\dots,d/2-1\} j{0,1,,d/21},它可以带来一定的远程衰减性。如下图所示:
      在这里插入图片描述
      从图中我们可以看到随着相对距离的变大,内积结果有衰减趋势的出现。因此,选择 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=100002j/d,确实能带来一定的远程衰减性。论文中还试过以 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=100002j/d为初始化,将 θ j \theta_{j} θj视为可训练参数,然后训练一段时间后发现 θ j \theta_{j} θj并没有显著更新,因此干脆就直接固定 θ j = 1000 0 − 2 j / d \theta_{j}=10000^{-2j/d} θj=100002j/d了。
    • RoPE实践:后续看看LLaMA、ChatGLM的源码。旋转位置编码RoPE源码-ChatGLM系列
      • ChatGLM:ChatGLM是二维位置编码,每个 q q q k k k向量前一半的位置添加一种位置编码,后一半位置添加另一种位置编码,每一种位置编码都融合旋转位置编码;

        • 细节:ChatGLM在执行旋转位置编码时,采用的是如下的变换方式,没有按照传统的RoPE模式。注意,这里的 d d d是前一半位置的维度大小。
          在这里插入图片描述
      • ChatGLM2:ChatGLM2取消了二维位置编码,每个 q q q k k k向量只有前一半的位置添加了旋转位置编码,后一半的位置不做任何处理;旋转位置编码的计算方式同ChatGLM;

      • ChatGLM3:基本和ChatGLM2保持一致;

      • LLaMA:实现了传统的RoPE模式(苏剑林版本的旋转位置编码)。

    • 优缺点
      • 优点:RoPE是通过绝对位置编码实现相对位置编码,优点是这种方法不仅可以处理位置信息,还可以处理距离信息,因为旋转操作可以很好地反映出元素之间的相对位置关系;
      • 缺点:缺点是它需要更多的计算资源,因为旋转操作比简单的向量加法更复杂。
    • 参考资料十分钟读懂旋转编码(RoPE)一文看懂LLaMA中的旋转式位置编码

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)=mLLh(θ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αd2d)d2i
      • 说明: i = 0 i=0 i=0时,与 α \alpha α无关,所以也就是直接外推;当 i = d / 2 − 1 i=d/2-1 i=d/21时,则变成了线性内插方案。
    • 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α^d2d)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} d qmTkntd qmTknt1 =0.1lnα+1

三、模型结构综述

模型名称模型结构上下文长度扩展方案
Qwen2.5嵌入层:nn.Embedding
QwenBlock:RMSNorm+Attention+RMSNorm+MLP
归一化层:RMSNorm
lm_head:nn.Linear
YaRN
GLM-4nn.Embedding
GLMBlock:RMSNorm+Attention+RMSNorm+MLP
归一化层:RMSNorm
lm_head:nn.Linear
-
LLaMA3.3nn.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-8BInternlm2.5-7B + InternViTstage1: MLP训练
stage1.5: ViT+MLP训练
stage2: ViT+MLP+LLM训练
MiniCPM-V-2.6-8BSigLip-400M + Qwen2-7B-
MiniCPM-o-2.6-8BSigLip-400M + Whisper-medium-300M + ChatTTS-200M + Qwen2.5-7Bstage1: 视觉/音频训练
stage2: 全模态训练
stage3: 全模态SFT+DPO
Qwen2.5-VLQwen2.5 + ViTstage1: 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可选范围会增大,模型输出随机性更大。
      在这里插入图片描述

五、三种训练方式

  • 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,再看这一篇就够了!!!

### Ollama概念及其实例 #### 什么是Ollama? Ollama是一个专注于简化大型语言模型(LLM)部署和服务的平台,旨在使开发人员能够更轻松地集成和利用强大的AI能力到应用程序中[^1]。此平台不仅提供了多种预训练的语言模型供选择,还支持自定义微调功能,允许用户根据特定需求调整模型性能。 #### 通俗解释 想象一下,如果想要让机器具备人类般的交流能力和解决问题的能力,就需要给它安装一个非常聪明的大脑——这就是所谓的“大模型”。然而,直接使用这样的大脑并不容易,因为它体积庞大且难以管理。这时就轮到了像Ollama这样的工具出场了;它们就像是专门为这些超级智慧体设计的操作系统,使得普通人也能方便快捷地把这种先进的人工智能技术融入自己的项目里去。 #### 实例展示 为了更好地理解如何使用Ollama来创建基于LLMs的应用程序,下面给出了一段简单的Python代码片段作为例子: ```python from ollama import Model # 加载预训练好的基础模型 model = Model.load('base_model') # 对输入文本进行预测处理 response = model.predict("请问今天的天气怎么样?") print(response) # 如果有特殊场景下的数据集,则可以进一步对该模型做针对性优化 custom_data = ["明天会下雨吗", "后天适合外出游玩么"] fine_tuned_model = model.finetune(custom_data) ``` 这段代码展示了怎样加载一个预先准备好的基本版本的LLM,并通过`predict()`函数获取对于简单自然语言查询的回答。此外,还可以看到当面对某些具体应用场景时,可以通过提供额外的数据来进行更加细致化的参数调节(`finetune()`)操作,从而提高模型在实际任务上的表现效果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值