Meta FAIR: 深层网络不合理的低效性

这篇文章的标题"The Unreasonable Ineffectiveness of the Deeper Layers"巧妙地呼应了著名物理学家尤金·维格纳在1960年发表的一篇论文"数学在自然科学中不合理的有效性"(The Unreasonable Effectiveness of Mathematics in the Natural Sciences)。维格纳在文中探讨了数学作为一种抽象工具,在描述和预测现实世界方面展现出的强大威力,而这种威力在某种程度上是出乎意料且难以解释的。

与之类似,这里的"不合理的低效性"表达了作者对深度神经网络中更深层的低效表现感到惊讶和疑惑。直觉上,我们可能会认为网络的深层部分应该发挥重要作用,负责提取更加抽象和高级的特征。然而,实验结果表明,至少在当前的架构和训练范式下,深层网络的很大一部分是低效甚至是多余的,去除这些层并不会显著损害模型的性能。这一发现对我们理解和设计深度神经网络提出了挑战和思考。

因此,这个标题简洁而巧妙地概括了全文的核心观点,同时也引发读者对深度学习的本质展开更广泛和深入的思考。

参考论文出处: https://arxiv.org/pdf/2403.17887

摘要

该研究对流行的开放权重预训练大型语言模型(LLM)系列进行了一个简单的层修剪策略的实证研究,发现在不同的问答基准测试中,在移除大部分层(高达一半)之前,性能只有很小的下降。为了修剪这些模型,该研究通过考虑层之间的相似性来识别最优的待修剪层块;然后,为了"修复"损坏,该研究执行少量的微调。具体而言,该研究使用参数高效微调(PEFT)方法,特别是量化和低秩自适应器(QLoRA),以便每个实验都可以在单个A100 GPU上执行。从实践的角度来看,这些结果表明,层修剪方法可以补充其他PEFT策略,一方面进一步减少微调所需的计算资源,另一方面可以改善推理的内存和延迟。从科学的角度来看,这些LLM对删除层的鲁棒性意味着,要么当前的预训练方法没有适当地利用网络更深层的参数,要么浅层在存储知识方面起着关键作用。

1 引言

在过去几年中,大型语言模型(LLM)已从单纯的研究产物演变为有用的产品。在很大程度上,这种演变可归因于用于训练的资源规模的大幅增加。由于这些模型在训练完成后的大部分生命周期中可能会在推理模式下看到最多的FLOPs,因此LLM的预训练不仅需要考虑高效(即计算最优)训练,还需要推理感知。

那些已经训练好的模型呢?除了神经缩放定律所表明的训练考量之外,还有许多用于降低LLM微调和推理成本和时间的后训练技术。特别是,量化可用于通过降低模型权重的精度来减少模型的内存占用,低秩自适应器(LoRA)可用于通过仅更新模型参数的一小部分来减少微调和定制的成本,或者修剪可用于通过直接消除不必要的参数或连接来减少内存占用和推理时间。由于这三种策略或多或少是正交的,因此在资源受限的环境中,理想情况下我们希望结合使用所有这三种后训练效率技术。朝着这个方向,流行的QLoRA方法引入了一些创新,使得参数的4位量化和LoRA微调可以协同工作。

在这些组合的基础上,该研究使用开放权重LLM研究了一种非常简单的修剪策略。具体来说,该研究开发了一种方法,使用不同层之间的表示相似性来识别给定修剪比例的最优层;然后,在移除这些层之后,该研究使用少量微调(使用QLoRA)来"修复"修剪引起的不匹配。该研究的主要结果是,在下游性能的最小降级的情况下,可以移除模型中相当大一部分最深层。例如,对于Llama-2-70B,在性能崩溃之前,可以消除大约一半的层。该研究策略和修剪Llama-2-70B的结果概述如图1所示。

在这里插入图片描述
图1:该研究的层修剪策略和示例结果的概述:(a)描述算法的流程图:如果要删除n个层,该研究找到最小化层ℓ和ℓ+n之间的角度距离d的层ℓ∗;然后删除从层ℓ∗开始的n个层;最后,如果需要,可以使用少量的(参数高效)微调来"修复"损坏。(b)示意图,描绘了删除总共n层,从ℓ∗到ℓ∗+n-1索引。©不同层数n与初始块层号ℓ之间的角度距离d;最下面的曲线(最暗的紫色)表示n=1,而最上面的曲线(最浅的黄色)表示n=64;黑线描绘了ℓ∗(n),即不同大小层块中角度距离的最小值。(d)修剪Llama-2-70B的结果,有修复(深蓝色)和无修复(浅蓝色)作为删除层的比例的函数:顶部(中间)面板给出了MMLU(BoolQ)问答基准测试的准确性,而底部面板给出了C4验证集的子集上的自回归损失;在这里,虚线红线(虚线灰线)表示原始未修剪模型(随机猜测)的准确性或损失;这些图说明了该研究发现的典型行为,其中对于问答任务的准确性(此处在40%-50%修剪比例之间),性能存在急剧的转变,但对于修复后的损失(深蓝色),连续性和缓慢增长一直持续到至少80%的修剪比例。

修剪不仅对减少推理的占用空间有用,而且还可以用于理解网络如何使用其参数:如果您可以在最小影响其性能的情况下删除网络的大块,那么这些块可能不是很重要。特别是,考虑到transformer架构的残差结构,该研究对丢弃层有如下直觉。更详细地说,最后一层的输出可以分解为所有模型层的输出之和加上嵌入的输入。如果这样的和具有众多且独立的项,那么删除其中几个应该不会显著改变输出。然而,由于这些项并不独立——每一层都是下一层的输入——如果某一层的残差贡献很小,那么该研究应该期望能够移除这些项。换句话说,如果每一层的输出在层与层之间不会发生太大变化。

与该研究的层修剪一起,该研究还调查了不同分离度下层表示的相似性,并广泛发现,与浅层相比,较深的层在定性上与相邻层更相似(最后一层除外)。这表明了一个更简单的修剪策略:从倒数第二层开始删除层,并从深到浅进行,直到删除所需数量的层。在这种情况下,该研究发现,在使用少量QLoRA微调修复损坏后,可以实现几乎与更复杂的相似性感知层修剪策略相匹配的性能。这种方法的有效性证明了LLM可能没有正确利用网络更深层的参数。

总的来说,该研究希望读者带走以下三点:

  • 模型的内存占用和推理时间随着删除层的数量呈线性减少。这使得层修剪成为一个强大的工具,特别是如果模型的性能对删除层具有鲁棒性。
  • 所有的效率方法——修剪、PEFT和量化——都可以有效地相互结合。因此,在这项工作中,每个实验都是在单个A100 GPU上执行的,开源和学术界都可以轻松访问。
  • 模型对删除更深层的鲁棒性,下游知识任务(例如MMLU和BoolQ)性能的急剧转变,以及自回归损失相对于这些修剪比例的平滑行为,共同表明浅层可能在存储知识方面起着关键作用。

本文的结构如下。在第2节中,该研究首先回顾了实用的后训练策略和深度学习科学研究的文献,为本工作提供了动机。然后,在第3节中,该研究给出了层修剪策略的直觉,并详细解释了方法,而在第4节中,该研究迭代了所有的实验结果。最后,在第5节中,该研究通过强调未来工作的方向来总结。具体的模型、微调、数据集和评估细节可以在附录A中找到,评估消融实验可以在附录B中找到。

2 文献综述

在本节中,该研究回顾了后训练效率的实用策略,并讨论了一些为该研究的方法提供动机或洞察力的科学研究:在第2.1节中,该研究首先回顾了修剪的历史,然后讨论了它在LLM中的现代应用;在第2.2节中,该研究将修剪与蒸馏(一种减少LLM参数数量的替代策略)进行对比;然后在第2.3节中,该研究讨论了各种实用的高效微调和推理加速方法,可以与修剪策略结合使用;最后在第2.4节中,该研究强调了一些关于LLM深度相关统计特性的科学研究,这些研究与该研究的结果是互补的。

2.1 修剪

修剪是通过删除不必要的参数(单独或作为一个组)来减小已训练的机器学习模型大小的方法。神经网络修剪有着悠久的历史,最初构想的非结构化修剪技术通过根据预定义的标准删除单个参数来稀疏化网络。例如,如果模型的参数值非常小,那么删除它(即将其设置为零)可能对性能影响最小。受这项早期工作的启发,现代研究人员开始探索此类非结构化修剪的不同标准,主要集中在计算机视觉模型上。特别是,参考文献开发了一种迭代修剪方法,用于交替修剪和微调网络,以达到更好的压缩比和性能。

虽然这些模型更小,但不一定更高效:通过根据标准删除单个参数来稀疏化网络会导致不规则或伪随机的稀疏化模式,如果没有专门为稀疏性设计的硬件或库,就很难加速。为此,开发了结构化修剪技术,以一起删除不相关的参数组,例如卷积网络中的特定通道或过滤器。随着它们实用相关性的提高,研究人员开始在计算机视觉和预transformer NLP架构中探索结构化修剪。

随着语言建模方面前所未有的进展,最近的工作重点是将结构化修剪方法应用于Transformer。这些研究几乎考虑了模型架构中每一个可能被消除的组件,方法从删除注意力头,到删除层,到修剪隐藏状态,到对大型权重矩阵进行秩约简,用更小的稠密矩阵替换稀疏权重矩阵,再到上述组的许多组合。

在先前也考虑transformer层丢弃的工作中,大多数研究BERT风格的模型,而该研究考虑了最常用于大规模语言建模和生成的解码器专用GPT风格模型。由于双向掩码语言建模(MLM)目标,BERT风格的模型天然适合理解任务,而GPT风格的模型由于其自回归目标而更适合生成。虽然最近更强大的GPT风格模型对这种划分提出了质疑,但先前的工作发现BERT和GPT模型在词的层表示演变方面存在显著的定性差异。总的来说,这表明层丢弃策略在两个系列之间的行为会有所不同。

一项针对BERT风格预训练模型的研究得出结论,最佳的层修剪策略是丢弃最后的层;这部分与该研究的结果相呼应,尽管相比之下,该研究发现(a)对于某些修剪大小,保留模型的最后几层实际上是有益的,(b)对于所有修剪大小,保留最后一层至关重要。此外,虽然作者也研究了不同层之间表示的相似性(与该研究的方法一样),但他们实际上发现浅层表示之间的相似性高于深层表示,这与该研究的结果非常不同。重要的是,参考文献中考虑的模型包含几亿个参数,比该研究考虑的模型规模小得多。也许正因为如此,尽管作者也对修剪后的模型进行了微调,但他们没有观察到该研究在第4.1节中报告的下游准确性的急剧转变。

相比之下,虽然参考文献考虑了GPT风格的模型,但方法与该研究有很大不同:(i)该研究不是先预训练然后使用固定的层丢弃策略,而是在修改的预训练过程中逐步丢弃层;(ii)作者研究了他们自己的sub-1B参数模型,而该研究重点关注常用于实际应用的、现成的、开放权重的大规模2.7B-70B参数模型系列。

最后,在wav2vec模型的背景下,transformer中层丢弃的系统方法也得到了研究,wav2vec模型是将语音映射到嵌入的仅编码器模型,其大小在亿参数量级。对于这些模型, 开发了一种基于层与下游指标之间相关性的层修剪算法。除了模型架构和领域之外,该工作的一个显著区别是,考虑了非连续的修剪方案,例如丢弃交替层。该研究对层修剪的直觉预测,这不应该像创建多个不匹配那样有效,每个不匹配对应一个被删除的层块。

2.2 模型蒸馏

另一种完全不同的减小已训练机器学习模型大小的方法是模型蒸馏, 其中知识通过训练学生模型以教师模型预测的分布为目标从大型"教师"模型转移到较小的"学生"模型。基本的见解是,这可以将教师的非常通用的知识和能力转化为更简化、压缩和可能特定于技能的表示。

虽然是一种非常通用的技术,但在语言模型的设置中,蒸馏已经通过以下方式实现:(a)白盒方法,其中学生被训练以模仿教师的logits或隐藏状态;以及(b)黑盒方法,其中学生只能访问教师生成的输出tokens。后一种方法广泛涵盖了学生在教师以某种方式增强的文本上接受训练的情况,例如通过添加合成标签、生成高质量的合成文本、提供思维链推理(旨在增强学生的推理技能)或通过注释指令来增强学生的指令遵循能力。

与层修剪相比,这些蒸馏方法需要大量计算资源,因为它们依赖于大型教师来处理大量数据。相比之下,该研究基于相似性的修剪策略只需要计算预训练语料库的一小部分上不同层之间的相似性,而该研究的第二个更简单的修剪策略只使用修剪后的简化模型。

2.3 高效微调和推理加速

除了直接减小模型的大小之外,参数高效微调(PEFT)侧重于降低将LLM专门化为某些任务的成本。特别是,低秩自适应器(LoRA)通过冻结预训练模型并引入参数上小的额外可训练权重来减少微调的内存和计算。该研究使用其量化版本QLoRA来保持实验的成本效率。可以与该研究工作结合的其他PEFT方法是参考文献: 在第一种情况下,LoRA矩阵的初始化根据量化方案进行调整;在第二种情况下,不同LLM模块的LoRA秩以自适应方式选择。

为了获得额外的效率提升,该研究可以将层修剪模型与进一步加速推理的方法相结合:使用推测解码,tokens从较小的草稿模型快速生成,然后由主模型并行评估;使用Medusa,草稿模型被丢弃以换取额外的解码头,但最终达到类似的效果。特别是,考虑在推测解码设置中将高度压缩的层修剪模型作为潜在的草稿模型可能很有趣。

2.4 广泛的深度相关研究

最后,让该研究强调一些研究LLM深度相关属性的科学工作。

一个相关的方向考虑知识和语言特性如何在语言模型中编码。一方面,参考文献分析了事实关联的存储和回忆:这些工作强调知识局部化在中间或最后层中,这对直接编辑或擦除模型的部分事实知识有影响。另一方面,尝试执行此类编辑提供了信息可能在层之间非局部存储的证据。相关研究了在推理期间处理事实的方式,区分了注意力头的作用(用于属性提取)和MLP块的作用(用于主题丰富):两者都分散在几个层中。

接下来,继之前的"逻辑镜头"之后,发明了一种称为"调谐镜头"的技术,通过使用可学习的仿射变换将中间表示转换为tokens上的分布来研究预测的轨迹。通过研究这种分布的层到层动态,作者注意到它趋于收敛。这种收敛强烈表明,较深的层可能是可修剪的,而事实上他们必须训练一个仿射探测器可能与该研究的观察有关,即最后一层不能被修剪。有点相关的是观察到只要激活深度超过网络前向传递的一半,就可以从在中间激活上训练的线性探测器确定基础文本中的地理特征。

更抽象地发现,激活的稀疏性在网络前向传递的大约一半处发生转变,从稀疏演变为密集。也许与此相关研究了哪些模型权重在微调期间更新最多,发现它们位于中间层。

总的来说,这些深入研究与该研究工作是互补的,一方面,该研究提供证据表明,删除LLM的最深层不会显著改变模型的性能,另一方面,该研究展示了在删除大约一半LLM最深层后的急剧修剪转变。

3 方法

在本节中,该研究给出了为什么认为层修剪有效的直觉(第3.1节),然后详细解释了方法(第3.2节)。

3.1 直觉

该研究对层丢弃的直觉来自将表示视为层索引的缓慢变化函数。具体而言,transformer的层到层表示演化由残差迭代方程给出

x ( ℓ + 1 ) = x ( ℓ ) + f ( x ( ℓ ) , θ ( ℓ ) ) x^{(ℓ+1)} = x^{(ℓ)} + f(x^{(ℓ)}, θ^{(ℓ)}) x(+1)=x()+f(x(),θ())

其中 ( x ( ℓ ) , θ ( ℓ ) ) (x^{(ℓ)}, θ^{(ℓ)}) (x(),θ())分别是第 ℓ ℓ 层的多维输入和参数向量, f ( x , θ ) f(x, θ) f(x,θ)描述了一个多头自注意力和MLP层块的变换。对于任何残差网络,如果展开这个迭代,我们可以看到,在总共 L L L层之后,输出可以描述为所有层变换的总和

x ( L ) = x ( 0 ) + ∑ ℓ = 0 L − 1 f ( x ( ℓ ) , θ ( ℓ ) ) x^{(L)} = x^{(0)} + \sum_{ℓ=0}^{L-1} f(x^{(ℓ)}, θ^{(ℓ)}) x(L)=x(0)+=0L1f(x(),θ())

如果总和中的项是众多的 ( L ≫ 1 ) (L ≫ 1) (L1)和独立的,例如,如果块函数是输入的函数 f ( x ( 0 ) , θ ( ℓ ) ) f(x^{(0)}, θ^{(ℓ)}) f(x(0),θ()),那么对和(2)的任何特定贡献都可以被忽略。

当然,它们根本不是独立的:如果我们删除第 ℓ − 1 ℓ-1 1层,那么我们现在必须将该层的旧输入 x ( ℓ − 1 ) x^{(ℓ-1)} x(1)连接到第 ℓ ℓ 层的块函数,如下所示

x ( ℓ + 1 ) = x ( ℓ − 1 ) + f ( x ( ℓ − 1 ) , θ ( ℓ ) ) x^{(ℓ+1)} = x^{(ℓ-1)} + f(x^{(ℓ-1)}, θ^{(ℓ)}) x(+1)=x(1)+f(x(1),θ())

为了清楚起见,尽管删除了层,但我们没有重新标记层或输入。通常,原始输入和新输入之间的这种不匹配应该对网络非常有害。然而,如果在一些初始层之后,表示收敛到关于层索引的缓慢变化函数,

x ( ℓ ) ≈ x ( ℓ − 1 ) + ϵ x^{(ℓ)} ≈ x^{(ℓ-1)} + ϵ x()x(1)+ϵ

其中在某种适当的意义上 ϵ ≪ x ( ℓ ) ϵ ≪ x^{(ℓ)} ϵx(),那么删除特定层 ℓ ℓ (例如,在从(1)到(3)的过程中进行替换 x ( ℓ ) → x ( ℓ − 1 ) x^{(ℓ)} → x^{(ℓ-1)} x()x(1))应该只会使后续层 x ( ℓ + 1 ) x^{(ℓ+1)} x(+1)中的表示发生很小的变化。类似地,要成功修剪第 ℓ ℓ 层之前的 n n n层,即从 ℓ − n , . . . , ℓ − 1 ℓ-n,...,ℓ-1 n,...,1索引的那些层,我们希望修剪块的输入与修剪块的输出非常相似:

x ( ℓ ) ≈ x ( ℓ − n ) + ϵ x^{(ℓ)} ≈ x^{(ℓ-n)} + ϵ x()x(n)+ϵ

无论如何,任何层删除都有级联效应:由于修剪后 x ( ℓ + 1 ) x^{(ℓ+1)} x(+1)是由与之前不同的函数计算的,参见(1)与(3)的对比,并且由于 x ( ℓ + 1 ) x^{(ℓ+1)} x(+1)直接或间接地输入到后续层 ℓ + 2 , . . . , L ℓ+2,...,L +2,...,L,删除浅层应该比删除深层产生更大的影响。

由此,该研究有以下假设,将通过实验进行测试:
(0)该研究应该能够修剪残差网络的层。
(1)该研究在修剪更深的层时应该有更大的成功。
(2)该研究成功修剪的层块应该具有与其输入相似的输出。

在下一小节第3.2节中,该研究将解释修剪算法的细节,在接下来的第4节中,该研究将提供支持(0)-(2)点的实验证据。

3.2 层修剪算法

该研究的主要层修剪算法非常简单:
0. 选择要修剪的层数 n n n

  1. 在中性预训练数据集或代表感兴趣的下游任务的数据集上,计算第 ℓ ℓ 层的输入 x ( ℓ ) x^{(ℓ)} x()和第 ℓ + n ℓ+n +n层的输入 x ( ℓ + n ) x^{(ℓ+n)} x(+n)之间的角度距离 d ( x ( ℓ ) , x ( ℓ + n ) ) d(x^{(ℓ)}, x^{(ℓ+n)}) d(x(),x(+n)),参见下面的(7)式。
  2. 找到使该距离最小化的层 ℓ ⋆ ℓ^⋆ :
    ℓ ⋆ ( n ) ≡ arg ⁡ min ⁡ ℓ d ( x ( ℓ ) , x ( ℓ + n ) ) ℓ^⋆(n) ≡ \arg\min_ℓ d(x^{(ℓ)}, x^{(ℓ+n)}) (n)argmind(x(),x(+n))
  3. 删除层 ℓ ⋆ ℓ^⋆ ℓ ⋆ + n − 1 ℓ^⋆+n-1 +n1;将旧的第 ℓ ⋆ ℓ^⋆ 层的输入连接到旧的第 ( ℓ ⋆ + n ) (ℓ^⋆+n) (+n)层块。
  4. (可选)在中性预训练数据集或特定感兴趣的数据集上,使用少量微调来修复第 ℓ ⋆ + n ℓ^⋆+n +n层的不匹配。

如果图中的文字比枚举列表中的文本对你更有帮助,那么请注意,该算法也描述在图1的(a)-(b)面板中。

详细说明第一步,单个序列长度为 T T T的角度距离由下式给出

d ( x ( ℓ ) , x ( ℓ + n ) ) ≡ 1 π arccos ⁡ ( x ( ℓ ) T ⋅ x ( ℓ + n ) T ∥ x ( ℓ ) T ∥ ∥ x ( ℓ + n ) T ∥ ) d(x^{(ℓ)}, x^{(ℓ+n)}) ≡ \frac{1}{π} \arccos(\frac{x^{(ℓ)^T} \cdot x^{(ℓ+n)^T}}{\|x^{(ℓ)^T}\| \|x^{(ℓ+n)^T}\|}) d(x(),x(+n))π1arccos(x()T∥∥x(+n)Tx()Tx(+n)T)

其中内积是在序列的最后一个token T T T的模型隐藏维度上, ∥ ⋅ ∥ \|\cdot\| 表示 L 2 L^2 L2范数,系数 1 / π 1/π 1/π是约定。然后,这个距离应该在足够多的样本上求和,以获得低波动估计,但总体上应该相当小。

详细说明最后一步的"可选性",该研究发现,在问答基准测试中几乎没有性能下降,参见图1(d)和第4.1节中的其他内容,可以通过少量微调扩展到更大的修剪比例。根据资源限制和修剪模型的预期应用,这可能不是必需的。然而,修复过程确实对困惑度有重大影响,参见图1(d)和第4.2节中的其他内容。

对于角度距离测量和修复,如果最终目标是针对下游任务进行监督微调(SFT),则可能有助于评估该数据集样本的距离,然后将修复过程与SFT结合起来。相反,为了获得最大的通用性,最自然的做法是使用近似模型最初预训练时的统计数据的预训练数据集来测量距离和修复。

最后,该研究还研究了一个更简单的修剪策略,其灵感来自分析不同模型系列之间的角度距离:删除最深的层(不包括LLM头之前的最后一层),然后(非可选地)修复损坏。为了完全清晰,这意味着如果从一个 L L L层的模型中修剪 n n n层,那么将删除 ( L − n ) (L-n) (Ln) ( L − 1 ) (L-1) (L1)层(含)。

4 结果

在本节中,该研究展示了修剪策略在不同问答(QA)基准测试中的有效性,并强调了性能中稳健的修剪驱动转变(第4.1节),而相比之下,该研究发现修复后修剪模型的自回归困惑度在其转变点处是连续的(第4.2节);然后,在比较了模型大小和系列之间不同层的相似性统计之后(第4.3节),该研究将主要的相似性感知修剪策略与更简单的删除最深层策略进行了对比(第4.4节)。

在这里插入图片描述

4.1 QA基准的准确性

该研究的第一组结果如图2所示,其中绘制了5-shot MMLU准确性与删除层比例的关系:在左面板中,该研究展示了Llama-2系列,在中间面板中,该研究展示了Qwen系列的模型,在右面板中,该研究显示了Mistral-7B和Phi-2。为了更好地比较具有不同总层数的模型,在这些图中,该研究选择通过删除层的比例(而不是删除层的绝对数量)来规范化x轴。请注意,由于MMLU包含四个可能响应的多项选择题,随机猜测的预期准确性为25%。

重要的是,该研究看到了一个特征性的稳健性能平坦区域,然后在Llama-2系列模型的45%-55%修剪比例、Mistral 7B的35%、Phi-2的25%和Qwen系列模型的20%左右的修剪比例处,急剧过渡到随机准确性。这意味着即使修剪比例可能相当大(!),在最终删除该知识之前,实现模型最高得分所需的基本知识不会因大量删除层而被删除。将带有和不带有修复曲线进行对比,该研究看到微调提供了适度的改进,通过更好地保持未修剪的性能并将随机猜测的相变推移到略大的修剪比例。

总的来说,该研究看到,对于更大和更深的模型(例如Llama-2-13B和Llama-2-70B),层修剪更加稳健,该研究推测这可能与以下事实有关:要么较小的模型过度训练,使参数冗余度降低,要么更深的模型在绝对意义上可以承受更多层的损失。此外,Qwen系列很奇怪,该研究将在第4.3节中进一步阐述这一事实。

在这里插入图片描述

4.2 下一个token预测的损失

在本节中,该研究研究了层修剪对预训练优化目标(下一个token预测的交叉熵损失)的影响,当在C4验证数据集的子集上评估时。为了在具有不同大小词汇表 V V V的模型之间进行公平比较,该研究通过 log ⁡ V \log V logV对损失进行了归一化,这对应于以均匀概率随机采样tokens的损失。(更多细节请参见附录A.2。)

在图3中,该研究绘制了所有七个模型的归一化C4验证损失,修复后(左面板)和修复前(右面板),作为删除层比例的函数。在没有修复的情况下,该研究看到每个模型在大约与QA基准准确性也急剧过渡到随机猜测的修剪比例处有一个有点急剧的过渡到随机猜测,这表明模型在这一点上已经无可救药地受损,参见图2。接下来,对比两个图的尺度,该研究看到修复显著恢复了所有模型的下一个token预测能力,接近未修剪水平,损失随着层丢弃缓慢线性增加。最引人注目的是——从科学的角度来看——修复后的连续性贯穿了该研究先前发现QA基准存在急剧转变的修剪比例:这种解耦说明了一种断开(或创造失准)下游任务性能(如MMLU和BoolQ)与连续性能度量(如交叉熵损失)之间联系的方法。

4.3 表示之间的角度距离

考虑到角度距离(7)在该研究修剪策略中的核心作用,让该研究花一小节来看看这七个模型之间的这些距离。对于这个分析,每个模型的角度距离在C4验证集的10k个样本上进行了平均。

在这里插入图片描述

回想一下早期的图1©:对于Llama-2-70B,它绘制了比较第 ℓ ℓ 层和第 ( ℓ + n ) (ℓ+n) (+n)层的角度距离 d ( x ( ℓ ) , x ( ℓ + n ) ) d(x^{(ℓ)}, x^{(ℓ+n)}) d(x(),x(+n)),对于从 n = 1 n=1 n=1 n = 64 n=64 n=64的块大小,跨越所有初始索引 ℓ ℓ ;曲线的最小值 ℓ ⋆ ( n ) ℓ^⋆(n) (n)给出了给定 n n n的最优修剪块,参见(6)式。一种更紧凑的显示相同数据的方式如图4的热图所示:每个方块都用颜色表示层 ℓ ℓ ℓ + n ℓ+n +n之间的行归一化角度距离,对所有可能的 ℓ ℓ 和直到总层数的很大比例的 n n n;给定块大小的最优修剪层 ℓ ∗ ( n ) ℓ^∗(n) (n)对应于每行中的最小距离。

跨模型,该研究进行了两个概括:(i)最小距离出现在更深的块上,这意味着更深的层通常与彼此非常相似,并且可以更容易地丢弃;(ii)最深块(包括最后一层的块)上的距离取最大值或接近最大值,这意味着不应该丢弃最后一层。虽然广泛适用,但也有一些例外。对于某些模型,例如Phi-2-2.7B,或者对于某些模型中最大的块,例如Llama-2-7B,最后几层似乎很重要。如前所述,Qwen系列有点不同寻常:在这里,该研究看到对于浅层块有一些奇怪的高相似性"孤岛";这可能解释了图2中较短的稳健性能区域。

4.4 一个更简单的修剪策略

受最近结论的启发,该研究尝试了一个非常简单的启发式修剪策略:
(1)如果从一个 L L L层的模型中修剪 n n n层,删除 ( L − n ) (L-n) (Ln) ( L − 1 ) (L-1) (L1)层,以便删除不包括最后一层的最深块;
(2)然后像以前一样用少量微调来修复。

与该研究主要的相似性感知修剪策略相比,这个更简单的启发式算法具有优势,即从不需要从业者在GPU上加载或推断未修剪的模型。它还提供了优化待修剪块重要性的有意义的消融。

在这里插入图片描述

在图5中,该研究对比了两种修剪策略,修复前(左面板)和修复后(右面板),用于QA基准测试(MMLU/BoolQ,上/中面板)和自回归损失(C4验证,下面板)。一方面,在修复修剪引起的损坏之前,简单的启发式方法表现得很差:QA基准的准确性随着修剪比例的增加迅速下降到(接近)随机,即使修剪量很小,损失也开始非常快地增加。另一方面,在修复之后,两种修剪策略在评估中的结果非常相似:对于QA基准,相似性感知算法在相变之前略微更好地保持了准确性,尽管简单算法可能将相变推到略大的修剪比例;对于损失,曲线几乎重叠,尽管相似性感知策略在所有修剪量上都略微优于简单策略。这些实验有力地证明,后修剪微调的目的是修复修剪接口处的损坏,而不是获取额外的知识。

5 讨论和未来方向

从开放权重的LLaMA系列的发布开始,开源机器学习社区聚集在让每个人都可以访问LLM的理念周围。这引发了围绕效率的许多创新,例如LoRA和量化(与LoRA),允许在仅单个80GB A100 GPU上微调大型(接近)最先进的70B模型。与这些其他工具结合使用,该研究的工作通过一种易于实现的层修剪技术实现了进一步的效率提升。

具体而言,发布的Llama-2-70B版本跨越140 GB内存,每个token消耗大约 3 × 1 0 10 3 × 10^{10} 3×1010个FLOP。通过4位量化和50%的层修剪比例,该模型大约占用17.5 GB内存,每个token需要大约 1.5 × 1 0 10 1.5 × 10^{10} 1.5×1010个FLOP:从16位bfloat量化到4位QLoRA精度将模型内存减少4倍,但保持FLOP或多或少相同,因为计算是以16位精度执行的;层修剪还将进一步按与层修剪比例相等的量减少内存和FLOP。这些内存和计算要求使得开放权重的最先进模型能够在消费级GPU上高效运行,甚至无需任何CPU卸载即可进行微调,并且只有很小的性能折衷。

在工作结束时,该研究留下了以下问题:

  • 有哪些更好的层修剪策略?有哪些更好的修复方法?
  • 为什么修复消除了损失中的相变,但不消除QA准确性中的相变?
  • 通过更全面的评估,不同任务的准确性是否会在不同深度下降?
  • 相关地,知识通常存储在浅层或中间层,还是非局部化的?
  • 预训练细节是否影响修剪能力,例如,缩放定律过度训练或蒸馏模型是否更难修剪?
  • 如何使LLM更有效地使用其最深层中的参数?

其中一些问题将受益于跨不同预训练检查点研究层相似性和修剪;例如,QA准确性中的急剧相变和临界深度在什么时候出现,更多的训练是否会导致更好地利用可修剪参数?其他问题表明需要探索具有不同预训练架构和目标的模型,例如为了更好地利用更深的层。通过更全面的评估,如果不同类型的任务在非常不同的深度下降,那么这可能表明完成这些任务所需的知识存储在不同的深度。使用修剪系统地研究这些可解释性问题将非常有趣。

A 实验细节

在这里,该研究解释了模型和修复(§A.1)以及评估(§A.2)的各种细节。

A.1 模型和修复细节

本文中的所有模型都使用Hugging Face Trainer API进行了微调。模型列表及其在Hugging Face上的路径如下:

在这里插入图片描述

对于修复,该研究使用了来自Hugging Face的Colossal Clean Crawled Corpus (C4)版本:data = load_dataset(“c4”, ‘en’)。该研究按照后面段落中的描述截断了长样本,并在可用时添加了特殊tokens。模型以16的全局批量大小训练了5000步:这对应于每个模型的总微调tokens为16 × 5000 ×[max_seq_length]。该研究使用了余弦退火学习率调度,warm-up为100步。

如果可能,peak学习率设置为模型预训练的peak学习率;在实践中,这意味着所有模型都以3e-4的peak LR进行训练,Phi-2除外,它在预训练期间以2e-4的peak LR进行训练,Llama-2-70B以3e-5的peak LR进行训练(这是扫描的结果),Mistral-7B以3e-6的peak LR进行训练(也是扫描的结果)。所有7B参数或更小的模型都以2048 tokens的最大序列长度进行训练,而所有13B参数或更大的模型都以4096 tokens的最大序列长度进行训练。虽然该研究意识到某些模型可能已经在更长的序列上进行了预训练,例如Qwen-the-outlier,但该研究决定在类似大小的模型中保持最大序列长度一致,以允许在模型系列之间进行更公平的比较。

在Hugging Face Trainer API之上,该研究在所有微调中使用了量化和低秩自适应器(LoRA):

  • 对于量化,该研究使用bitsandbytes库进行QLoRA将模型量化为4位。

  • 对于LoRA,该研究使用Hugging Face peft库。该研究将LoRA dropout设置为0.05,并保持LoRA α等于LoRA秩。除了两个例外(下面讨论),模型以64的LoRA秩进行训练。

  • 同样该研究仅将LoRA应用于FFN模块:对于Llama-2和Mistral模型为[“gate_proj”, “down_proj”, “up_proj”],对于Phi-2为[“fc1”, “fc2”],对于Qwen模型为[“w1”, “w2”, “c_proj”]。

这些超参数选择中的绝大多数是标准的,可以在之前的工作中找到。为了绝对清晰,该研究列出了下面的所有模型特定架构和修复细节:

该研究还有以下所有模型共有的超参数:

在这里插入图片描述

A.2 评估细节

该研究进行了三个主要评估:MMLU准确性、BoolQ准确性和C4损失。

对于MMLU准确性:

  • 该研究使用来自Hugging Face的cais/mmlu版本的数据集。
  • 该研究遵循原始参考文献中建议的格式,没有进一步的提示工程。
  • 对于构建few-shot样本,该研究使用cais/mmlu中的dev集。
  • 对于实验,该研究使用0个few-shot样本;结果和分析对这个选择是稳健的,参见图7。
  • 该研究报告所有科目的平均准确性。

对于BoolQ准确性:

  • 该研究使用来自Hugging Face的hassansh/boolq_n_shot版本。
  • 对于实验,该研究使用0个few-shot样本。
  • 完整的BoolQ结果如图6所示(在正文中被截断):在左面板中,该研究展示了Llama-2系列,在中间面板中,该研究展示了Qwen系列的模型,在右面板中,该研究应该显示Mistral-7B和Phi-2;该研究还使无修复的实验半透明,以更好地显示完整相似性感知修剪方法的结果。重要的是,虽然该研究在这里看到修复比在图2的MMLU中发挥更重要的作用,但在修复后,仍然存在稳健性能的特征平坦区域;与之前一样,在达到模型相关的临界阈值之前,通过大量层修剪不会消除实现模型最高分数所需的能力。

对于C4验证损失:

  • 该研究使用来自Hugging Face的c4版本(即将被allenai/c4取代)。
  • 该研究使用验证拆分进行评估,因为使用训练拆分进行了修复。
  • 鉴于其大小,该研究随机抽取了60k个序列,并在所有模型中保持不变。
  • 在图3中,为了便于跨具有不同词汇表大小的模型系列进行公平比较,该研究将损失归一化:归一化时,除以 log ⁡ V \log V logV,其中 V V V是每个模型的词汇表大小(在§A.1的表中列出)。这个 log ⁡ V \log V logV对应于均匀采样tokens的损失,自然为给定模型设置了尺度。

在这里插入图片描述

B 消融实验

在这里,该研究详细说明了各种超参数的消融实验:提示(§B.1)、微调种子(§B.2)、LoRA秩(§B.3)。定性地说,本文的结果对于任何这些因素的变化都相当稳健。

B.1 提示

众所周知,在QA评估中改变提示会显著影响结果。为了控制提示,该研究对§3.2中描述的主要相似性感知修剪在应用于Llama-2-13B时的MMLU准确性进行了消融实验:在图7的左面板中,该研究显示了改变提示中few-shot样本顺序的结果,在同一图的右面板中,该研究显示了改变few-shot样本数量的结果。总的来说,该研究看到层修剪方法对这些变化是稳健的。

B.2 微调种子

在这里,该研究改变微调种子。对于所有实验,该研究使用以下代码片段来确保可重现性:

SEED_VAL = 0
transformers.enable_full_determinism(SEED_VAL)

由于从预训练模型开始,微调种子不会影响初始化,但它会影响进一步训练的随机方面,例如数据顺序。为了控制这一点,该研究对§3.2中描述的主要相似性感知修剪在应用于Llama-2-13B时的微调种子进行了消融实验:在图8中,该研究观察到层修剪方法对种子的选择是稳健的。

在这里插入图片描述
在这里插入图片描述

B.3 LoRA秩

在这里,该研究改变用于修复的LoRA秩。不幸的是,该研究的计算预算不允许在所有实验配置中进行详尽的扫描。作为替代,该研究采用了以下协议进行主要实验:

  • 从64的秩开始,遵循QLoRA设置(例如,参见参考文献[19]的附录B.2)。
  • 如果用该秩修复会显著损害性能(与不修复相比),则扫描该模型的LoRA秩,并根据其MMLU准确性选择表现最佳的LoRA秩用于其他评估。

该协议旨在最大化修复在所有评估中改善性能的机会。为简单起见,该研究使用简单修剪启发式运行了这个选秩协议,Llama-2-70B除外。

在实践中,这导致该研究对每个模型使用秩64,Mistral-7B(秩4)、Llama-2-7B(秩2)和Llama-2-70B(秩8)除外。(要以表格形式查看相同信息,请参见§A.1中的第二个表。)图9显示了支持这些选择的Mistral-7B(左下面板)、Llama-2-7B(中下面板)和Llama-2-70B(右上面板)的MMLU准确性扫描:总的来说,虽然LoRA秩对修复模型的定性行为没有显著影响,但降低LoRA秩通常会提高性能。在图9的左上和中上面板中,该研究显示了Mistral-7B(上)和Llama-2-7B(中)使用相似性感知修剪策略的相应扫描:该研究看到,对于这种修剪方法,两个模型都更加稳健,尽管秩2仍然是Llama-2-7B的最佳表现秩。

在这里插入图片描述

Llama-2-7B MMLU准确性随着LoRA秩的降低而特征性地提高(即使对于极低的秩(!)),这需要一个解释。一种可能性是,降低LoRA秩可以更好地正则化微调以防止过拟合。特别是,细心的读者可能会对§A.1中关于peak学习率的讨论感到惊讶:模型以与预训练相同的peak进行微调;64的"大"LoRA秩引入了大量额外参数,可能会过拟合到C4。这种过拟合肯定是有害的,因为该研究考虑的模型的实际预训练数据集(a)对该研究是未知的,(b)可能比C4有显著更高的质量。

该研究直接为Mistral-7B研究了这一点。在图9的右下面板中,该研究绘制了不同LoRA秩下的C4验证损失:该研究看到,虽然降低LoRA秩通常会提高MMLU准确性(参见最左面板),但同时它会损害C4验证损失。这支持了该研究的过拟合假设。在未来有更多资源的情况下,通过考虑其他形式的正则化和学习率调整来改进修复过程将很有趣。

总结自己的见解

该研究对实验细节的详细描述,包括所使用的模型、修复过程、评估方法以及各种消融实验,有助于读者全面理解该工作,并为未来的研究提供了坚实的基础。

几个有趣的观察结果:

  1. LoRA秩对修复性能的影响很大。降低LoRA秩通常可以提高下游任务的性能,但会损害自回归的验证损失。这表明LoRA秩的选择需要在过拟合和欠拟合之间取得平衡。未来的工作可以探索如何自适应地选择LoRA秩,以优化修复性能。

  2. 提示工程和随机种子对实验结果的影响相对较小。这表明该研究提出的层修剪方法具有一定的稳健性。然而,在将该方法应用于新模型或新任务时,仍然需要谨慎地选择超参数。

  3. 不同模型在最佳超参数设置上存在差异。例如,Mistral-7B和Llama-2-7B在低LoRA秩下表现最佳,而其他模型则使用默认的秩64。这强调了为每个模型单独调整修复策略的重要性。

总的来说,该研究的实验设置全面而严谨,支持了本文的主要结论。同时,消融实验也为改进修复策略提供了有价值的见解。未来的工作可以在这些实验的基础上,进一步优化层修剪算法,并将其应用于更广泛的模型和任务。此外,深入研究不同模型在最佳超参数设置上的差异可能有助于揭示它们在知识表示和存储方面的内在差异。

最后,我想强调的是,该研究在实验细节部分所展示的开放性和透明性值得称赞。通过详细报告所使用的模型、数据集、评估指标和超参数设置,该研究使其他研究人员能够复现实验结果,并在此基础上进行进一步的探索。这种开放性对于推动自然语言处理领域的发展至关重要。

该研究展示了一种简单而有效的层修剪方法,可以显著减少LLM的推理时间和内存占用,同时在下游任务上保持接近原始未修剪模型的性能。这表明目前的预训练方法可能没有充分利用LLM更深层的参数,或者浅层在存储知识方面起着关键作用。

该研究的修剪策略基于不同层之间表示的相似性,这种相似性可以通过计算角度距离来衡量。实验结果表明,在LLM中,更深的层通常比浅层更相似,这为修剪更深的层提供了直觉和理论依据。有趣的是,最后一层似乎总是与其他层非常不同,表明它可能在LLM的计算中起着独特的作用。

另一个有趣的发现是,在应用修剪后,下游任务的性能(如问答)表现出急剧的相变行为,而自回归损失则表现出连续性。这种解耦现象值得进一步研究,因为它可能揭示语言模型的一些内在属性。

展望未来,该研究提出了几个有趣的问题,例如如何开发更好的修剪和修复策略,不同类型知识在LLM中的分布方式,以及预训练方法如何影响修剪性能等。这些问题的探索将有助于我们更好地理解LLM的工作原理,并进一步提高其效率。此外,将修剪与其他参数高效方法(如量化、知识蒸馏)相结合也是一个有前景的研究方向。

该研究工作是迈向更高效、更可解释的LLM的重要一步。随着该领域的快速发展,期待在未来看到更多关于LLM压缩和理解的突破性工作。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/608992.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

FPGA+炬力ARM实现VR视频播放器方案

FPGA炬力ARM方案,单个视频源信号,同时驱动两个LCD屏显示,实现3D 沉浸式播放 客户应用:VR视频播放器 主要功能: 1.支持多种格式视频文件播放 2.支持2D/3D 效果实时切换播放 3.支持TF卡/U盘文件播放 4.支持定制化配置…

Linux运维:centos环境变量

前言 在 Linux 运维工作中,管理环境变量是至关重要的一项任务。在 CentOS 环境下,正确配置环境变量可以使系统更加高效和易于管理。 本文将重点讨论 CentOS 环境下的环境变量设置,并就python的环境变量配置方案进行讲解(不包含Ano…

AutoModelForCausalLM.from_pretrained 函数调用本地权重报错

文章目录 1、代码报错的位置(前情提要)finetune_lora.shfintune_clm_lora.py 2、报错截图2.1、huggingfaces上的 meta-llama/Llama-2-7b-chat-hf2.2、服务器上模型文件路径 3、特别注意事项 1、代码报错的位置(前情提要) 在终端直…

06.命令的组合使用

命令的组合使用 1.查询当前整个系统每个进程的线程数 我们经常遇到这样的问题,比如某台服务器的CPU 使用率飙升,通过top命令查看是某个程序(例如java)占用的cpu比较大,现在需要查询java各个进程下的线程数情况。可以通…

Reactor Netty HTTP 服务器端-响应式编程-014

🤗 ApiHug {Postman|Swagger|Api...} = 快↑ 准√ 省↓ GitHub - apihug/apihug.com: All abou the Apihug apihug.com: 有爱,有温度,有质量,有信任ApiHug - API design Copilot - IntelliJ IDEs Plugin | Marketplace The Next Generation API Development Platform …

风扇开启执行逻辑

执行流程 public static void businessExecutionWork(){//以下为业务逻辑部分System.out.println("1、根据电池包控制风扇服务执行 开始!");//1、获取电池包电压、电流、环境温度//获取电池包电压、电流、环境温度ObtainBatteryDataService obtainBatteryDataServic…

Docker 怎么将映射出的路径设置为非root用户权限

在Docker中,容器的根文件系统默认是由root用户拥有的。如果想要在映射到宿主机的路径时设置为非root用户权限,可以通过以下几种方式来实现: 1. 使用具有特定UID和GID的非root用户运行容器: 在运行容器时,你可以使用-u…

监控异地组网怎么组网?

监控异地组网是指在不同地域的网络环境下,实现对监控设备的远程访问和管理。在传统的网络环境下,由于网络限制和设备配置等问题,监控设备的远程访问往往受到一定的限制和困扰。为了解决这个问题,引入了天联组网技术,实…

Mysql幻读

幻读指的是一个事务在前后两次查询同一个范围的时候,后一次查询看到了前一次查询没有看到的行。 幻读仅专指“新插入的行” 在可重复读隔离级别下,普通的查询是快照读,是不会看到别的事务插入的数据的。因此,幻读在“当前读”下…

【JavaEE网络】HTTP/HTTPS协议的工作原理与格式详解

目录 HTTP/HTTPSHTTP是什么理解“应用层协议”理解HTTP协议的工作过程HTTP协议格式 HTTP/HTTPS HTTP是什么 应用层,一方面是需要自定义协议,一方面也会用到一些现成的协议 HTTP及HTTPS是应用层重点协议 使用浏览器,打开网站,这…

自动化运维工具——Ansible

一、Ansible的概念: 1.Ansible的介绍: Ansible是一个基于Python开发的配置管理和应用部署工具,现在也在自动化管理领域大放异彩。它融合了众多老牌运维工具的优点,Pubbet和Saltstack能实现的功能,Ansible基本上都可以…

OpenHarmony 实战开发(南向)-Docker编译环境搭建

Docker环境介绍 OpenHarmony为开发者提供了两种Docker环境,以帮助开发者快速完成复杂的开发环境准备工作。两种Docker环境及适用场景如下: 独立Docker环境:适用于直接基于Ubuntu、Windows操作系统平台进行版本编译的场景。 基于HPM的Docker…

2024车载测试还有发展吗?

2024年已过接近1/4了,你是不是还在围观车载测试行业的发展? 现在入车载测试还来得及吗? 如何高效学习车载测试呢? 首先我们看一下车载测试行情发展,通过某大平台,我们后去数据如下: 这样的数据可以预估一下未来车载测试还是会持续发展. 随着科技的发展和汽车行业的不断创新,…

第08章 IP分类编址和无分类编址

8.1 本章目标 了解IP地址的用途和种类了解分类编址和无分类编址区别掌握IP地址、子网掩码、网关概念及使用掌握子网划分及超网划分方法掌握无分类编址的改变和使用 8.2 IP地址的用途和种类 分类编址:造成地址的浪费,以及地址不够用;无分类编…

labview技术交流-字符串数组连接成字符串

应用场景 我们可能需要将一维的字符串数组转换成一整条字符串,然后方便记录在数据库或表格中的一个单元格中。 代码展示 方案一 我们使用for循环完成这样的功能需求,见下图: 这种方案可能相对基础和普通,但是它更方便和易于扩展…

在Flask中使用Celery完成异步和定时任务(Flask、Celery、Redis)

编程目标 通过使用Flask和Celery,实现一个简单的Web应用程序,能够接收HTTP POST请求,并异步发送电子邮件。 说明 使用Flask创建一个简单的Web应用程序,包含一个HTTP POST路由,用于接收发送电子邮件的请求。使用Cele…

【Java SE】对象的比较

🥰🥰🥰来都来了,不妨点个关注叭! 👉博客主页:欢迎各位大佬!👈 本期内容满满干货,将会深入介绍对象与对象之间是如何进行比较的,我们知道基本数据类型是可以直…

使用 docker-compose 搭建个人博客 Halo

说明 我这里使用的是 Halo 作为博客的工具,毕竟是开源了,也是使用 Java 写的嘛,另外一点就是使用 docker 来安装(自动挡,不用自己考虑太多的环境因素),这样子搭建起来更快一点,我们…

【STM32 |新建一个工程】基于标准库(库函数)新建工程

目录 STM32开发方式 库函数文件夹 建工程步骤 库函数工程建立 建立工程总结 STM32开发方式 目前stm32的开发方式主要有基于寄存器的方式、基于标准库的方式(库函数的方式)、基于HAL库的方式基于库函数的方式是使用ST官方提供的封装好的函数&…

17、线上系统中垃圾回收参数的精准调校指南

17.1、前文回顾 在上一篇文章中,我们已经通过逐步的图解方式,详细解释了CMS垃圾回收的运行机制。简单来说,CMS垃圾回收器采用了四个阶段来进行垃圾回收,以尽量避免长时间的“Stop the World”现象。这四个阶段分别是:初始标记、并发标记、重新标记和并发清理。 在初始标…