剪枝方法的基本原理是向模型引入稀疏性,将某些参数或参数组设为零。然而,这种稀疏性的引入方式会显著影响实际效果,尤其是在计算效率方面。主要区别在于非结构化剪枝和结构化剪枝。非结构化剪枝:细粒度稀疏性非结构化剪枝,常被称为权重剪枝,在最细粒度的层面进行操作。它针对模型参数张量中的单个权重(如线性层中的权重矩阵或卷积滤波器)。核心思想简单明了:根据某些标准(最常见的是它们的绝对值),识别对模型输出贡献最小的权重并将其设为零。剪枝方法通过向模型引入稀疏性来发挥作用,即将某些参数或参数组置为零。然而,这种稀疏性引入的方式极大地影响实际效果,尤其是在计算效率方面。主要区别在于非结构化剪枝和结构化剪枝。W = [[1.2, -0.3, 0.8], [0.1, -2.1, -0.5], [-0.9, 0.05, 1.5]] # 经过幅度剪枝后(阈值 0.4) W_pruned = [[1.2, 0.0, 0.8], [0.0, -2.1, -0.5], [-0.9, 0.0, 1.5]]特点:灵活性: 提供最高的稀疏性潜力,因为它可以在不直接影响其他权重的情况下移除任何单个权重。这通常能实现模型尺寸的大幅缩减(指非零参数的数量),同时在相同稀疏度水平下,与结构化方法相比,仍能保持高准确率。准确率保持: 因为它只移除看似最不重要的单个权重,因此在发生显著的准确率下降之前,它通常能达到更高的稀疏度,而移除更大的结构块则不然。硬件挑战:尽管能达到较高的理论稀疏度(许多零值权重),非结构化剪枝在现代硬件(如GPU和TPU)上常常导致令人失望的实际加速效果。原因如下:不规则稀疏性: 生成的零模式不规则且分散。标准的稠密矩阵乘法算法和硬件高度优化用于连续的数据块。访问分散的非零元素会引入显著的内存访问开销,并打破这些加速器所依赖的可预测模式。专用核/格式: 为了获得加速,需要专用的稀疏矩阵格式(如压缩稀疏行 - CSR,或压缩稀疏列 - CSC)以及相应的计算核。尽管这些技术确实存在,但其性能优势通常只有在非常高的稀疏度水平(例如,>90-95%)下才能体现,而这可能在不导致无法接受的准确率损失的情况下难以达到。此外,管理稀疏索引的开销有时会抵消跳过零乘法带来的节省。控制流开销: 实现非结构化稀疏性通常需要条件逻辑(例如,“如果权重非零,则计算”),这可能在GPU等并行处理器上引入分支发散和指令开销。本质上,虽然浮点运算(FLOPs)的数量在理论上可能大幅减少,但实际的解决时间(延迟)通常不会按比例提高,有时甚至会降低,这是因为标准硬件无法高效处理细粒度、不规则的稀疏性。实现了用于存储或传输的模型尺寸缩减,但推理加速存在问题。结构化剪枝:粗粒度稀疏性结构化剪枝采取了一种更粗粒度的方法。它不移除单个权重,而是移除模型中整个结构单元。这些单元与网络的计算结构对齐。例子包括:通道剪枝: 移除卷积层中的整个输出通道(及相应的滤波器)或线性层中的行/列。滤波器剪枝: 移除整个卷积滤波器。注意力头剪枝: 移除Transformer模型中的整个注意力头。块剪枝: 将权重矩阵中的连续块置零。N:M 稀疏性: 一种半结构化方法,在一个由M个权重组成的小块中,N个权重必须为零(例如,2:4稀疏性在小向量中强制实现50%的稀疏性)。由于NVIDIA Ampere GPU等加速器上的直接硬件支持,这种方法受到了关注。考虑剪枝权重矩阵中的一整列(代表连接到下一层某个特定神经元的输出)或一整行(代表来自上一层某个特定神经元的输入):W = [[1.2, -0.3, 0.8], [0.1, -2.1, -0.5], [-0.9, 0.05, 1.5]] # 剪枝第2列(结构化) W_pruned_col = [[1.2, 0.0, 0.8], [0.1, 0.0, -0.5], [-0.9, 0.0, 1.5]] # 剪枝第1行(结构化) W_pruned_row = [[0.0, 0.0, 0.0], [0.1, -2.1, -0.5], [-0.9, 0.05, 1.5]]特点:硬件兼容性: 这是主要优点。移除整行、整列、整个滤波器或注意力头会产生更小、稠密的张量。可预测的加速: 这些更小的稠密操作可以被标准库(cuBLAS, cuDNN)和硬件加速器高效执行,而无需专用的稀疏核。由此产生的计算可以直接映射到GPU和TPU高度并行、优化的流水线上。潜在的准确率影响: 由于生成的运算仍然是稠密的(只是规模更小),因此观察到的加速通常与剪枝结构相关的FLOPs或参数数量的减少更直接相关。移除整个结构组对模型准确率的损害可能比移除单独选定的权重更大,尤其是在较高稀疏度水平下。一个完整的注意力头可能封装了某种特定的关系处理能力,完全移除它可能比在多个注意力头中移除等量的分散权重产生更明显的影响。可视化差异:下图描绘了由此产生的稀疏模式。非结构化剪枝产生分散的零,而结构化剪枝则移除整行/整列/整个块,留下更小的稠密结构。digraph G { rankdir=LR; node [shape=plaintext]; subgraph cluster_0 { label = "原始稠密矩阵"; style=filled; color="#e9ecef"; a [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> </TABLE>>]; } subgraph cluster_1 { label = "非结构化剪枝"; style=filled; color="#e9ecef"; b [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD></TR> <TR><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD></TR> </TABLE>>]; } subgraph cluster_2 { label = "结构化剪枝(列)"; style=filled; color="#e9ecef"; c [label=<<TABLE BORDER="0" CELLBORDER="1" CELLSPACING="0"> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> <TR><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#dee2e6">0</TD><TD BGCOLOR="#4263eb"> </TD><TD BGCOLOR="#4263eb"> </TD></TR> </TABLE>>]; } a -> b [label=" 针对单个\n低幅度权重 "]; a -> c [label=" 针对整个\n结构组 "]; }稀疏模式的可视化比较。蓝色单元格代表非零权重,灰色单元格代表已剪枝(零)权重。非结构化剪枝导致零点分散,而结构化剪枝则移除整列,形成更小、有效的稠密矩阵。权衡与考量在非结构化剪枝和结构化剪枝之间做出选择涉及权衡:非结构化: 稀疏性潜力高,准确率保持好,但在标准硬件上难以加速。主要用于模型压缩(减少存储/内存占用)。结构化: 在准确率显著下降之前,最大稀疏度较低,但生成的模型结构能高效映射到硬件,从而带来实际的推理加速。对加速计算更有效。选择通常取决于主要目标:如果模型尺寸缩减是重要考量(例如,对于存储受限的边缘设备),即使加速有限,也可能优先选择非结构化剪枝。如果推理延迟缩减是主要目标(例如,对于实时服务),结构化剪枝(或在有硬件支持的情况下采用半结构化N:M稀疏性)通常是更具实践性的方法。现代方法常尝试弥合这一差距,例如,通过开发更硬件感知的非结构化剪枝标准或研究混合技术。理解这一基本区别对于在LLM优化背景下有效地选择和应用剪枝方法十分重要,因为模型尺寸和推理速度都是重要考量。