去年搞了半年的大语言模型的应用开发。大语言模型的应用技术门槛相对较低,不过发挥第一性原理,抽点时间再回顾一下跟模型架构相关的理论知识。
简略的一些纪要,不会做详细的讲解。
0.故事线
现在开源大模型的框架(Llama、GLM、Qwen等)大多是基于GPT的变种,所以GPT的架构到底长什么样?虽然GPT脱颖而出了,但是其同时期的经典框架和它的区别又是什么?要知道这些,需要往下看一层:transformer(因为这些都是基于transformer的上层建筑),所以transformer又长什么样子?我们再往下看,transformer里最核心的结构是attention,它长什么样子?优势又是什么?同时transformer又是一种seq2seq架构,那么什么又是seq2seq?基于这些追问,我们反过来重头开始看。
1. Seq2Seq
Seq2Seq(Sequence to Sequence)是一种在自然语言处理(NLP)领域常用的模型架构,尤其在机器翻译、文本摘要、问答系统和对话系统中非常流行。Seq2Seq模型的核心目标是将一个序列转换为另一个序列,这两个序列的长度可以不同,这使得它非常适用于上述任务。该架构最初由Ilya Sutskever, Oriol Vinyals和Quoc V. Le在2014年提出(原文arxiv地址),主要目的是解决当时DNN不能很好的处理输出长度不一致的监督学习任务。该架构定义两个核心组成部分:编码器和解码器。
- 编码器(encoder):编码器的任务是接受输入序列,并将其转换为固定大小的上下文向量(或称为“状态向量”)。这个上下文向量被认为是输入序列的内部表示,包含了输入数据的关键信息。
- 解码器(decoder):解码器的任务是接受编码器产生的上下文向量,并基于这个向量生成输出序列。在开始生成过程时,解码器通常接受一个特殊的起始符号,以指示开始生成序列。然后,它逐步生成输出序列中的每个元素,直到遇到特殊的结束符号(<EOS>),表示序列生成完成。
可以想像成encoder主要做表示学习,把原始input表示成高维抽象特征并且学习其空间分布(固定维度);然后decoder进行自回归生成(采用beam search,解释见下),基于encoder的表征做预测。Ilya的原文中encoder和decoder都是用的LSTM。同时,原文还用了将input倒置的trick(比如 正常句子是abc,但是先颠倒成cba作为模型的input),目的是减少长期依赖的距离。后来有了attention的使用,解决了传统RNN的长时记忆问题,所以这种trick现在基本不使用了。
【beam search】
Beam Search 是一种启发式图搜索算法,常用于自然语言处理中的序列生成任务,特别是在使用序列到序列(Seq2Seq)模型进行机器翻译、文本摘要、语音识别等任务时。与简单的贪心搜索不同,它在每一步并不只是选择概率最高的一个词,而是保留多个最有可能的候选选项,这些候选选项被称为beam。比如目标是最大化:
其中是当前的表征空间(状态特征)。为了最大化左式,可以采用贪心算法(也是beam=1的情况),即在右式中每一个t的时候,都取当前条件概率最大的那个。但是这样很可能只能得到局部最优,但是计算效率较高。在此基础上我们可以牺牲一点计算效率,然后最优更优的可能性:比如在每一步t,保留可能组合中的top2高的条件概率对应的和,直到<EOS>(停止符,end of sentences)这便是beam=2的情况。相同的,可以每一步都保留n个当前概率最高的可能情况,就是beam=n。所以beam趋于的时候,就是全空间搜索,必定得到全局最优,但是相应的计算效率就很低了。
2. Attention
通俗的说,attention机制是模拟人类注意力聚焦特性而设计的一种计算单元,它允许模型在处理数据时“关注”到序列的某些部分更多一些,而不是平等的对待每个元素。设想你阅读一本书你的大脑并不是平等地关注每一个单词。相反,你会根据当前句子的上下文和你想要理解的内容,集中注意力于某些词语上。在传统的序列处理模型中,模型是将所有信息压缩进一个固定大小的向量中,不管序列有多长,这就好比要你在听完一个长故事后,只用一个句子来复述它,这显然很难做到既准确又全面。而attention允许模型在生成每个输出时“回头看”输入序列的不同部分,从而根据需要关注更相关的信息。这就像在复述故事的每个部分时,都能重新参考原文,确保你的复述既准确又相关。
从技术层面来讲,注意力机制可以被看作是一个加权求和的过程,其中加权系数决定了在生成输出时对输入序列的不同部分的“关注”程度。这个机制通常被集成到序列处理模型中,不止transformer,像RNN、LSTM也都能使用这个。注意力机制的核心是一个可学习的权重分配过程,这个过程会为输入序列中的每个元素(如单词或字符)分配一个权重,表明每个元素对当前输出元素(如翻译中的单词)的重要性。这些权重随后被用来计算加权平均的上下文向量,该向量将被用作生成当前输出的额外输入。
假设我们有一个输入序列和一个当前的query(比如decoder中生成的上一状态或输出),attention的计算可以分为以下几步:
- query, key, value:首先,对于序列中的每个元素,我们通过可学习的参数转换它们为key()和value()。同时,当前的query()也通过相似的变换得到。
- 注意力得分的计算 :然后,我们计算与每个之间的相似度,即注意力得分。这个得分经典的通过点积得到(其中是query的维度)。不过注意力得分也有其他的设计,比如加性得分等。
- 归一化:注意力分数通过softmax函数进行归一化,以确保所有的权重加起来等于1。这些归一化的分数称为注意力权重。
- 加权平均:最后,计算value()的加权平均,权重为对应的注意力权重。得到的加权和被称为上下文向量,它是输入序列的加权表示,突出了对当前输出最重要的部分。
下面左图是通用的attention机制,右图是经典的点积attention。
![]() |
![]() |
---|
attention里query()、key()和value()可以是完全不同的3个特征向量。对某个query()进行相似度查询,查询对象列表就是整个key列表,检索到相关的key后映射到其value,然后做一个聚合(加权求和)。有点像比如菜市场里所有菜的名字和价格构成了和,然后你这次想做一个番茄炒蛋,需要买菜,那么你带着这个目的去菜市场,番茄炒蛋就是本次的。先q和K进行相似度检索,那么番茄炒蛋最需要的是番茄、鸡蛋,这两个权重很大(相似度得分高);然后还需要可能洋葱、小葱或者其他的配菜(相似度得分稍低);那么对于菜市场里有的其他的比如猪肉、鱼这种完全用不到的,在这次买菜(query)里相似度得分就接近0。相似度检索完后找到需要买的菜的价格(),然后按权重计算本次买菜行为需要的成本就可以。
【self-attention】
attention机制中有一个很特殊的情况,就是,一个输入同时承担了三种角色,这就是自注意力机制。在NLP任务中,所说的attention基本都是self-attention,因为这些任务(比如机器翻译)中一般输入都只有一个东西,就是句子转换成的词向量组。它们自己和自己玩儿,自我探索结构词和句子语义间的关系😄。
【multi-head attention】
简单的讲就是多个attention的联合。在实际中,给定一组QKV,我们肯定通过注意机制可以捕捉更多的知识,例如捕获这个序列中各种范围的依赖关系(较短范围与较长范围)。因此,直觉上让注意力机制联合使用QKV的不同表示子空间可能是更好的方式,就是说创建多个attention,然后最后再concat起来。
在实际操作中,multi-head attention的实现一般会使用一个大的组合权重张量来代表所有的head,执行一次大的矩阵乘法,然后将其分割成每个head的矩阵。从理论上讲,这不影响模型输出,因为代数运算是相同的。
3.transformer
最原始的Seq2Seq还是基于RNN的,其不足:
- encoding过程中长距离衰减问题,当句子过长,越往后的hidden state蕴含的前面的信息就会越弱。
- 同样的,decoding过程也是一样的长距离衰减问题
- 解码阶段缺乏对编码阶段各个词的直接利用。简单说就是:机器翻译领域,解码阶段的词和编码阶段的词有很强的映射关系,比如“爱”和“love”。但是seq2seq模型无法再译“love”时直接使用“爱”这个词的信息,因为在编码阶段只能使用全局信息。
attention的提出极大的改善了上面的问题,不过attention有个问题是没考虑顺序(这个带来另一个优势就是可以并行,不用像RNN只能串行)。
2017年Google发布了transformer架构,基于Seq2Seq(Encoder-Decoder),并且把RNN踢出了局,改为只用(Self-)Attention+FFNN(前馈神经网络)作为encoder、decoder的核心。所以这篇文章叫:Attention is all your need。
上一张经典图来展示其架构:
其序列位置信息的纳入是通过positional encoding的方式来进行的(解释见下面对应部分)。左边灰色框(self-attention + FFNN)是encoder,右边灰色框(masked self-attention + cross attention + FFNN)是decoder。原始transformer里encoder和decoder分别要堆叠6层(有点类似于从单层NN到深度NN,6只是个超参数)。encoder是一个AE(autoencoding)模型,decoder是一个AR(autoregressive)模型。encoder进行的是上下文的理解,复杂特征空间表示学习;而相应的decoder进行一个一个按顺序的预测生成。所以可以看到encoder都是self-attention,到了decoder里的第二层是cross-attention,就是把encoder里学到的表示作为key和value,然后将第一层里的结果作为query。decoder里第一层里使用了mask掩码技巧(解释见下面对应部分)。
【positional encoding】
原文中用的是这种方法,使用函数,直接将位置索引值映射到维向量上。公式为:
其中为序列中位置索引值,是位置编码向量中的位置索引。比如在原序列中的第2个位置就被编码成(假设位置向量是10维):
除了上述的编码方法,还可以使用embedding的手段,就是说像word embedding一样,为序列中每个绝对位置也赋予一个连续、低维、稠密的向量表示。
【FFNN】
这儿前馈神经网络由两个线性变换(全连接层)和一个非线性激活函数组成:
【masked self-attention】
在decoder里的第一层,目的是在训练的时候不使用未来信息,因为attention可以并行,训练时可以同时进行query和key的点积计算,不过在一句话中当前位置的词query只能跟该位置之前的词key进行注意力得分计算(而在encoder里也可以和这个位置之后的词进行,因为encoder是在做语义的理解)。之后mask的技巧也衍生出不同的掩码方式,这种最原始只向左看齐就是causal mask,此外还有prefix mask等。
4.Pre-trained Models
经典的NLP领域预训练模型也不是照搬的transformer结构,参考这篇blog分为了以下3种流派:encoder-only(AE),decoder-only(AR)和encoder-decoder(Seq2Seq)。见下图:
decoder-only优缺点:
- 优势:
- 适合生成式任务。因为AR模型使用causal attention去预测下一个token,训练目标也更多以预测下一个词为主,所以天然的就更适合生成任务。
- 劣势:
- 只能适用于单向(正向或者逆向)上/下文预测任务,不适用于需要双向上下文的任务。
encoder-only优缺点:
AE模型更多是用于内容理解的任务,比如经典的BERT(填补缺失句子中的词信息+预测两个句子间是不是前后关系)。
- 优势:
- 可以同时用到上下文的信息,对词与词,句子与句子间的理解捕捉得更好。
- 劣势:
- 训练中会用到掩码标记
[mask]
,然而在真实的预测任务中不存在 - 独立性假设,假设了
[mask]
和[mask]
之间是相互独立的,这个和真实的情况也是有偏差的(同一个句子中这个mask已知之后会改变下一个mask预测的条件分布)
- 训练中会用到掩码标记
encoder-decoder:
同时兼具了AE和AR模型,这种通常用于处理一些需要在输入和输出间建立精确映射的任务,比如机器翻译、文本摘要等。在这些任务中,理解输入的精确内容并据此生成特定的输出是非常重要的。而基于这种架构训练出来的模型,一般只能应用于某种特定的任务。
从这3种架构流派看,encoder-only主打一个理解,decoder主打生成,encoder-decoder从理论上讲应该是最完美的。但是从实践来看,当前主流的LLM都是decoder-only框架,其原因也给一些主观的观点:
- decoder-only更“知行合一”,他的训练和预测的任务是一致的,更容易往“one for all”的去走,无论什么下游任务,都变成根据指令的生成任务(根据指令的自回归的next word prediction),通过SFT+RLHF来训练。
- encoder-only本身设计就是要搭配fine-tuning的,没办法很好的one for all(多个下游模型的fusion空间的对齐也很困难,至少对于当前来说成本很大)。encoder-decoder的精确度是最高的,同时也带来的弊端就是它只适用于specific的任务,它需要被泛化到通用的one for all的代价就更高。
- 想说timing这个点,其实也是成本导向,decoder-only逻辑上就是最容易先出成果的方向,其到one for all程度的应用实践所需的训练数据的获取、处理、训练时间都比encoder+FT框架更容易、更快。所以当前看decoder-only框架好像更好,可能也只是当下,decoder-only进入瓶颈期后说不定encoder类的框架也会卷出新的高度。当然也可能是跳出transformer的框架。世界总不缺创新的探险者。
【causal attention】
causal的意思是因果(掩码),也就是每个tokens只能关注到自己和自己左侧的tokens。因果两个字就说明了只能从前到后,意思是第二个字的表示应该包含第一个字的贡献,相反,第一个字的表示,不应该受到第二个字的影响,这就是因果,只有过去可以影响现在,现在不能再对过去产生影响。causal attention也就是带因果掩码的attention机制。
还有一种是prefix attention,其实也是causal的,相当于是对于已经吐出来的那部分subsentence已经是可以相互之间捕捉相关性的了(比如下图中的)。
与这些相对的是全部都可视的,一般在encoder里存在,相当于做语义理解,捕捉词与词,词与句子的关系,做这些表示学习的时候都是全可见的。
见下图(来自于paper:Exploring the Limits of Transfer Learning with a Unified
Text-to-Text Transformer):
4.1. BERT
pass
4.2. GPT
具体可以看这篇blog,讲得很好。我就只总结以下重点。
- GPT3使用了Sparse Attention(见下),提高计算效率。
- 自从GPT2开始,decoder的layer normalization位置提前了,原生的layer normalization在每次Attention 或者 FeedForward之后,GPT2提到了之前。然后在最后一次decoder之后,进入最后的Linear+Softmax之前增加了一词layer noramlization。
- decoder有12个。
- 每个decoder里multi-head attention有96个head。
最后贴一张blog里的手绘架构图,很强(可能看不清楚,建议下下来看或者去原文里看)。
【Sparse Attention】
最原始的GPT使用了sparse attention,这个是将attention进行了一些改造,主要是提高计算效率(会降低一些理论精度)。大概看一下我之前的这篇也有讲过这个。
推荐一篇很好的可视化blog:LLM visualization,用其中nano-gpt的例子很好的可视化讲解了类GPT的核心结构。
5. LLM
回到大语言模型上,截止目前,大部分的LLM都是采用decoder-only的transformer架构基础,然后在这个基础上做一些变化。这儿再展开讲一下decoder-only的核心架构,它是在原始transformer架构上,移除了以下两个部分:
- 整个encoder部分
- decoder中的encoder-decoder self-attention层。
![]() |
![]() |
---|
大语言模型(或者更广义的基础模型)的提出动机来自于两个事实:
- 大量丰富的非标注语料
- 标注数据的稀缺性
同时,传统大多数深度学习模型,需要大量的标注数据去解决一个表现良好的判别任务,表现得更显一个“局部领域的专家”。它们有一些很难被逾越的缺陷:
- 一些领域没有足够的标注数据。
- 每次新任务都必须重新建模,成本高。
与其每次去训练一个新模型,不如先预训练一个语言模型,然后在此模型的基础上通过一些方式去适配解决各种下游的语言任务。一种方式就是fine-tuning在更多数据上训练一个适合下游任务的模型;另一种更突破性的,就是使用零样本(zero-shot)/少样本(few-shot)推理。
零样本/少样本推理的过程被叫做prompting,其实就是通过指令让语言模型给出回答(这些指令被叫做prompt)。在训练GPT类模型的时候,其接收到的文本数据input一般都是类似于如下样子:
- "Translate this sentence to English:
=>" - "Summarize the following document:
=>"
这些以解决任务的指令input在大规模语料的学习下拥有了zero-shot(在没看过正确output的前提下也能进行作答)/few-shot(给定一些指令和对应指令的正确回答的例子然后进行作答)推理的能力。
要较好的实现以上的zero-shot/few-shot的能力,除了架构和数据,还有工程化很重要的一点:训练方式或者训练步骤。
- Tokenization
- Text Embedding
- Pre-training
- supervised fine-tuning(SFT)
- reinforcement learning with human feedba(RLHF)
下面对一些经典的LLM家族的架构进行说明,主要以推理视角,所以以架构为主;训练视角的元素,如训练方式和训练数据如无需要不做特别的说明。( 有时间将会持续更新。)
5.1. Llama
Llama基本采用了传统decoder-ony transformer的架构,但在以下3个地方进行的修改:
- Normalization。layer normaliztion改成了root mean square normalization(RMSNorm for short),这是一个简化版的LayerNorm,就是将LayerNorm里减去均值的操作省略了(所有的地方都变成了),同时还将线性转换中的需要学习的偏置项取消掉,公式:。实验验证以上简化后速度提升40%,效果几乎无损。此外,Llama还采用了pre-nromalization的设计,如GPT2里使用的一样,将normalization处理时机提前,如下图:
- Activation Function。Llama采用了SwiGLU替代传统的ReLU作为Feed Forward层的激活函数,这个激活函数使用门控单元,里面的包含了2个线性变换,所涉及的权重也是需要学习的,这是和一般的激活函数不同的地方。
采用SwiGLU激活的FFN可以表示成(no-bias形式):
- RoPE。在位置编码(positional embedding)上引用Rotary Positional Embedding,是一种结合了绝对位置编码和相对位置编码的技术。具体细节见这篇blog或者这篇知乎。使用RoPE可以在长序列上带来更好的位置嵌入效果。需要补充的是,RoPE是和self-attention同时进行的,所以不是跟传统的PE一样在Input Text Embedding的时候进行一次,而是在每个有self-attention的地方都需要运行。
在以上Llama的变化基础上,Llama还对架构进行了进一步修改,最关键就是采用了grouped-query attention来替代原始的multi-head attention。grouped-query attention介于multi-head attention和multi-query attention(由这篇paper提出,在PaLM模型里使用并得到较好实践效果)之间,3者关系如下图所示:
其中,multi-query attention的改变是在于在每个head之间共享了相同的,这使得推理的速度可以得到明显提升(以前上计算次的现在只需要1次)。但是提一下,训练速度上并无太大提升,原因是训练更大的开销在于梯度下降的计算和参数更新上。可见,grouped-query attention是将原始的个multi-head又分成了个小组,然后在小组间共享,相当于是在预测效果和推理速度之间做了一个trade-off。
此外,在多轮对话推理的优化上使用了Ghost Attention技术。
5.2. Falcon
Falcon依然采用的decoder-only causal transformer 架构。在传统基础上,进行了如下几处修改:
- Flash Attention。这是一个可以加速attention计算的算法优化,不过这个算法的核心不是在理论上降低计算复杂度(比如reformer、informer等),而是在硬件上,它重新制定了Attention计算在GPU上不同计算单元间的调度,以此来达到真实场景下的提速。GPU硬件上本人不是太行,对细节感兴趣的可以看这篇blog。实际运用中,FlashAttention可以对推理提一些速(10%-40%),但是效果感觉并不是那么惊人。
- RoPE embeddings。见Llama章节介绍。
- Multi-Query Attention。见Llama章节介绍。
- Parallel Attetnion and Feed-Forward layers。传统串行的attention+feed-forward不同,Falcon采用了并行的方式(我记得最初好像是由PaLM提出来的),相当于对于input,分别进行self-attention和feed-forward,然后再加起来(同时还需要加上原input,因为ResNet)。大概如下图:
5.3. ChatGLM
ChatGLM采用的是GLM架构,是一个挺有意思的架构。它的诞生其实是在LLM井喷之前,在预训练模型被Bert、GPT和T5三分天下的时候。GLM也是采用的decoder-only transformer,但是它与GPT很大的不同在于,它并不只是做NLG(next token prediction),同样的他还要做NLU(Bert的强项)。GLM巧妙的设计了一个机制,autoregressive blank filling,使得它在预训练的时候可以既做理解训练又做生成训练。机制如下(可以对照下面的官方案例图一起看):
- 对于收集到的某一条语料句子,首先从里面采样子句子(连续token),比如图中的sub-sentence1:和sub-sentence2:。
- 将原始句子分为两部分:
- PartA:挖掉采样子句子后剩下的原句子,并将挖掉的部分留空白用
[M]
表示。这儿即。 - PartB:刚才采样的子句子,这儿即。
- PartA:挖掉采样子句子后剩下的原句子,并将挖掉的部分留空白用
- 重排序列组合生成Input。先将PartB里的子句子shuffle随机排序,比如这儿sub-sentence2就变到了sub-sentence1前面,变成了。然后加上开始token(
[S]
)。最后将PartA和当前PartB拼接起来。Input就是。 - 给重排序后的序列进行位置编码,使用了2D-positional encoding。第一个位置编码是原始句子中的位置,填空的部分(
[M]
)用一个位置标记。第二个位置编码是对于PartB的子序列标记其原有的内在顺序。 - 将上述Input和位置编码放入GLM,进行双目标训练:完形填空(靠PartA)和下文生成(靠PartB)。所以其Attention掩码的设计就不是经典的causal mask,而是prefix mask。PartA是非causal的,相互之间可以看到,进行上下文理解,做完形填空。而PartB里就是causal的,做下文预测。从这儿可以感受一下,PartA就类似Bert,同时PartB的shuffle设计还将不同
[M]
之间变得非独立(克服了Bert里独立性的假设)。
![](https://lostlau.github.io/post-images/attention_to_gpt/chatglm.png)
除了以上最核心设计的区别,GLM在在原始的transformer架构上还:
- 更改了LayerNorm和ResNet的顺序。改为先LayerNorm后Add。
- 用单个线性层来进行最终token的预测
- 激活函数用GeLUs替代ReLU
5.4. Qwen
讲道理,在我已有的实践中,千问是用得比较多的,所以po一下它的家族系列:
目前开源社区里的主要是蓝色和紫色的部分,RLHF部分应该是千问商用API的😄。
看了千问的技术报告,架构上基本同Llama。一些小调整在于:
- embedding层和output层的权重矩阵分离(传统transformer应该是tied weights,就是这两个是共享的。Llama2里好像没有说这个)
- Input到QKV的转换加入了bias(很多是没有加的),即
架构之外,在推理上,关于长序列推理加入几个重要的training-free技术:
- dynamic NTK。具体可见这篇知乎文章
- LogN-Scaling。基于熵不变性为出发点的外推技术,推导可以看这篇blog
- window attention。类似于Sparse Attention,不过这儿只是在推理的时候才用到,训练的时候不用。将attention的计算只限定在一个固定窗口长度中。
5.5. Mixtral
Mixtral的出名是提出了一种新的行之有效(评估结果很好)的架构模组:MoE(Mixture of Experts)。我们先介绍原始的Mixtral-7B,然后再引出Mixtral-MoE(8✖7B)。
Mixtral-7B在架构上基本还是采用的Llama架构,在此基础上最核心的改变是使用sliding window attention(SWA,道理同sparse attention):
。
由于decoder blog一般都会重复很多次,所以虽然每次当前token的注意力都只在只限定在一个窗口里,但是一层一层传递的时候,这个token会受到较多前文的影响(指数增加,如上图最右边例子)。理论上说是这么一说,原文中window size设置的也只是最长回望上下文长度的一半😄。
推理性能上也做了两个调整,适配SWA:Rolling Buffer Cache和Pre-fill Chunking。都是在cache上的调整,具体可以见原文。
Mistral-7B架构上感觉很普通,但是也有不错的评估效果,我认为应该是在数据上做了不少文章。
在Mistral-7B基础上,该团队提出了MoE的模型(Mistral 8*7B),获得了较大的成功。Mistral-MoE提出了一种新的transformer decoder-only架构变种。将decoder从GPT开始一直沿用的[ Attention + Add&Norm -> FeedForward + Add&Norm ]中的FeedForward layer替换成了MoE layer,借鉴一下下图:
。
MoE首次提出是在20年(这儿),之前没什么名气。这个layer里主要包含两个东西:router和expert。MoE整体实现是个加权求和,router给出了加权的权重,expert给出求和的每个元素。所以,对于给定的Input ,有(这是个超参数)个experts的MoE层的output可以表示为:
这儿,表示gating network(即router)的维output中的第个(对应第个expert的权重),是第个expert network的output。
所谓的gating network 是用softmax计算得到的权重,但是这儿的softmax是取的top K(K为超参数)个元素的softmax:
相当于x先进行线性转换,在得到的向量里只取最大的前K个来进行softmax,只有前K个有权重(概率),后n-K个权重都为0。比如原文中是8个experts,每次只取前2个来进行softmax。可以想象成每一个入参都由8个专家审核,但是每次只会采纳2个专家的建议。
“专家的建议”则由SwiGLU激活单元表示(没有过多的解释,很好奇为什么不是SwiGLU的FFN🤔️)。
MoE最核心的就是以上了。整体感觉MoE没有什么复杂的操作,但是却实现了一个比较好的效果,就很“漂亮”。然后虽然名字叫Mixtral-8*7B,但是实际参数量并不是56B,只有47B,因为8个专家只有在expert network上各自独立参数,其他的在attention层、resnet、norm、router、output层都是共享的相同权重矩阵。