本文授权转载自学术平台 PaperWeekly,公众号ID:paperweekly。
这是一个推荐、解读、讨论和报道人工智能前沿论文成果的学术平台,致力于让国内外优秀科研工作得到更为广泛的传播和认可。
来源 | PaperWeekly
作者|林野
单位|东北大学自然语言处理实验室
在神经网络发展的过程中,提高模型的容量往往会对模型性能带来正向效果,在近几年的研究工作中,为了追求性能的提升,神经网络模型规模也确实呈现出逐渐增大的趋势。提高模型容量的方法主要包括增加模型的深度和拓展模型的宽度,ResNet-156L 和 BERT 等深层网络在图像、语音、语言模型领域被充分验证其有效性,使用 Transformer Big 这类宽模型也会带来较大的性能提升。
然而,伴随着模型的增大,模型的参数量和计算量也随之增加,当前的大规模神经网络模型参数量普遍达到千万级甚至上亿级别,使其很难部署在计算资源和存储资源受限的小设备上,也使得这些性能优越的模型在一些日常交流、涉及个人隐私等场景下无法发挥其实际价值。
随着科学研究与生产实践相结合需求的与日俱增,模型压缩和加速成为当前的热门研究方向之一。本文旨在对一些常见的模型压缩和模型加速方法进行简单介绍(每小节末尾都整理了一些相关工作,感兴趣的小伙伴欢迎查阅)。这些方法可以减少模型中存在的冗余,将复杂模型转化成更轻量的模型。本文涉及方法的主要类别有:知识蒸馏、高效网络结构设计、条件计算、模型剪枝、参数共享、量化。
目录
一、知识蒸馏(Knowledge Distillation)
二、高效网络结构设计(Efficient Neural Architecture Design)
三、条件计算(Conditional Computation)
四、模型剪枝(Pruning)
五、参数共享(Parameter Sharing)
六、量化(Quantization)
想要减少模型的参数量和计算量,最直接的方式就是训练一个更小的模型。然而,直接训练的小模型的性能往往达不到我们的预期,这时我们就需要一些辅助的手段来提升小模型的性能,知识蒸馏就是一种可选的解决方案。
在知识蒸馏的实现中,首先我们需要一个大模型,我们将其称之为“教师模型”,并将目标模型称之为“学生模型”。知识蒸馏利用了迁移学习的思想,将网络的预测结果(输出层或中间层隐藏状态)或者参数作为知识的一种载体,将教师网络的知识转移到学生网络。知识蒸馏的有效性需要基于两点假设:(1)“知识”在模型间是可迁移的;(2)教师模型所蕴含的“知识”比原始数据中的“知识”更容易被学生模型捕捉。
针对以上假设的第一点,预训练就是个很好的例子。通过使用尽可能多的训练数据,训练模型可以提取到更丰富的特征,这样的预训练模型可以应用在不同的下游任务中,并为这些下游任务带来非常显著的收益。针对以上假设的第二点,我们可以将真实标签数据中蕴含的知识称为“硬知识”,将教师模型学习到的知识称作“软知识”。虽然神经网络对我们来说是一个黑盒模型,但我们可以把一个神经网络看成是一个未知的函数,输入输出已知为我们的训练数据。
在教师模型的训练过程中,可以学习到 softmax 分布与真实标签匹配的关系。举个例子,当我们想翻译“猫”这个词的时候,真实标签只能告诉我们“猫”被翻译为“cat”。而大模型学习到的“软知识”却能包含更丰富的信息,我们可以知道“猫”大概率被翻译为“cat”,小概率能被翻译成“dog”,但只有极小的概率可能被翻译为“noodles”。通过教师模型对原始数据中“硬知识”的学习,将其转化为“软知识”教授给学生模型,可以降低任务的学习难度,从而帮助学生模型取得更好的性能。
知识蒸馏作为一种简单有效的模型压缩方法,近些年得到了非常广泛的研究,从模型的规模方面也不再受限于“教师模型的规模比学生模型大”,一些知识蒸馏方法的变体(例如自蒸馏和反向蒸馏)也逐渐衍生出来,这都为知识蒸馏的发展提供了更多的可能性。
[1] Distilling the Knowledge in a Neural Network
https://arxiv.org/pdf/1503.02531.pdf
知识蒸馏的经典之作,知识蒸馏的概念首次被提出。之所以取名知识“蒸馏”,就像做热力学的蒸馏实验,在这个过程中教师网络中的“精华”部分的知识通过“蒸馏”的手段提取出来,随后供学生网络去学习。
[2] FitNets: Hints for Thin Deep Nets
https://arxiv.org/pdf/1412.6550.pdf
本文的创新之处在于,知识蒸馏中的教师模型是一个“wide and shallower”的模型,而学生模型是一个“thin and deeper”的模型,这样的学生模型可以使用更少的参数量和计算量获得比教师模型更好的性能。
[3] Sequence-Level Knowledge Distillation
https://arxiv.org/pdf/1606.07947.pdf
本文提出的 sequence-level 知识蒸馏方法,不同于之前的 word-level,是在序列级别上学习知识,在机器翻译等任务上的实验结果优于 word-level 的知识蒸馏方法。
[4] Ensemble distillation for neural machine translation
https://arxiv.org/pdf/1702.01802.pdf
本文将 ensemble 模型作为教师模型,提升蒸馏知识的质量,得到性能更好的学生模型。
[5] Self-Knowledge Distillation in Natural Language Processing
https://arxiv.org/pdf/1908.01851.pdf
提出 self-knowledge distillation(自蒸馏),通过对自身知识进行提出的方式进行知识蒸馏。
[6] Selective Knowledge Distillation for Neural Machine Translation
https://arxiv.org/pdf/2105.12967.pdf
知识蒸馏中的“知识”并不是越多越好,某些知识的存在甚至可能会损害学生模型的整体性能。本文提出 batch-level 和 global-level 两种策略来进行知识蒸馏中样本的选取。
[7] Tinybert: Distilling BERT for natural language understanding https://arxiv.org/pdf/1909.10351.pdf
本文提出一种基于 Transformer 模型结构的知识蒸馏方法,用于预训练中 BERT 模型的压缩和加速。最终的实验表明,在达到与原始 BERT 模型相同性能的前提下,可以将模型大小减小为原来的 1/7.5, 模型推断的时间减少为原来的 1/9.4。
[8] Distilbert, a distilled version of BERT: smaller, faster, cheaper and lighter
https://arxiv.org/pdf/1910.01108.pdf
本文仍基于 BERT 模型进行实验,引入了三种损失函数:有监督的 Mask Language Model(MLM)损失、蒸馏 MLM 损失、词向量余弦损失,最终将模型参数量压缩至原来的 40%,推理速度提升 60%。
[9] MobileBERT: a Compact Task-Agnostic BERT for Resource-Limited Devices
https://arxiv.org/pdf/2004.02984.pdf
基于 BERT 模型,提出了一种 task-agnostic 的模型压缩方法。
高效网络结构设计方法主要分为手动设计和结构搜索两类。手动设计神经网络需要有具备专业背景知识的研究人员,针对任务的具体特性,进行神经网络结构的重新设计或者在现有网络上进行修改。比如当前在各个任务及领域都取得了显著效果的 Transformer 模型,相较于传统的 RNN 模型,Transformer 注意基于 self-attention 机制,它的计算复杂度和参数复杂度较小,并且得益于其中学习到的词与词之间的对齐关系,取得了比 RNN 更好的效果。
相比于手动设计一个神经网络,神经网络结构搜素看起来“智能”得多。其主要思想是“用神经网络设计神经网络”,通常采取强化学习方法或者进化算法来进行复杂网络的设计。结构搜索通过制定合理的搜索策略以及搜索算法,通过自动化的方式寻找特定目标下神经网络的最优结构。虽然大部分的工作由自动化的方式完成,但仍需要人为制定搜索方法和评估策略。并且由于结构搜索需要预设计一个较大的搜索空间,这个搜索过程所需的算力,时间成本和硬件成本都比较高。
手动设计神经网络需要较高的人力成本,结构搜索需要较高的时间成本和硬件成本,两种方法各有其优缺点,采取哪种方法更有优势还需要结合具体场景具体分析。
[10] Non-autoregressive neural machine translation
https://arxiv.org/pdf/1711.02281.pdf
想要了解非自回归神经机器翻译,首先需要知道什么是自回归。自回归,即机器翻译模型中解码器具有的一种特性,是指解码器在生成当前单词的时候需要依赖之前生成的单词,因此解码过程只能是非并行的。而非自回归可以并行生成模型的输出,显著提升了模型的推断效率。
[11] Deep encoder, shallow decoder: Reevaluating the speed-quality tradeoff in machine translation
https://arxiv.org/pdf/2006.10369.pdf
当前神经机器翻译模型并没有很好的权衡 encoder 和 decoder 的模型深度。本文中探索了不同深度 encoder 和 decoder 的神经机器翻译模型,实验表明一个深层 encoder 和浅层 decoder 的模型可以很好地达到速度和质量的平衡。
[12] Accelerating neural transformer via an average attention network
https://arxiv.org/pdf/1805.00631.pdf
本文将平均注意力网络应用在 Transformer 模型当中。文中提出,在 Transformer 模型的计算过程中,无需动态计算 self-attention 的权重,而是通过一个累加平均操作计算之前单词的信息,认为之前所有单词对当前单词的贡献都是相同的,从而提升这部分的计算效率。
[13] Sharing attention weights for fast transformer
https://arxiv.org/pdf/1906.11024.pdf
本文通过共享不同层间 attention 权重,简化了解码端 attention 的计算,从而提升 Transformer 模型的推断效率。
[14] An efficient transformer decoder with compressed sub-layers
https://arxiv.org/pdf/2101.00542.pdf
本文通过压缩 Transformer 的基本模块来简化体系结构,将 decoder 中的三个子层合并为一个,由此实现更高的并行度。
[15] Reducing Transformer Depth on Demand with Structured Dropout
https://arxiv.org/pdf/1909.11556.pdf
本文提出了 LayerDrop,在 Transformer 的训练过程中引入了一种结构化的 dropout 对大网络中的子网络进行采样,在训练过程结束后通过模型剪枝方法得到一个小网络。
[16] Efficient softmax approximation for gpus
https://arxiv.org/pdf/1609.04309.pdf
本文提出的 adaptive softmax 可以提升 softmax 函数的运算效率,softmax 中参数矩阵维度为词表大小,因此这种方法非常适用于词向量维度较大的神经网络。
[17] Reformer: The Efficient Transformer
https://arxiv.org/pdf/2001.04451.pdf
本文提出了两种方法来降低 Transformer 模型计算的时间复杂度。首先,将 dot-product attention 替换为 locality-sensitive hashing,将这部分的计算复杂度从 O(L2)更改为 O(Llog L),L 为序列长度。其次,使用可逆残差代替标准残差以进一步提升模型的计算效率。
[18] Neural Architecture Search with Reinforcement Learning
https://arxiv.org/pdf/1611.01578.pdf
将强化学习与深度学习相结合,神经网络结构搜索(Neural Architecture Search, NAS)的开山之作。
[19] SqueezeBERT: What can computer vision teach NLP about efficient neural networks?
https://arxiv.org/pdf/2006.11316.pdf
本文探索了如何用分组卷积结构来设计基于自注意力机制的神经网络。SqueezeBERT 用分组卷积代替了全连接层,并将这个分组卷积结构和自注意力机制相结合,提升了网络的计算效率。
[20] AdaBERT: Task-Adaptive BERT Compression with Differentiable Neural Architecture Search
https://arxiv.org/abs/2001.04246
本文通过可微神经架构搜索(Differentiable Neural Architecture Search, DNAS)对 BERT 模型进行了压缩,可以根据不同的任务自适应的生成不同结构的小模型。
[21] Progressive Neural Architecture Search
https://arxiv.org/pdf/1712.00559.pdf
本文提出了一种渐进式的神经网络结构搜索算法,实验证明这种方法比现有的基于强化学习和进化算法的结构搜索算法更有效。
神经网络模型的性能与训练样本的数量息息相关,针对大规模训练数据,如果没有与之匹配规模的模型,很容易造成欠拟合等训练难题。但如果模型规模增大,计算代价也随之提升。
条件计算可以针对于每个样本,激活网络的部分子网络进行计算,也就是说网络的哪部分被激活由输入的训练样本决定,使用这种方法可以在不增加计算代价的前提下显著增加模型容量。在 ICLR2017 的 MoE 中,作者提出了一个超大规模的神经网络,在模型容量上得到了超过 1000 倍的提升,同时并不会对计算效率造成过大负担。其中的稀疏门控混合专家层由数千个前馈神经网络组成,选择哪些专家层由门控机制控制。整个 MoE 网络由数十亿的参数组成,此类方法的提出使得研究学者们针对超大规模神经网络的探索过程又前进了一大步。
[22] Universal Transformers
https://arxiv.org/pdf/1807.03819.pdf
在 Transformer 模型基础上添加了一个模型 depth 维度上的循环,通过条件计算控制模型的计算次数,可以根据不同样本选取所需的模型层数。
[23] Outrageously Large Neural Networks: The Sparsely-Gated Mixture-of-Experts Layer
https://arxiv.org/pdf/1701.06538.pdf
本文提出的稀疏门控混合专家层由数千个前馈神经网络组成,虽然整个MoE由数十亿的参数组成,但仍保证了模型的计算效率。
[24] Depth-Adaptive Transformer
https://arxiv.org/pdf/1910.10073.pdf
本文提出一种深度自适应性的 Transformer 模型,在模型的推断过程中可以通过训练样本选取不同层数的模型进行计算,提升了网络推断效率。
[25] FastBERT: a Self-distilling BERT with Adaptive Inference Time
https://arxiv.org/pdf/2004.02178.pdf
[26] DeeBERT: Dynamic Early Exiting for Accelerating BERT Inference
https://arxiv.org/pdf/2004.12993.pdf
FastBERT 和 DeeBERT 思想比较相似,都是通过在 Transformer 层间插入额外的分类器来加速 BERT 的推断过程。
模型剪枝通过将一个稠密的神经网络变得稀疏来减小模型的参数量以及训练代价。
从剪枝的粒度来分类,模型剪枝方法分为非结构化剪枝和结构化剪枝。非结构化剪枝通常以神经元为单位进行剪枝,这种方法虽然可以显著减少模型参数量,但由于底层计算库通常只支持结构化的加速,因此往往这种非结构化的稀疏方法无法达到实际的加速效果。
结构化剪枝通常是指对模型 layer、block、channel 等级别的结构进行剪枝,虽然这种“粗粒度”的剪枝会对模型性能造成更大的影响,但却能获得真实的加速效果,在实际的生产应用中具备更大的优势且更有利于部署。在方法实现中,可以通过人为设定的一些检验标准判断模块的重要程度,或者对网络进行 L1、L2 正则化处理,后者可以在模型的训练过程中自动评价模块的贡献度大小,将不重要的部分“安全地”剪掉。
从剪枝的阶段来分,模型剪枝又可以分为训练前剪枝、训练中剪枝和训练后剪枝。典型的模型剪枝方法可以分为训练(Training)、剪枝(Pruning)和微调(Fine-tuning)三个阶段:
(1)训练一个“过参数化”的大网络,以此为基准进行剪枝。关于为什么需要训练一个大网络,可以参照 ICLR2019 best paper 的彩票假说。大网络中包含多个小的子网络,那么更大的网络就包含更多的“可能性”,有更大的概率可以表现的更好;
(2)区分网络中“重要”和“不重要”的部分,将不重要的部分剪掉;
(3)微调修剪后的模型,在实现过程中将大网络中重要的部分单独抽取出来,而后在训练数据集上进行一个快速的 finetune,这个步骤是为了尽可能地降低剪枝后模型的性能损失。
在以上三个步骤中,训练和剪枝两个步骤按先后顺序串行的方法属于训练后剪枝,如果并列进行就是训练中剪枝,将剪枝这一步骤设定在训练之前的方法属于训练前剪枝。当前最常用的剪枝方法是训练后剪枝,通过训练-迭代剪枝-微调的流程得到大网络中的一个较优子网路,虽然其训练代价较高,但方法简单,工程实践更友好,模型性能损失也较小。
[27] Deep compression: Compressing deep neural network with pruning, trained quantization and huffman coding
https://arxiv.org/pdf/1510.00149.pdf
ICLR 2016 的 best paper,通过剪枝、量化和哈夫曼编码来压缩深度神经网络。
[28] The Lottery Ticket Hypothesis: Finding Sparse, Trainable Neural Networks
https://arxiv.org/pdf/1803.03635.pdf
ICLR 2019 的 best paper,提出了“彩票假说”。
[29] Are Sixteen Heads Really Better than One?
https://arxiv.org/pdf/1905.10650.pdf
[30] Analyzing multi-head self-attention: Specialized heads do the heavy lifting, the rest can be pruned
https://arxiv.org/pdf/1905.09418.pdf
以上两篇论文均是针对 Transformer 中的多头注意力进行模型剪枝,实验发现将多头注意力中的部分头剪掉对模型性能影响不大。
[31] DynaBERT: Dynamic BERT with Adaptive Width and Depth
https://arxiv.org/pdf/2004.04037.pdf
基于 BERT 模型,对不同大小的子网络进行训练,在训练后的推断阶段直接对模型剪枝,从而达到模型压缩的目的。
[32] LadaBERT: Lightweight Adaptation of BERT through Hybrid Model Compression
https://arxiv.org/pdf/2004.04124.pdf
本文提出的 LadaBERT 通过一个混合模型压缩框架,以迭代方式将模型压缩至目标大小,其中涉及到知识蒸馏、模型剪枝、矩阵分解等模型压缩方法。
参数共享又叫权重共享,其主要作用就是通过共享网络中的权重来减少模型的参数量,从而减少模型所需存储空间。针对 Transformer 模型,有两种最常见的参数共享方法:1)Encoder 和 Decoder 间的 Embedding 层权重共享;2)隐藏层跨层参数共享(如 ALBERT);
在 Embedding 层权重共享的方法中,以机器翻译任务为例,虽然翻译中的源语言和目标语言属于不同类别,但对于两种语言中共同出现的词(如数字、标点、字符等等)可以共用一张大词表,为共享词表提供了可能。由于词表大小通常在上万级别,共享词表方法可以节省的模型参数量非常可观。在常用的 BPE 方法中,由于最小的单元是子词级别,类似于英语和德语这样的同系语的两种语言,其子词重合度非常高,因此进行 embedding 层共享还可以更好的进行单词表示,从而提升模型性能。但对于汉语和英语这样相差较大的语言对,使用共享词表的预期收益较小。
在 ALBERT 这类工作中使用了跨层参数共享的概念,以一个 12 层的 BERT-base 模型为例,在训练时可以只学习第一个层的参数,并在剩下的 11 个层中重用这套参数,而不是让 12 个层中的每一层都学习不同的参数。与 BERT-base 的 1.1 亿个参数相比,相同层数和 hidden size 的 ALBERT 模型只有 3100 万个参数。可以看出,这类方法可以显著减小模型参数量。
[33] ALBERT: A lite BERT for self-supervised learning of language representations
https://arxiv.org/pdf/1909.11942.pdf
采用跨层参数共享和矩阵分解的方式来加快 BERT 的训练速度并降低训练时内存的消耗。
[34] Recurrent Stacking of Layers in Neural Networks: An Application to Neural Machine Translation
https://arxiv.org/pdf/2106.10002.pdf
以循环叠加层的方式构造神经网络模型,在 Transformer 模型上的实验表明,将一层参数叠加 6 次可以达到和 6 层模型相近的性能。
[35] Speeding up Deep Model Training by Sharing Weights and Then Unsharing
https://arxiv.org/pdf/2110.03848.pdf
本文通过参数共享的方式提升了深层神经网络的训练效率。
量化方法,即将模型中常用的浮点 32 位数值映射到更少位数的数值,根据映射的间隔是否相等,量化方法可以分为均匀量化和非均匀量化。
量化方法现在最普遍的应用就是混合精度计算,通过浮点 32 位和 16 位间的数据类型转换与交替计算,使用此方法可以在特定硬件(如 TITAN V)上取得显著的加速效果并不损失模型性能。更极端的情况下,还可以使用 8 位整数或用更少比特位数表示的数值(如 2 值网络、3 值网络)进行计算,理论上可以获得更大的加速效果。但此类方法受硬件和底层计算库的限制较大,想要达到实际的加速效果还需要获得底层计算库方面的支持。
[36] Mixed precision training
https://arxiv.org/pdf/1710.03740.pdf
一种简单且实用的技术,通过 FP32 和 FP16 的混合精度计算,在保证模型性能的前提下可以显著提升模型的计算效率并降低对显存资源的消耗。
[37] Binarized Neural Networks: Training Neural Networks with Weights and Activations Constrained to +1 or -1
https://arxiv.org/pdf/1602.02830.pdf
[38] XNOR-Net: ImageNet Classification Using Binary Convolutional Neural Networks
https://arxiv.org/pdf/1603.05279.pdf
以上两篇论文在量化过程中仅使用了 1-bit,是比较极端的量化方法。
[39] Pieces of eight: 8-bit neural machine translation
https://arxiv.org/pdf/1804.05038.pdf
[40] Towards Fully 8-bit Integer Inference for the Transformer Model
https://arxiv.org/pdf/2009.08034.pdf
[41] Q8BERT: Quantized 8Bit BERT
https://arxiv.org/pdf/1910.06188.pdf
8bit 量化方法,在尽可能不损失模型性能的前提下,可以达到 4 倍的模型压缩效果。