首页IT科技meta分析模板(Meta最新模型LLaMA细节与代码详解)

meta分析模板(Meta最新模型LLaMA细节与代码详解)

时间2025-09-18 02:24:45分类IT科技浏览4764
导读:0. 简介 今天介绍的内容是Facebook Meta AI最新提出的语言模型LLaMA,该模型声称以更小的体积,在多数任务上超越了GPT-3的性能。...

0. 简介

今天介绍的内容是Facebook Meta AI最新提出的语言模型LLaMA               ,该模型声称以更小的体积                      ,在多数任务上超越了GPT-3的性能               。

模型相关项目已经开源:

https://github.com/facebookresearch/llama

论文地址:https://scontent-tpe1-1.xx.fbcdn.net/v/t39.8562-6/333078981_693988129081760_4712707815225756708_n.pdf?_nc_cat=108&ccb=1-7&_nc_sid=ad8a9d&_nc_ohc=ov6yTHfLfNQAX-guxqd&_nc_ht=scontent-tpe1-1.xx&oh=00_AfDMyTEYewg-cHT9_4_sUaW5h0gqrqwjcNMylD9HtVFCWA&oe=6401C9E2

由于模型较大        ,目前的设备暂时没有办法支持进一步的实验               ,但是其模型代码已经开源                      ,所以可以先通过代码了解一下模型结构上的一些细节        ,今天就针对github上放出的代码       ,了解一下模型的细节                      。

此外                      ,该模型其实就是transformer做了一点细节上的改进               ,真正更有价值的工作应该在数据和训练方面        。通过阅读代码       ,可以对transformer的基础构造进行复习                      ,并且了解大模型如何在多卡上分布推理               。

由于该项目源码几乎没有注释               ,这就肯定会给很多同学阅读时带来困扰,所以本文顺带着就把代码部分详细的介绍一下                      。

1. 项目环境依赖

此项目给出的环境依赖只有4个:

torch fairscale fire sentencepiece

其中torch不比多讲                      ,fairscale是用来做GPU分布的                      ,一般是当使用DDP仍然遇到超显存的问题时使用fairscale        。目前fairscale我还没有试过,在下文的源码介绍中               ,我会用torch中对应的基础网络替代fairscale中的结构层进行介绍       。fire是一个命令行工具                      ,用或者不用他都可以        ,sentencepiece是用于tokenizer的工具包               ,会在tokenizer部分简单介绍                      。

2. 模型细节

由于该模型就是用的transformer的decoder                      ,所以在结构上它与GPT是非常类似的        ,只是有一些细节需要注意一下               。

2.1 RMS Pre-Norm

关于Pre-Norm和Post-Norm是神经网络中老生常谈的话题       ,目前比较普遍的被大家接受的结论是                      ,相同的深度条件下               ,Post-Norm的效果要优于Pre-Norm       ,因为Pre-Norm实际上相当于通过了一个更宽的网络而非更深的网络                      ,所以在同等深度下               ,Pre-Norm的实际效果相当于一个更浅却更宽的网络,详细的推理过程参考:https://spaces.ac.cn/archives/9009       。

然而在LLaMA中却采用了Pre-Norm                      ,或许是因为模型够深(7B                      ,13B,30B               ,65B的模型                      ,transformer layer数量分别为32        ,40               ,60                      ,80)        ,而Pre-Norm的恒等分支更加明显       ,有利于梯度的传播(这部分暂时没有想到很合理的解释                      ,如果有更好的理解               ,欢迎在评论区补充)                      。

RMS Norm(Root Mean Square Layer Normalization)       ,是一般LayerNorm的一种变体                      ,可以在梯度下降时令损失更加平滑               。

与layerNorm相比               ,RMS Norm的主要区别在于去掉了减去均值的部分(re-centering),只保留方差部分(re-scaling)                      ,从归一化的表达式上可以直观地看出:

一般的LN:

a

i

=

a

i

μ

σ

g

i

\overline{a}_i = \frac {a_i- \mu} \sigma g_i

ai=σaiμgi 其中                      ,

μ

=

1

n

i

=

1

n

a

i

\mu = \frac 1 n \sum_{i=1}^na_i

μ=n1i=1nai

σ

=

1

n

i

=

1

n

(

a

i

μ

)

2

\sigma= \sqrt {\frac 1 n \sum_{i=1}^n{{(a_i-\mu)}^2}}

σ=n1i=1n(aiμ)2

RMS Norm:

a

i

=

a

i

R

M

S

(

a

)

g

i

\overline{a}_i = \frac {a_i} {RMS(a)} g_i

ai=RMS(a)aigi

其中,

R

M

S

(

a

)

=

1

n

i

=

1

n

a

i

2

{RMS(a)}=\sqrt {\frac 1 n \sum_{i=1}^n{{a_i}^2}}

RMS(a)=n1i=1nai2

可以看到               ,二者的区别就在于有没有减去均值。至于RMS Norm为什么有用                      ,需要求梯度进行分析        ,感兴趣的同学可以阅读RMS Norm的论文                      。

2.2 SwiGLU激活函数

LLaMA采用SwiGLU替换了原有的ReLU                      。

采用SwiGLU的FNN               ,在论文中以如下公式进行表述:

F

F

N

s

w

i

G

L

U

(

x

,

W

,

V

,

W

2

)

=

(

S

w

i

s

h

1

(

x

W

)

x

V

)

W

2

FFN_{swiGLU}(x, W, V, W_2) = (Swish_1(xW)\otimes xV)W_2

FFNswiGLU(x,W,V,W2)=(Swish1(xW)xV)W2

其中                      ,

S

w

i

s

h

β

(

x

)

=

x

σ

(

β

x

)

Swish_\beta(x) = x\sigma(\beta x)

Swishβ(x)=xσ(βx), (Ramachandran et al., 2017.)

2.3 RoPE旋转位置编码

RoPE(Rotary Position Embedding)旋转位置编码        ,是苏剑林老师提出的一种旋转位置编码方法       ,其思想是采用绝对位置编码的形式                      ,实现相对位置编码。这一部分比较关键               ,如果不理解的话       ,后边的代码估计就看不懂了               。读懂RoPE涉及一点复变函数的基础知识                      ,不过如果你没有学过的话也没有关系                      。

位置编码对大模型而言尤为重要               ,因为既然是要训练大模型,那么长文本的表征和模型对于长文本的建模能力就显得非常重要        。(但是对于绝对位置编码                      ,我有一个直观地感受                      ,认为其本质上不适用于长文本的场景,因为它会直接导致模型的Embedding层被无限放大               ,并且由于数据分布在seq_len方向上通常是长尾的                      ,这又会必然导致绝对位置编码的矩阵在尾部会越来越稀疏        ,一方面造成资源浪费               ,另一方面这种表示方法直观上就很不利于模型的学习                      ,因为它与我们实际场景是有很大的矛盾的               。而RoPE虽然具有相对位置编码的性质        ,但是从代码部分可以看出       ,在构造的时候                      ,其也是受到了最大长度的限制的                      。关于这一点               ,我无法严谨得说明       ,只是一点个人的想法        。)       。

而RoPE的巧妙之处在于                      ,它既保留了绝对位置编码中的绝对位置信息               ,又保留了在内积运算下,对位置信息的相对性                      。

RoPE主要借助了复数的思想               。为了引入复数                      ,首先假设了在加入位置信息之前                      ,原有的编码向量是二维行向量

q

m

q_m

qm

k

n

k_n

kn
,其中

m

m

m

n

n

n
是绝对位置               ,现在需要构造一个变换                      ,将

m

m

m

n

n

n
引入到

q

m

q_m

qm

k

n

k_n

kn
中        ,即寻找变换:

q

m

~

=

f

(

q

,

m

)

,

k

n

~

=

f

(

k

,

n

)

\tilde {q_m} = f(q, m), \tilde{k_n} = f(k, n)

qm~=f(q,m),kn~=f(k,n)

考虑到Attention的核心计算是内积:

A

t

t

e

n

t

i

o

n

(

Q

,

K

,

V

)

=

s

o

f

t

m

a

x

(

Q

K

T

d

k

)

V

Attention(Q, K,V) = softmax(\frac {QK^T} {\sqrt{d_k}})V

Attention(Q,K,V)=softmax(dkQKT)V

所以               ,寻求的这个

f

(

)

f(*)

f()变换                      ,应该具有特性:

f

(

q

,

m

)

,

f

(

k

,

n

)

=

g

(

q

,

k

,

m

n

)

\langle f(q, m), f(k, n) \rangle = g(q, k, m-n)

f(q,m),f(k,n)⟩=g(q,k,mn)

这里直接说结论        ,寻求的变换就是

q

m

e

i

m

θ

q_me^{im\theta}

qmeimθ       ,也就是给

q

m

q_m

qm
乘以

e

i

m

θ

e^{im\theta}

eimθ
                      ,相应地               ,

k

n

k_n

kn
乘以

e

i

n

θ

e^{in\theta}

einθ
       。

具体的求解过程       ,请参考苏剑林老师的博客                      。

做了这样一个变换之后                      ,根据复数的特性               ,有:

q

m

,

k

n

=

R

e

[

q

m

k

n

]

\langle q_m, k_n \rangle = Re[q_mk^*_n]

qm,kn=Re[qmkn]

也就是,如果把二维向量看做复数                      ,那么它们的内积                      ,等于一个复数乘以另一个复数的共轭,得到的结果再取实部               。

带入上面的变换               ,也就有:

q

m

e

i

m

θ

,

k

n

e

i

n

θ

=

R

e

[

(

q

m

e

i

m

θ

)

(

k

n

e

i

n

θ

)

]

=

R

e

[

q

m

k

n

e

i

(

m

n

)

θ

]

\langle q_me^{im\theta}, k_ne^{in\theta} \rangle = Re[(q_me^{im\theta}) (k_ne^{in\theta})^*] =Re[q_mk_n^*e^{i(m-n)\theta}]

qmeimθ,kneinθ=Re[(qmeimθ)(kneinθ)]=Re[qmknei(mn)θ]

这样一来                      ,内积的结果就只依赖于

(

m

n

)

(m-n)

(mn)        ,也就是相对位置了。换言之               ,经过这样一番操作                      ,通过给Embedding添加绝对位置信息        ,可以使得两个token的编码       ,经过内积变换(self-attn)之后                      ,得到结果               ,是受它们位置的差值       ,即相对位置影响的                      。

于是对于任意的位置为

m

m

m的二维向量

[

x

,

y

]

[x, y]

[x,y]
                      ,把它看做复数               ,乘以

e

i

m

θ

e^{im\theta}

eimθ
,而根据欧拉公式                      ,有:

e

i

m

θ

=

cos

m

θ

+

i

sin

m

θ

e^{im\theta}=\cos{m\theta}+i\sin{m\theta}

eimθ=cosmθ+isinmθ

于是上述的相乘变换也就变成了:

(

x

+

i

y

)

e

i

m

θ

=

(

x

cos

m

θ

y

sin

m

θ

)

+

i

(

x

sin

m

θ

+

y

cos

m

θ

)

(x+iy)e^{im\theta}=(x\cos{m\theta}-y\sin{m\theta})+i(x\sin{m\theta}+y\cos{m\theta})

(x+iy)eimθ=(xcosmθysinmθ)+i(xsinmθ+ycosmθ)

把上述式子写成矩阵形式:

f

(

(

q

,

%2

创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!

展开全文READ MORE
phpcms怎么用(phpcms读不到缓存怎么办) linearx m53麦克风(libsvm liblinear 使用心得)