近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,从而导致模型变得越来越大,因此,需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。 模型压缩主要分为如下几类:
- 模型稀疏化/剪枝
- 知识蒸馏
- 模型量化
本系列将针对一些常见大模型稀疏化方案(LLM-Pruner、SliceGPT、SparseGPT、Wanda)进行讲述。
- 大模型稀疏化技术原理:概述
- 大模型稀疏化技术原理:Double Sparsity
- 大模型稀疏化技术原理:SparseGPT、Wanda
- 大模型稀疏化技术原理:LLM-Pruner、SliceGPT、LoSparse
- 大模型稀疏化技术原理:总结
另外,我撰写的大模型相关的博客及配套代码均整理放置在Github:llm-action,有需要的朋友自取。
本文将针对当前大模型剪枝相关的一些工作进行讲述。
剪枝简介
模型稀疏化/模型剪枝是一种用于减少神经网络模型参数数量和计算量的技术。它通过识别和去除在训练过程中对模型性能影响较小的参数或连接,从而实现模型的精简和加速。在LLM中,稀疏化通常应用于权重参数和注意力激活。这促进了权重剪枝策略和稀疏注意力机制的发展。
剪枝类型
通常,模型剪枝可以分为两种类型:结构化剪枝、非结构化剪枝、半结构化剪枝。
非结构化剪枝
非结构化剪枝,也称为权重剪枝,是最细粒度的剪枝。非结构化剪枝指直接去除神经网络中的单个权重参数,这可能会导致模型连接中断或者参数数量不均匀情况。非结构化剪枝方法通常根据参数的重要性进行剪枝,例如:通过计算参数的绝对值大小或者梯度大小来确定哪些参数应该被保留。
在实践中,非结构化剪枝通常不会直接将权重设置为0,而是将其相应的掩码设置为0。在这种情况下,非结构化剪枝被视为对每个权重应用二进制掩码。通常,网络使用固定掩码 m 进行重新训练(即微调或从头开始训练),同时,掩码权重不参与重新训练。
由于非结构化剪枝可以去除任何地方的权重,非零权重的不规则替换导致实际加速需要特殊软件或硬件的支持。因此,将非结构化剪枝视为一种专用的加速技术。
结构化剪枝
结构化剪枝是指在神经网络中去除整个参数或层,而不是单个参数。常见的结构化剪枝方法包括对整个滤波器、通道或者层进行剪枝。通过保留最重要的滤波器或者通道,然后去除不重要的部分;同时,重建具有规则结构的窄模型。它不需要特殊硬件和软件(例如:稀疏卷积库)的支持,可以直接加速网络并减小神经网络的大小。因此,将结构化剪枝视为一种通用的加速技术。
半结构化剪枝
为了提高结构化剪枝的灵活性并在剪枝率较高时实现较低的精度下降,引入了半结构化剪枝,以同时实现高精度和具有结构规律性。半结构化剪枝也被称为基于模式的剪枝,可设计各种模式的剪枝。
剪枝步骤
模型剪枝的一般步骤包括:
- 训练初始模型:首先,需要训练一个初始的大模型,通常是为了达到足够的性能水平。
- 评估参数重要性:使用某种评估方法(如:权重的绝对值、梯度信息等)来确定模型中各个参数的重要性。
- 剪枝:根据评估结果,剪枝掉不重要的参数或连接,可以是结构化的或非结构化的。
- 修正和微调:进行剪枝后,需要进行一定的修正和微调,以确保模型的性能不会显著下降。
模型剪枝可以带来多方面的好处,包括减少模型的存储需求、加速推理速度、减少模型在边缘设备上的资源消耗等。然而,剪枝可能会带来一定的性能损失,因此需要在剪枝前后进行适当的评估和调整。
剪枝标准
当进行模型剪枝时,如何确定要保留哪些网络结构以及要剪枝哪些网络结构呢?为了回答这个问题,需要一个适当的剪枝标准,它将对权重、滤波器或神经元进行重要性排名。常用的剪枝标准包括幅度、范数,显著性或敏感性,损失变化等。这些标准之间没有严格的界限,但侧重点不同。
- 基于幅度进行剪枝
基于幅度进行剪枝是剪枝较小幅值的权重,它基于这样的假设:绝对值较小的权重往往对神经网络模型输出的影响最小。该公式定义为:
其中, 是阈值,表示向量的范数,计算方法是将该向量中所有元素的绝对值相加。 基于幅度进行剪枝可以应用于非结构化或结构化剪枝。例如:通过计算权重绝对值的总和来对滤波器进行评分。此外,基于幅度的剪枝标准可以与全局/局部、一次性/迭代剪枝相结合。尽管它很简单,但仍然广泛应用,使其成为该领域的主要剪枝标准。
- 基于范数进行剪枝
使用范数来评估权重、滤波器、通道的重要性。例如:利用范数来评估滤波器的重要性。具有较小范数的滤波器比具有较大范数的滤波器更有可能被剪枝。一些基于范数的剪枝方法使用范数作为重要性指标。在这种情况下,这些方法也属于基于幅度的剪枝方法。此外,重要性值通常通过基于范数的稀疏正则化进行优化。
- 基于敏感性或显著性进行剪枝
利用敏感性或显著性来评估权重、通道、滤波器的重要性。敏感性或显著性的定义在不同的工作中可能有所不同。例如:将权重显著性定义为通过剪枝该权重引起的损失变化。
- 基于损失变化进行剪枝
通过评估有没有权重、滤波器或通道对神经网络模型的损失变化来衡量权重的重要性是也一种流行的标准。以滤波器重要性评估为例,由于在逐个删除滤波器后重新评估整个神经网络的性能并非易事;因此,一些研究人员以基于泰勒展开的方式近似滤波器的重要性。一阶泰勒展开式是最常见的用于测量损失变化的方法。损失函数的二阶泰勒展开式也早已得到了应用,用于去除不重要的权重,并逐渐在许多后续方法中得到利用。
静态剪枝与动态剪枝
根据剪枝时机和模型运行时结构是否可变可分为静态剪枝与动态剪枝。
静态剪枝是在推理之前执行所有剪枝步骤,在推理过程中,不需要对神经网络进行额外的剪枝。 而动态剪枝是在推理运行时执行剪枝。
静态剪枝
静态剪枝通常包括三个部分:预训练、剪枝参数的选择、选择性微调或再训练;再训练可以提高剪枝后的神经网络的性能,以达到与未剪枝时的神经网络相当的精度,但可能需要大量的计算时间和能耗。静态剪枝可应用于训练前、中、后任一阶段,但结构一旦确定即固定。静态剪枝后的模型存储成本低,适用于资源有限的边缘设备,但是也存在三个主要问题:
1)通道的剪枝是永久性的,对于一些较为复杂的输入数据,可能无法达到很好的精度。
2)需要精心设计要剪枝的部分,不然容易造成计算资源的浪费。
3)神经元的重要性并不是静态的,而且神经元的重要性很大程度上依赖于输入数据,静态的剪枝很容易降低模型的推理性能。
动态剪枝
神经网络模型中的一些权重在某些迭代中作用不大,但在其他的迭代中却很重要。动态剪枝就是通过动态的恢复权重来得到更好的网络性能。动态剪枝在运行时才决定哪些层、通道或滤波器不会参与进一步的活动。动态剪枝可以通过改变输入数据来克服静态剪枝的限制,从而潜在地减少计算量、带宽和功耗,动态剪枝通常属于训练后应用,支持模型运行时调整,无需微调或重新训练。
与静态剪枝相比,动态剪枝能够显著提高神经网络的表征能力,从而在预测精度方面取得更好的性能;但动态剪枝也存在一些问题:
1)许多动态剪枝方法依赖强化学习实现,但由于权重掩码的二进制特性导致其不可导,无法直接使用梯度下降法进行优化。这限制了动态剪枝在端到端训练中的应用。
2)动态剪枝需要实时存储和更新掩码或状态信息,这显著增加了内存占用。因此,这种方法在资源受限的边缘设备上难以实现,限制了其在实际场景中的应用范围。
剪枝案例
下面来探讨一些将LLMs与剪枝技术相结合的方法,旨在解决LLMs巨大尺寸和计算成本的问题。
非结构化剪枝方法
非结构化剪枝通过删除特定参数而不考虑其内部结构来简化 LLM。这种方法针对 LLM 中的单个权重或神经元进行,通常通过将阈值以下的参数归零。但是此方法忽略了 LLM 整体结构,导致不规则的稀疏模型,这种不规则性需要专门的压缩技术来有效存储和计算剪枝后的模型。
非结构化修剪通常涉及对 LLM 进行大量重新训练以重新获得准确性,这对于LLMs来说尤其昂贵。该领域的一种创新方法是 SparseGPT(论文:SparseGPT: Massive Language Models Can be Accurately Pruned in One-Shot)。它引入了一种不需要重新训练的一次性剪枝策略。该方法将剪枝视为广泛的稀疏回归问题,并使用近似稀疏回归求解器对其进行求解。 SparseGPT 实现了显著的非结构化稀疏性,在 OPT-175B 和 BLOOM-176B 等大模型上甚至高达 60%,而困惑度的增加很小。
与此相反,Syed 等人[Syed et al., 2023]提出一种迭代剪枝技术,在剪枝过程中以最少的训练步骤微调模型。
另一个优化是 LoRAPrune(论文:LoRAPrune: Pruning Meets Low-Rank Parameter-Efficient Fine-Tuning),它将参数高效调整 (PEFT) 方法与剪枝相结合,以增强下游任务的性能。它引入了一种独特的参数重要性标准 [Hu et al., 2022] 使用低秩自适应 (LoRA) 的值和梯度。
为了解决 SparseGPT 仍然需要的资源密集型权重更新过程,Wanda(论文:Simple and Effective Pruning Approach for Large Language Models)提出了一种新的剪枝指标。 Wanda 根据每个权重的大小和相应输入激活的范数的乘积来评估每个权重,并使用小型校准数据集进行近似。该指标用于线性层输出内的局部比较,从而能够从 LLMs 中删除较低优先级的权重。
通过观察到 LLM 推理性能和内存使用量很大程度上受到下图四种类型的 Skinny MatMul 的限制。 因此,Flash-LLM 旨在基于称为“稀疏加载和密集计算”(LSCD) 的关键方法来优化四个 MatMul。Flash-LLM 作为另一个用于非结构化模型剪枝的大语言模型推理加速方法。主要包含基于Tensor-Core加速的非结构化稀疏矩阵乘法计算的高效GPU代码,可以有效加速LLM中常见矩阵计算的性能。使用Flash-LLM,修剪后的LLM模型可以以更少的内存消耗部署到GPU上,并且可以更高效地执行。
结构化剪枝方法
结构化剪枝通过删除整个结构组件(例如:神经元、通道或层)来简化 LLM。这种方法同时针对整组权重,具有降低模型复杂性和内存使用量的优点,同时保持整体 LLM 结构完整。
这个领域的一个例子是 LLM-Pruner(论文:LLM-Pruner: On the Structural Pruning of Large Language Models),它采用通用方法来压缩 LLMs,同时保护其多任务解决能力和语言生成能力。此外,LLM-Pruner 还解决了 LLMs 使用大量训练数据带来的挑战,这可能导致大量的数据传输。为了克服这些挑战,LLM-Pruner 结合了依赖性检测算法来查明模型中相互依赖的结构。它还实现了一种有效的重要性估计方法,该方法考虑一阶信息和近似的 Hessian 信息。该策略有助于选择最佳的组用于剪枝,从而改进压缩过程。
通过研究能否利用现有的预训练 LLMs 来生成更小、通用且具有竞争力的 LLM,同时使用比从头开始训练要少得多的计算量?LLM-Shearing 提出了另外一种结构化剪枝方法。该方法提出了两种技术:
- 有针对性的结构化剪枝:将源模型剪枝为预先指定的目标架构,同时最大化剪枝模型的性能。
- 动态批量加载:修剪会导致跨域的信息保留发生变化。本方法为恢复缓慢的域加载更多数据,并且加载比例是动态决定的。
通过评估一系列广泛的下游任务,包括推理、阅读理解、语言建模和知识密集型任务,我们的 Sheared-LLaMA 模型优于现有的大语言模型。
结语
本文简单讲述了目前大模型剪枝的一些工作,在大模型参数量越来越大的今天,该方向的研究对于减少模型的大小以及复杂性非常有用。
码字不易,如果觉得有帮助,欢迎点赞收藏加关注。
参考文档: