最近 ACL 2024 论文放榜,扫了下,SMoE(稀疏混合专家)的论文不算多,这里就仔细梳理一下,包括动机、方法、有趣的发现,方便大家不看论文也能了解的七七八八,剩下只需要感兴趣再看就好。
下面是列表,顺序大抵是个人兴趣程度排序。
1. DeepSeekMoE: Towards Ultimate Expert Specialization in Mixture-of-Experts Language Models
2. Harder Tasks Need More Experts: Dynamic Routing in MoE Models
3. XMoE: Sparse Models with Fine-grained and Adaptive Expert Selection
4. HyperMoE: Towards Better Mixture of Experts via Transferring Among Experts
5. Not All Experts are Equal: Efficient Expert Pruning and Skipping for Mixture-of-Experts Large Language Models
6. Multimodal Instruction Tuning with Conditional Mixture of LoRA
未完待续,大概还遗漏了一二三四篇,后续再加上 2024 年的一些 MoE 论文:
1. Let the Expert Stick to His Last: Expert-Specialized Fine-Tuning for Sparse Architectural Large Language Models
论文地址:
https://arxiv.org/abs/2401.06066
代码地址:
https://github.com/deepseek-ai/DeepSeek-MoE
首先是众所周知的 DeepSeekMoE。
1.1 动机
本文的动机偏直觉:
1)专家不够分化:以往的 MoE 模型专家数量很少,假如模型的知识很繁杂,也就是说涉及的领域很多的话, 即使每个专家处理相同数量的领域,平均分配下来,一个专家仍然要包含很多领域的知识,也就是专家不够“专”——所以增加专家数量,然后寄希望于模型分化吧。
2)专家有冗余:假设每个 token 只能选一个专家,又假设每个 token 都需要常识知识,那么结果就是不论选哪个专家,这个专家的参数里都有常识知识,因此有冗余了——最好的情况是有个专家专门负责提供常识知识,所有 token 都会用一下这个专家。
2.2 方法
看完了动机,想必大家也知道方法怎么做了:
1)增加专家数量。具体来说,是通过拆分专家——比如把一个拆成两个——来增加专家数量。
更具体点,主流的专家实际上就是个 FFN,FFN 实际上就是两个矩阵。假设这两个矩阵的大小分别是: 和 。如果要把这个专家拆分成两个专家,实际上就是把矩阵拆成两个 和 。相应的,假如原本一个 token 选择 top-1 专家来处理,拆成两个后,就变成选择 top-2 专家来出来。这样拆前和拆后,计算量和参数量是没有变化的。
碎碎念:实际上,计算量还是有变化的。 路由模块 原本从 N 个专家里面选择 1 个,现在要从 2N 里选择 2 个。如何快速计算专家的分数,如何快速排序,如何快速分发数据,还是有点讲究的。
好处是什么呢?不妨假设每个专家实际上是一个图书馆。原本只有 4 个图书馆,每个图书馆的藏书都不同。我们想要解决自己的问题,必须且只能选择一个图书馆,说不定我们要的某本书并不在我们要选的图书馆里。拆分后呢,就有了 16 个图书馆,这时候我们可以选择 4 个图书馆来查阅,那么图书的排列组合多样性更多了,我们的选择也更灵活了。
2)增设共享专家。也就是说,有的专家是必选的,除此以外,每个 token 按照自己的喜好,再来选择 top-k。比如有 64 个专家,那么第一个专家是所有 token 都要选的,除此以外,每个 token 还从剩下的 63 个里选择自己的 top-1 专家。实际上就是 top-2 啦。
碎碎念:实际上,正如文章所指出的,deepspeedmoe 在 22 年提出了这个设计。
有趣的现象:
在参数是 1.89B 时,DeepseekMoE 只用 0.24B 的参数,它的性能和 用上全部参数的 dense 模型不分伯仲。
和同样是 MoE 结构的 GShard 比,拆分专家可以使得模型激活更少的参数取得更好的性能。
02
Dynamic MoE
论文地址:
https://arxiv.org/abs/2403.07652
代码地址:
https://github.com/ZhenweiAn/Dynamic_MoE
2.1 动机
top-k 路由在 MoE 模型中被广泛使用。作者认为,简单的任务需要少专家,复杂的任务需要多专家,如果一视同仁,那么效率会低。因此,作者提出了基于阈值 threshold 的路由方法,让每个 token 可以动态选择 1 到 多个专家。
2.2 方法
众所周知,在 MoE 层,对于每个 token,它会对所有的专家打分(算是喜爱程度吧),而且分数经过 softmax 后,总和为 1。
方法很简单,一句话:先人工设置一个超参数阈值,t,为 0.4 。对于每个 token, 把所有专家按分数从大到小排列,然后选择排名前几的专家,使这些专家分数总和大于 t,也就是 0.4,剩下的专家就不选了。于是这就实现了动态路由。
举个例子,假如有场考试,我们的目标是拿到分数超过 60 分及格就好,那么为了速通考试,我们只需要挑选分值最大的题目做,做到总分超过 60,就可以尽快离场了。如果有个题目分值超过 60 分,那么只做一道题就行,这就是 top-1 了。
这有个隐患,考虑极端情况,专家的分数是均匀分布的。如果 t 设置为 0.5,这意味着就需要选择一半的专家来计算。为了避免这种情况,文章增加了一个损失函数,优化目标是让专家概率尽可能大——变得极端。
2.3 发现
在推理时,平均每个 token 激活的专家数量不超过 2 —— 应该损失函数的功劳吧。
在下游任务上,效果居然还比 top-2 好 —— 我猜测或许是训练初期每个 token 选了很多专家(>2,来自 Figure 3),间接让每个专家多训练了。
底层用到的专家更多,甚至会用 4 个,高层反而 1 个就够。
subtoken —— 那些 tokenize 之后的碎片 —— 需要的专家更多,还挺有趣,但不知道意味着什么。
03
XMoE
论文地址:
https://arxiv.org/abs/2403.18926
代码地址:
https://github.com/ysngki/XMoE
这篇文章,竟然,是上面两篇文章方法的并集。缘,妙不可言。但动机不同,分析也挺有趣。
3.1 动机
众所周知,FFN 可以写成 ,其中 是激活函数。
以前的工作发现,当 relu 是激活函数时,输出的向量有 80% 的元素是 0,这意味着第二个矩阵乘法有严重的计算浪费。
这个现象在 MoE 模型也存在,而且随着专家数量增大,浪费增加 —— 是不是有点像 deepseekmoe 的第一个动机。本文提出,参考以往工作,FFN 可以看成 memory network。浪费意味着有冗余的知识。类似于去图书馆,有很多没用的书。
所以方法就是 缩小专家,通过拆分 。
然而, 缩小专家之后,每个 token 选几个专家呢?多了浪费,少了性能下降。
没错,方法就是上面的 基于阈值的路由。
3.2 分析
缩的越小,效果越好,但是后面几乎没有增长。举个例子,缩小 8 倍时,只用先前一半的计算量,效果还更好。
其实,dense 模型,也可以当做混合专家来训练。具体来说,可以把 dense 模型看成仅有一个 FFN 的 MoE 特例,然后拆成好几个小专家,训练时把阈值设置为 1—— 也就是选择所有专家才能满足——从而稠密训练。测试时可以调低阈值,实现稀疏计算。结果发现,又快又好。有趣,建议推广。
拆的越小,relu,甚至 gelu 之后大于 0 的比例越大 —— 参数被更有效的利用了,符合动机。
一味的缩小不可取。这是因为专家数量越多,路由上花的时间显著增加,路由模块的加速或许也必要。
碎碎念:如果专家继续缩小下去,就变成一个专家只有一个向量了,这很像 Large Memory Layers with Product Keys, 19 NIPS,需要特殊方法来加速路由过程。
碎碎念:顺带一提,Adaptive Gating in Mixture-of-Experts based Language Models, 23 EMNLP 也是做动态路由的,但是只支持 top-1 和 top-2 的切换。
04
HyperMoE
论文地址:
https://arxiv.org/abs/2402.12656
代码地址:
https://github.com/Bumble666/Hyper_MoE
4.1 动机
原文的动机是:1)token 选的专家越多越好好,但是为了效率,不能选多 -> 2)那就用没被选的专家,来帮助选了的专家 -> 3)这目的很像 multi-task learning 的 knowledge transfer -> 4)以前工作发现 hypernetworks 可以帮助 multi-task learning 的 knowledge transfer -> 5)所有我们把 moe 和 hypernetworks 结合起来。
碎碎念:咱不了解多任务学习,所以不好评价。就事论事,2)这一点还是挺有吸引力的。
简洁版本的动机是:让专家之间互帮互助,又不增加计算负担,这包括:没被选的专家也能帮助选了的专家,曰 cross-expert information。
4.2 方法
首先介绍下 hypernetwork:它是用来生成神经网络参数——实际上就是矩阵——的神经网络——实际上也是矩阵。
本文在下游任务微调 Switch Transformer-base-8,每层有 8 个专家,top-1 路由。
对于每个输入的 token,除了让它选择的 top-1 的专家老老实实计算外,本文还新增了如下操作,具体如下:
防止在细节中迷失,这里给出一句话摘要:根据没用上的剩下 7 个专家,生成出 2 个矩阵,然后把 token 和这两个矩阵相乘,得到一个输出向量。
每层的每个专家都有一个相对应的 expert embedding,标记为 ,维度是 。因为每层有 8 个专家,所有 8 个 。这个 是随机初始化的。
对于每个 token,它会选择一个专家,这意味着剩下有 7 个专家没用。这 7 个专家的 相加,为了省事,相加得到的向量还是标记为 。
用一个双层 MLP,把 处理一下,变成 ,叫做 selection embedding。
每一层还有一个 layer embedding,标记为 ,维度是 。
把 和 拼在一起,然后,i)和一个大矩阵相乘,得到 W_1,维度是 ,ii)和另一个大矩阵相乘,得到 W_2,维度是 。
好的,终于最后一步了,把输入 token,标记为 ,进行 的操作。
好了,上面一长串得到的输出向量 和 top-1 专家的计算结果相加,结束了。第 5 步用到了两个大矩阵,就是 hypernetwork。
4.3 吐槽
作者为了不增加激活专家的数量,引入了好多多余的计算啊,有这工夫,为什么不之间变成 top-2 呢。论文没提供复杂度的分析,也没提供维度具体怎么设置的,这里也不分析了。
在最后一页的 Table 5,讨论了一下时间上的开销,对比的指标是每秒能推理多少个 sample,对比的只有两个模型,原始 top-1 moe,以及本文提出的 HyperMoE。具体来说,数量下降了 10% -- 15%。强烈建议增加对比 top-2!
05
Expert SparsityPublic
论文地址:
https://arxiv.org/abs/2402.14800
代码地址:
https://github.com/Lucky-Lance/Expert_Sparsity
5.1 动机
MoE 有很多专家,就算不用的话,那还是要占空间的。为了省空间,可以在部署前删掉!
MoE 的专家不是同样重要。不重要的在推理时跳过,这样推理速度更快。
5.2 方法
和动机相对应,由两个方法构成:1)expert pruning,2)dynamic expert skipping。注意,这两个方法都是 post-training,也就是说,拿个训练好的 MoE 模型过来,再使用这些方法来优化。
Expert Pruning:做法其实很简单
0)从 C4 这个预训练数据集挑一些数据,这里挑 128 个 sequence,每个长度 2048,
1)让模型把这个数据集全都前向传播一遍,保存中间每一层的所有 hidden states,
2)假设我们的目标是只保留 k 个专家,那么从第一个 moe 层开始,遍历所有 k 个专家的组合,只用这个 k 个专家进行计算,衡量和保存的 hidden states 的 Frobenius norm 距离。
3)选择距离最小的那 k 个专家,然后继续处理下一层。
Dynamic expert skipping:本文使用的模型是 Mixtral 8x7B,每层有 8 个专家,选择 top-2。skipping 的做法是,如果 第二名的专家分
5.3 效果
肯定是会下降的,看个人接受程度吧,散了散了。
06
MixLoRA
论文地址:
https://arxiv.org/abs/2402.15896
6.1 动机
多模态多任务学习会有任务干扰(task interference),具体表现是梯度冲突 (gradient direction conflicts),即不同任务的 loss 函数对于同一块参数的 梯度优化方向不一致——最糟糕就是完全相反,那就抵消啦。通过多模态数据上的梯度冲突的分析,证明确实这样。
6.2 方法
用 moe 的方法 + lora。简单理解,就是 moe 的专家从 FFN 变成了 lora。下面是细节:
lora 本来是 两个小矩阵 A、B合成 一个大矩阵 W,即 W=BA。
这里变成两个向量,a、b,通过外积合成出一个矩阵 W。
碎碎念:这种 vector 当做 moe 专家的做法,让我联想到了 Pushing Mixture of Experts to the Limit: Extremely Parameter Efficient MoE for Instruction Tuning, iclr 24,虽然记不太清了,隐约感觉挺像的。
07
ESFT
论文地址:
https://arxiv.org/abs/2407.01906
代码地址:
https://github.com/deepseek-ai/ESFT
又是一篇 DeepSeek 的工作。
7.1 动机
参数高效的微调 (PEFT)在 MoE 模型上还没有充分研究。
文章提出一种更适合 MoE 的微调方法。
7.2 方法
方法是基于如下的实验发现:
那些使用了小专家的 MoE 模型(deepseek-moe, XMoE)的专家很分化。
分化,即意味着不同任务使用的专家重叠度很低。
因此不同的任务可以 finetune 不同的专家。
那么给定一个具体的任务,到底微调哪些专家呢?
从这个任务中随机选择若干个 sample,用来拼接出长度 4096 的 32 个新 sample。
把这 32 个 sample 送到 MoE 模型里前向传播,同时记录些信息,用来给每层的每个专家打分。(打分方式有两种,等会讲。)
根据打分,还有一个超参数 threshold,选择分数最高的那些专家,使得这些专家的打分之和大于 threshold。(熟悉的感觉)
只微调这些专家的参数,其他固定不变 —— 个人理解,即便某个专家被激活了,但如果不在微调的专家列表里,就不会被梯度传播。
碎碎念:是不是很直观。有点像上面的剪枝论文。
剩下的细节就是打分的方法了。
1)对于某个专家,token 选择了这个专家的比例,作为分数。举个栗子,有 4096 个 token,每个 token 选 4 个专家,假如有 2048 个 token 选择过专家 1,那么专家 1 的分数就是 2048 /(4096 * 4)。
2)对于某个专家,选择了它的那些 token 给它打的分数的总和,作为分数。举个栗子,有两个 token 选了专家 1,分数分别是 0.1, 0.08,那么这个专家的分数就是 0.1 + 0.08 啦。
总之,每个打分方法,都要保证所有专家的分数总和加起来是 1。(所有方法 2 给的例子不太精确,理解万岁。)
实验结果显示,两种方法在不同数据上各有各的好。
碎碎念:论文给第一种方法设置的阈值是 0.2, 第二种是 0.1。喂,这是不是也太小了啊。但是论文说,“The average number of experts used per task across layers ranges from 2 to 15 out of 66”,所以说,即便阈值只有 0.1,也需要至少 2 个专家才能达到?路由模块的置信度这么低?
7.3 实验
比较对象是 全参数微调 FFT 和 LoRA。本文的方法标记为 ESFT。
训练效率上:LoRA (16.5分钟)> ESFT (19.8分钟)> FFT (28.5 分钟)
性能效率上:FFT > ESFT > LoRA 。(有的场景下 ESFT 还能更好,咱倒也不是不能理解。)
总的来说,如果代码好实现的话,也不是不能用啦。
碎碎念:有一说一,如果用上 论文 2,3 的基于阈值的路由的话,本身路由模块已经进行了专家的相关度的筛选。是不是可以考虑结合一下呢?
文章来源于“大模型智能”,作者“杨远航@哈尔滨工业大学(深圳)”
【开源免费】graphrag是微软推出的RAG项目,与传统的通过 RAG 方法使用向量相似性作为搜索技术不同,GraphRAG是使用知识图谱在推理复杂信息时大幅提高问答性能。
项目地址:https://github.com/microsoft/graphrag
【开源免费】Dify是最早一批实现RAG,Agent,模型管理等一站式AI开发的工具平台,并且项目方一直持续维护。其中在任务编排方面相对领先对手,可以帮助研发实现像字节扣子那样的功能。
项目地址:https://github.com/langgenius/dify
【开源免费】RAGFlow是和Dify类似的开源项目,该项目在大文件解析方面做的更出色,拓展编排方面相对弱一些。
项目地址:https://github.com/infiniflow/ragflow/tree/main
【开源免费】phidata是一个可以实现将数据转化成向量存储,并通过AI实现RAG功能的项目
项目地址:https://github.com/phidatahq/phidata
【开源免费】TaskingAI 是一个提供RAG,Agent,大模型管理等AI项目开发的工具平台,比LangChain更强大的中间件AI平台工具。
项目地址:https://github.com/TaskingAI/TaskingAI
【开源免费】XTuner 是一个高效、灵活、全能的轻量化大模型微调工具库。它帮助开发者提供一个简单易用的平台,可以对大语言模型(LLM)和多模态图文模型(VLM)进行预训练和轻量级微调。XTuner 支持多种微调算法,如 QLoRA、LoRA 和全量参数微调。
项目地址:https://github.com/InternLM/xtuner