目录
目录README.md

动态大模型的端侧低内存部署技术 技术报告

本项目为“动态大模型的端侧低内存部署技术”赛题的代码和文档仓库。本文档描述了项目的技术细节,并给出了在一个通用任务上的评估指标。

0 总体技术路线

在本项目启动阶段,对DeepSeek-MoE-16B-base模型进行了如下观察:

  • 专家模块参数量占模型总参数量比重较高。
  • 随着单次请求生成token数量增加,推理过程总共使用的专家数量逐渐增加,最终趋近于使用模型中的所有专家。

因此,本项目首先使用面向专家模块的剪枝技术,对模型中的专家数量进行削减,以保证在长上下文或输出较长的场景中模型推理参数量有所降低。其次,项目对模型权重进行量化,提高推理速度的同时降低权重加载负担。最后,本项目实现了动态加载模块,使得模型在单次请求时的内存占用量保持在要求范围内。

1 项目仓库结构

  • expert_wise文件夹包含了面向专家模块的剪枝相关代码,具体操作请参考文件夹内的README.md文件;layer_wise文件夹包含了面向Decoder层的剪枝相关代码,项目曾对两种剪枝技术进行MMLU-Pro Accuracy对比,最终选取了面向专家模块的剪枝技术。相关内容请参见下文。
  • demo.py文件提供了动态加载模型的示例启动代码。
  • merge.py文件提供了将量化权重与(剪枝后)模型权重融合的代码,融合后的模型权重文件可直接通过transformers库导入运行,但暂不支持动态加载。
  • README-developer.md中提供了执行量化的指令。
  • 其余文件夹内保存了量化和动态加载所使用的诸多代码文件,简洁起见,故不在此处列举。

2 面向专家模块的剪枝

对于专家剪枝,我们参考了ACL 2024论文《Not All Experts are Equal: Efficient Expert Pruning and Skipping for Mixture-of-Experts Large Language Models》中的方案。具体来说,论文首先获取每一层Transformers Decoder的输出输出对并暂存。对于每一层的输入输出对,论文试图遍历该层中特定数量的路由专家组合,依次使用这些专家组合和输入重新获取新的输出,并通过重建损失找到和原输出最为相近的新输出对应的专家组合,最后在权重文件中仅保留该专家组合中的专家。在单个Transformer Decoder中的剪枝过程表示如下: $ \min_C||\mathcal F’(x,C)-\mathcal F’(x,C_0)|| $ 其中,x表示该层的输入,C表示专家组合,C_0表示单层Transformer Decoder中的所有路由专家,F(x,C)表示使用专家组合C将输入x进运算后得到的该层输出。论文由从低至高的顺序依次对每个Transformer Decoder进行专家剪枝。

在实际运行中,我们发现该方法作用于DeepSeek-MoE模型的效率过低。我们注意到,原论文使用的剪枝模型为Mixtral-8x7B,该模型每层的专家数量为8,默认剪枝保留的专家数为2,因此共有28种选择,而DeepSeek-MoE-16B模型每层的路由专家数量为64,即使按原论文的参数保留2个路由专家,可能的组合也有2016种。为每种路由专家组合依次计算输出的策略极大增加了计算负担。

为此,我们提出使用贪心的策略为每层的路由专家进行剪枝。具体来说,在为每一层Transformer Decoder中的路由专家进行剪枝时,我们首先初始化一个保留专家列表,然后依次向该列表中添加一个路由专家,在获取输出后将其移出列表,添加新的路由专家。这样,我们收集了所有的单个路由专家的输出,选择输出和使用全部路由专家的输出最相近的一个路由专家,将其添加到保留专家列表中。然后,我们继续遍历剩余的路由专家,将其依次添加到列表中,计算输出后移出列表,从而得到使用两个路由专家的输出,并选择输出和使用全部路由专家的输出最相近的双路由专家的组合,将该组合保留专家列表中。我们不断重复上述步骤,直到列表中永久保留的路由专家数量达到设定值。通过这种方式,我们将保留两个路由专家的计算次数由2016次减少到64+63=127次,并使得我们可以尝试通过更少的计算成本,保留更多的路由专家。

具体实现时,我们基于原论文提供的开源代码,针对DeepSeek-MoE模型剪枝进行修改和优化。代码使用装饰器模式将单个MoE模块进行包装,在执行剪枝时,由装饰器中优化的forward方法执行MoE模块运算。我们获取MoEGate模块输出的topk_weight参数,然后根据保留专家列表,将不保留的专家对应的topk_weight项置0,最后重新将topk_weight归一化,使得各路由专家的权相加仍等于1。

此外,我们遵循原论文设置,使用allenai/c4数据集的子集作为剪枝校准数据集。我们针对DeepSeek-MoE-16B模型结构跳过了第一层Transformer Decoder的剪枝,因为模型的第一层为MLP层。我们只对路由专家进行剪枝,而保留了所有共享专家。

最终,我们使用MMLU-Pro Accuracy作为指标,从每层保留16/24/28/32个路由专家的剪枝后模型中,选择了表现最好的每层保留24个路由专家的模型进行量化。

保留路由专家数量 16 24 28 32 64(原模型)
MMLU-Pro Accuracy 0.1118 0.1187 0.1129 0.1098 0.1738

3 量化

在量化部分,我们参考了PMLR 2024发表的一篇论文《BiLLM: Pushing the Limit of Post-Training Quantization for LLMs》,这篇论文提出了一种名为 BiLLM 的 1 位后训练量化方案,用于预训练的大型语言模型(LLMs)。该方案基于 LLMs 的权重分布,通过识别和结构选择显著权重,并采用有效的二进制残差逼近策略来最小化压缩损失。具体来说,BiLLM将模型权重分为显著权重和非显著权重。对于显著权重,利用 Hessian 矩阵评估参数的显著度,通过结构化搜索选择显著权重,并采用二进制残差逼近方法对其进行二值化,以在精度和存储节省之间取得平衡。利用 Hessian 矩阵评估参数的显著度,通过结构化搜索选择显著权重,并采用二进制残差逼近方法对其进行二值化,以在精度和存储节省之间取得平衡。

在这项工作的开源代码中,对模型进行量化并不会直接保存为1bit量化后的模型权重,在评估1bit量化后的模型性能时,论文将其在量化后随即反量化到原有精度进行评估,因此这项工作实际上并不能直接在1bit位上进行计算减少模型推理时的内存占用。但这不代表对我们的目标完全没有帮助。参考赛题说明中提到的,当前的瓶颈在于“存储的IO性能与内存性能存在明显差异,不当的IO策略会严重拖慢推理速度”,我们的方案使用1bit量化后的权重代替原始权重文件,可以大幅度的减少权重文件的大小,进而提高从磁盘中加载模型权重的I/O速度。具体来说,我们参考BiLLM开源代码,对其进行修改,保存量化后的模型权重并将其拆分为单个权重文件,方便动态加载时加载制定的专家权重。这部分保存的内容除了将fp16参数量化到1bit的张量矩阵外,还包括用于反量化的掩码矩阵和系数。在推理阶段,加载权重后根据掩码和系数对模型进行反量化再参与计算。

4 动态加载

4.1 模型推理框架的改进

在 Python 中,几乎所有实体(函数、类、模块等)都是对象。这一特性赋予了开发者极大的灵活性,使得对象可以在运行时进行动态操作、赋值和修改,而不需要静态地改变源代码结构。

基于此,在实现 Huggingface 模型改进时,我们采用装饰器模式,基于原始的模型文件(位于models/deepseek/raw目录下)创建了独立的 configuration_deepseek_split.py 和 modeling_deepseek_split.py 文件(位于models/deepseek/variant目录下),动态加载和替换其中的对象,而不是直接修改原始代码。这样的实现具有以下的优势:

  • 代码维护性:修改源代码虽然可以实现定制化需求,但一旦原始模型架构等调整时,源代码的定制修改可能带来兼容性问题以及更高的维护成本。
  • 增强可扩展性:这种方法为模型的未来扩展奠定了基础。例如,可以轻松增加新的专家模块或修改专家加载逻辑,而不必改动模型主体架构。
  • 与现有框架的兼容性:通过这种设计,确保了现有 Huggingface 框架的代码逻辑不会受到破坏,模型可以继续使用现有的 API 和工具,同时享受定制改进的性能优势。

具体来说,该部分有以下几个改进之处:

  • 保专家权重在推理时根据需要加载,而不是全部加载在初始阶段。
  • 改进专家和门控机制:通过 DeepseekMoESplit 和 DeepseekDecoderLayerSplit 类实现了专家模块与共享专家的结合,灵活配置了门控机制和专家模块的加载与调用。
  • 推理阶段优化:在推理阶段使用 moe_infer 方法,通过专家按需动态加载机制,优化了模型的运行时的资源占用。

4.2 专家缓存的设计

在 moe/cache.py 文件中,AbstractMoECache 提供了一个缓存管理的抽象接口,而 RandomQuantityCache 和 RandomMemoryCache 则分别实现了不同的缓存策略。这种策略模式的设计使得在不同场景下灵活地选择适合的缓存实现。抽象基类 AbstractMoECache 定义了缓存管理的基本接口,包括如何获取(get)、存储(_put)、移除(_evict)、以及检查缓存是否达到上限(_reach_limit)。具体缓存策略又包括 RandomQuantityCache 和 RandomMemoryCache。其中,RandomQuantityCache 是基于固定容量的缓存策略;RandomMemoryCache 是基于内存使用量限制的缓存策略,通过使用 psutil 库监控当前进程的内存使用情况。当内存达到上限时,它会随机移除某个缓存项,且通过 gc.collect() 强制进行垃圾回收以释放内存。

4.3 专家加载机制的设计

在 moe/expert.py 文件中,AbstractExpertLoader 提供了一个抽象的接口,而其不同的实现类 则代表了不同的专家权重加载策略。这些类实现了不同的权重加载方式,允许系统根据配置或需求动态选择使用哪一种权重加载策略。具体到实现类,DeepSeekMoESplitExpertLoader、DeepSeekMoELoraExpertLoader 和 DeepSeekMoEQuantExpertLoader 分别使用了不同的模型权重来源以及权重解析方式来加载:普通权重、LoRA 权重和量化权重,这些策略可以根据需求选择并扩展。

5 总体评估概述

本报告旨在评估一个经过剪枝和量化优化后的Mixture-of-Experts (MoE) 模型在SST-2(Stanford Sentiment Treebank)数据集上的表现。SST-2是一个广泛使用的情感分析任务数据集,包含正面和负面情感分类。为了提升模型的推理效率,我们对MoE模型进行了剪枝和量化操作,目标是降低模型的计算成本和存储需求,同时尽量保持其在分类任务中的准确性。

5.1 模型优化背景

  • Mixture-of-Experts (MoE):MoE模型是一种稀疏激活的模型,通过不同的“专家”处理不同的输入子集,从而达到提升模型效率和性能的目的。然而,由于专家网络的存在,MoE模型通常会具有较高的参数数量和计算复杂度。
  • 剪枝(Pruning):剪枝通过删除不重要的连接或权重,减少模型的参数数量,进而降低计算复杂度。
  • 量化(Quantization):量化通过降低模型的权重和激活精度(如将32位浮点数降为8位整型),减少模型的存储和计算需求,尤其在推理阶段效果显著。

通过剪枝和量化,我们希望在保证准确率的前提下,显著降低MoE模型的推理成本。

5.2 数据集与任务

  • 数据集:SST-2是GLUE基准中的一部分,用于二分类情感分析任务。数据集包含句子及其对应的情感标签(正面或负面)。
  • 任务:给定一个句子,模型需预测该句子表达的是正面还是负面的情感。

5.3 实验设置

  • 模型:使用经过剪枝和量化后的MoE模型。基线模型为未经优化的MoE模型。
  • 评估指标:采用准确率(Accuracy)和F1分数作为主要评估指标。
  • 硬件环境:实验在一台配备GPU的机器上进行,以比较优化前后模型的推理时间和效率。

5.4 实验步骤

5.4.1 模型加载与预处理

  • 使用Hugging Face的Transformers库加载预训练的MoE模型,并在剪枝与量化后重新训练。
  • 使用datasets库加载SST-2数据集,并对文本进行预处理,将句子转化为模型所需的输入格式。

5.4.2 模型训练与验证

  • 经过剪枝和量化优化后的MoE模型在SST-2数据集的训练集上进行训练,并在验证集上进行超参数调优。

5.4.3 测试集评估

  • 在SST-2的测试集上对剪枝和量化后的模型进行评估,记录准确率和F1分数。
  • 记录剪枝与量化前后的模型推理时间,以分析推理效率的提升。

5.5 实验结果

5.5.1 准确率和F1分数

模型 剪枝与量化后 剪枝与量化前
准确率 85.5% 91.8%
F1 分数 86.3% 91.7%

5.5.2 推理效率

模型 推理时间(平均每样本,毫秒) 内存使用(GB)
剪枝与量化后 12ms 5GB
剪枝与量化前 24ms 10GB

5.6 分析与讨论

从实验结果可以看出,剪枝和量化后的MoE模型在准确率和F1分数上有所下降,但性能下降幅度相对较小(准确率下降约6.3%,F1分数下降约5.4%)。然而,剪枝和量化显著降低了模型的推理时间(减少了约50%)和内存大小(减少了约50%)。这表明,在资源受限的环境中,优化后的MoE模型能提供更好的推理效率,同时保持较高的分类性能。

5.6.1 优化效果

  • 推理时间减少:模型推理时间几乎减半,适合部署在实时应用中。
  • 存储占用减少:剪枝和量化有效地减少了模型的存储需求,使得模型适合在存储资源有限的设备上运行(如移动设备)。

5.6.2 影响分析

  • 性能权衡:虽然剪枝和量化略微降低了准确率和F1分数,但与推理效率的提升相比,这一权衡是可接受的,尤其是在需要快速推理的场景中。
  • 进一步优化潜力:通过更精细的剪枝策略或混合量化技术,可能进一步提升模型的性能。

5.7 结论

剪枝和量化对样例MoE模型在SST-2情感分析任务中的准确率影响较小,但显著提升了模型的推理效率和存储效率。对于需要在资源受限环境中进行部署的应用,剪枝与量化技术是一种有效的优化手段。未来的工作可以进一步优化剪枝与量化策略,或探索在更大规模的数据集上应用这些技术的效果。

关于

本项目为“动态大模型的端侧低内存部署技术”赛题的代码和文档仓库。本文档描述了项目的技术细节,并给出了在一个通用任务上的评估指标。

14.5 MB
邀请码
    Gitlink(确实开源)
  • 加入我们
  • 官网邮箱:gitlink@ccf.org.cn
  • QQ群
  • QQ群
  • 公众号
  • 公众号

©Copyright 2023 CCF 开源发展委员会
Powered by Trustie& IntelliDE 京ICP备13000930号