2023-11-21论文笔记
写在前面
最近面试的时候被问到了大模型压缩技术的相关问题,本人对此并无什么了解,因此阅读几篇相关论文进行初步了解。
常用的大模型压缩技术
常用的大模型压缩技术可以被整理为下图:
剪枝(Pruning)
剪枝是一种强大的技术,类似于给模型“减肥”,通过去掉一些不必要或多余的部分,以降低模型的大小和复杂性。我们可以把这些多余的东西想象成模型的“赘肉”,它们对模型性能几乎没有影响,反而占用了很大的内存和计算量。因此,我们可以直接去掉这些赘肉,在模型的性能几乎不受影响的同时提高模型的存储效率、内存利用率和计算效率。
剪枝有两种主要类型:结构化剪枝和非结构化剪枝。前者以一整组的形式去剪枝,比如说直接剪去整个神经元、通道或层。这种方式的好处在于能够降低模型的复杂性和内存占用,但同时整体的模型结构仍然得以保持。这就好比在修剪花园中的某一排树木之后,花园整体轮廓和结构依然清晰、整齐;后者则是以更细粒度的方式进行,它直接瞄准个别权重或神经元,就像单独修剪花园中的某几棵树木,虽然也减少了冗余,但是花园整体会有些凌乱,这样的方法可能导致模型变得稀疏却不规则,需要特殊的压缩技术来高效存储和计算,并且通常需要对LLM进行大量的重新训练以恢复其准确性。
知识蒸馏(Knowledge Distillation)
知识蒸馏是一项很棒的技术,旨在提升模型性能和泛化能力。其核心思想是将来自一个复杂模型(称为“教师模型”)的知识传递给一个更简单的模型(称为“学生模型”)。
知识蒸馏方法可以被分为两个类别:黑盒知识蒸馏和白盒知识蒸馏。在黑盒知识蒸馏中,学生 LLM 只能获取到教师模型的预测结果,却无法了解教师模型的具体参数和内部结构,这就好比我们只知道某人的答案,但对于他是如何得出这个答案的一无所知,黑盒知识蒸馏注重于结果的传递,尽管无法提供深入的内在机制,但它在许多实际场景中仍然是一种有效的知识传递方式;而在白盒知识蒸馏中,学生 LLM 不仅可以获取到教师模型的预测结果,还可以访问和利用教师模型的参数信息,这就像是我们对教师的了解不仅限于他的答案,还包括他是如何思考的,为什么会给出这样的答案,这种方法允许学生模型更深入地理解教师模型的内在结构和决策过程,通常会带来更大的性能提升。
量化(Quantization)
在模型压缩领域,量化技术被用于减少深度学习模型的存储和计算开销。传统的表示方法采用浮点数,而量化将其转换为整数或其他离散形式,这一转变显著降低了存储需求和计算复杂性。尽管存在一定的精度损失,但通过谨慎地选择量化技术,可以在只有最小精度下降的情况下实现最大幅度的模型压缩。
量化主要分为三种方法:量化感知训练(Quantization-Aware Training,QAT)、量化感知微调(Quantization-Aware Fine-tuning,QAF)和训练后量化(Post-Training Quantization,PTQ)。这些方法的主要区别在于何时应用量化来压缩模型。在量化感知训练中,量化的目标被无缝地整合到模型的训练过程中,这就像是模型在学习的同时就已经“知道”了后续会面对的量化挑战,通过在训练期间考虑量化,模型能够适应低精度表示,从而在后续的量化过程中更好地保持性能。量化感知微调是在模型已经完成训练后,专门为量化而进行的微调过程,这就是在模型已经具备一定知识的情况下,再对其进行细致的调整,以适应量化所带来的变化,这种方法更灵活,可以在模型训练完成后根据具体需求进行精细调整。相比之下,训练后量化是一种更为简单而高效的压缩方法,在训练完成后,模型的参数被量化,无需对模型进行进一步的训练或微调,尽管这种方法简单,但由于量化过程可能引入一定的精度损失,需要权衡压缩效果和性能损失。
低秩分解(Low-Rank Factorization)
低秩分解旨在通过将给定的权重矩阵分解成两个或多个较小维度的矩阵,从而对其进行近似。低秩分解背后的核心思想是找到一个大的权重矩阵W的分解,得到两个矩阵U和V,使得W≈U V,其中U是一个m×k矩阵,V是一个k×n矩阵,其中k远小于m和n,U和V的乘积近似于原始的权重矩阵,这样便大幅减少了参数数量和计算开销。在 LLM 研究的模型压缩领域,研究人员通常将多种技术与低秩分解相结合,包括剪枝、量化等在实现更有效的压缩同时保持模型的性能尽量不降低。
相关论文
SHEARED LLAMA: ACCELERATING LANGUAGE MODEL PRE-TRAINING VIA STRUCTURED PRUNING
背景
虽然已经有了很多降低大模型训练成本的技术,但是训练大模型的代价仍然十分高昂,普通人难以承受。因此,作者希望使用剪枝技术来从已有的预训练大模型中生成一个小一些的 LLM,但是这面临着两个挑战:如何确定最终的性能强大、推理高效的剪枝结构——LLM 目前的结构化剪枝技术没有指定的目标结构,导致剪枝后模型在性能和推理速度方面不理想;以及如何继续预训练剪枝后的模型以达到预期性能——与从头开始训练模型相比,使用原始预训练数据来训练会导致不同域出现不同的损失减少率。
工作
首先需要说明的是,给定一个现有的大模型,希望通过剪枝技术生成一个更小但是性能更强的模型,作者设计了一个两阶段的范式:第一阶段将原模型剪枝为一个小模型,成功地减少了参数数量,但不可避免地导致性能下降;因此第二阶段持续预训练小模型,使其性能更强。
整体来说,作者使用了两个关键技术:定向结构化剪枝以及动态批加载。前者将剪枝看成一种约束优化问题,通过端到端的方式移除特定的层,头以及隐藏维度等等来将模型压缩到目标结构,后者根据模型在不同域数据上的损失下降速率动态调整每个域的数据所占比例,提高数据使用效率。
定向结构化剪枝
作者利用现有预训练模型的配置作为目标架构,例如当生成一个2.7B模型时,作者使用INCITE-Base-3B架构作为目标架构。具体来说,该方法将剪枝问题建模为一个约束优化问题,通过学习剪枝掩码来搜索一个与预先指定的目标架构匹配的子网络,同时最大化性能——在不同粒度的模型参数上学习一组剪枝掩码(例如粗粒度上的层、隐藏维度以及细粒度上的注意力头的数目、中间维度),每个掩码变量控制是否剪枝或保留相关的子结构,然后将剪枝掩码和模型权重一起进行优化。例如,如果某层对应的层掩码为0,则需要删除这个层。剪枝之后,再通过保留与每个子结构中的掩码变量相关的最高得分组件来最终确定剪枝后的架构,并继续使用语言建模目标对剪枝后的模型进行预训练。下图说明了剪枝掩码如何控制被剪枝的结构。
动态批加载
作者认为对剪枝后的模型进行大量预训练是很有必要的,这样才能恢复模型性能,但是作者发现在原有的预训练数据集上继续进行预训练相比原版的 llama 模型在不同的域数据上损失的降低速度不同,这说明对数据的利用效率较低。因此作者提出了动态批加载方法来根据真实loss和参考loss之间的差值调整各域数据在一次采样中所占的比例来解决这个问题,算法如下图所示:
效果
Distilling Step-by-Step! Outperforming Larger Language Models with Less Training Data and Smaller Model Sizes
背景
大语言模型不易于部署,因为它们需要很大的显存以及大量的计算,因此在现实应用中,人们往往通过使用人工标签微调或者使用LLM生成的标签进行蒸馏来得到更小的任务特定的语言模型。但是一个现实的问题是无论是微调还是蒸馏都需要大量数据才能尽量保证小模型的性能不会骤降。
工作
作者提出了 Distilling step-by-step 方法,使得小模型的性能超过了原本的 LLM,并且只需要比微调或者蒸馏更少的训练数据。这个机制的核心观点是:不再将 LLMs 是做带有噪声的标签的来源,而是将其视为可以进行推理的 agent:LLMs 可以生成自然语言解释,用于证明它们产生的预测结果。实现的核心是:利用教师 LLMs 生成的解释作为额外信息,通过多任务训练机制,同时进行标签预测和解释预测,以此训练学生 LLMs。该方法分为两个阶段——使用 CoT 从 LLMs 中提取解释以及使用多任务学习方法训练学生模型,其整体示意图如下图所示:
从 LLMs 中提取解释
在这一阶段中,作者使用了基于 few-shot CoT 的 prompt 来获得大模型对于预测的推理解释,如下图所示:
多任务学习训练学生模型
作者使用多任务学习方法,让模型根据输入分别输出预测和解释,并设计了总体损失函数:$\mathbb{L}=\mathbb{L}_{label}+\lambda\mathbb{L}_{rationale}$,在测试时可以只让模型输入预测结果,不输出解释,以加快推理。
在训练过程中,为了让模型知道什么时候输出预测标签,什么时候输出具体解释,作者会将 [label] 和 [rationale] 分别插入到输入的前面来加以区分。
效果
微调的 770M 的 T5 模型比使用 few-shot 的 540B 的PaLM模型效果更好,而且只使用了其 80% 的微调数据。更多实验结果如下图所示: