ASR和TTS的大型深度学习模型通常需要大量计算资源和内存。虽然在开发过程中功能强大,但其尺寸和处理需求可能在资源受限的设备(如手机、嵌入式系统)上部署时,或在服务器上实现低延迟和高吞吐量时,令人却步。模型量化是应对这些问题的主要方法。它指的是降低表示模型参数(权重)以及可能在计算过程中表示其激活值的数值精度。基本理念是从高精度浮点表示(通常是32位浮点数,即float32)转换为低精度格式,最常见的是8位整数(int8)。这种转换带来以下几项好处:模型尺寸减小: 使用int8代替float32立即使存储模型权重所需的内存减少约4倍。这对于存储有限的设备端部署非常重要。推理速度加快: 许多现代CPU、GPU和专用加速器(如NPU或TPU)都针对整数运算有高度优化的指令。与float32操作相比,在int8中执行计算可显著提升速度。功耗降低: 整数运算通常消耗的电量少于浮点运算,这对于电池供电设备很重要。当然,这种精度降低并非没有代价。用更少的位数表示值本身会限制数值范围和精细度,可能引入近似误差,影响模型准确性。量化技术的目的是在最大限度提高效率的同时,尽量减少这种准确性下降。量化策略应用量化有两种主要策略:训练后量化(PTQ): 这通常是最简单的做法。您从一个预训练的float32模型开始,然后将其权重转换为低精度格式,如int8。激活值可以通过两种方式处理:动态量化: 权重离线量化,但在推理过程中激活值动态(实时)量化。这需要观察每次计算的激活值范围。应用相对简单,但由于动态范围计算和量化,可能在推理过程中引入计算开销。静态量化: 权重和激活值均离线量化。这需要一个校准步骤,即您在小型、有代表性的数据集(校准数据集)上运行float32模型,以收集每层激活值典型范围的统计信息。然后,这些范围用于确定推理过程中将float32激活值映射到int8所需的固定缩放因子。静态量化通常比动态量化带来更快的推理速度,因为缩放因子是预先计算的。PTQ具有吸引力,因为它无需重新训练模型,也无需访问原始训练流程和数据集(静态PTQ需要一个小型校准集)。然而,它有时可能导致准确性显著下降,特别是对于对精度变化敏感的模型。量化感知训练(QAT): 此方法将量化过程整合到模型训练循环中。在训练的前向传播过程中,模型图中会插入“伪”量化操作。这些操作模拟int8精度(舍入、截断)对权重和激活值的影响,同时确保在反向传播过程中梯度仍能流动(通常使用直通估计器,即STE等方法)。通过在训练期间模拟量化,模型学习调整其权重,以更好地适应精度降低。与PTQ相比,QAT通常能使量化模型获得更高的准确性,通常能与原始float32模型的性能非常接近。主要缺点是训练复杂度增加、需要修改训练代码以及需要访问原始训练数据。量化方案和参数进行量化时,有几个选项定义了如何将浮点值映射到整数:精度: 尽管int8最常见,但研究人员也在关注int4甚至二元/三元表示以实现进一步压缩,尽管通常会带来更大的准确性挑战。半精度浮点格式如float16或bfloat16提供了一种折衷方案,将尺寸减小2倍,同时对准确性的影响通常小于int8,但可能无法像int8那样有效利用整数专用的硬件加速。映射: 量化的核心是将浮点范围映射到整数范围。常见的仿射映射为: $$真实值 \approx (整数值 - 零点) \times 缩放因子$$ 其中scale是决定步长的正浮点数,zero_point是一个将浮点零点与整数值对齐的整数。对称性:非对称量化: 将观察到的浮点范围[min_val, max_val]映射到完整的整数范围(例如,uint8的[0, 255]或int8的[-128, 127])。这需要scale和zero_point两者。它通常适用于ReLU之后的激活值,它们是非负的。对称量化: 将中心化的范围[-abs_max, +abs_max]映射到整数范围(例如,int8的[-127, 127],会留下一个值未使用或特殊处理-128)。zero_point对于有符号整数通常固定为0。这常用于权重,因为它们往往集中在零附近。粒度:逐张量: 对整个权重张量或激活张量使用单个scale和zero_point。实现最简单。逐通道(或逐轴): 对张量的不同切片使用不同的scale和zero_point值,通常是沿着卷积层或线性层权重的输出通道维度。这提供更精细的控制,并且通常比逐张量量化获得显著更高的准确性,特别适用于通道间权重分布不同的层。量化在实践中的应用对于大型语音模型(如Transformer或深度RNN),量化通常应用于计算密集型层:卷积层、线性/全连接层和循环单元。需要谨慎,因为某些操作或层可能比其他层对量化更敏感。例如,归一化层或注意力分数计算有时可能保持更高的精度(例如,float16或float32)以保持准确性,从而形成混合精度模型。PyTorch(torch.quantization)、TensorFlow(通过TensorFlow Lite)和ONNX Runtime等框架提供工具和API来促进PTQ和QAT。这些工具通常自动化了部分过程,例如插入量化/反量化节点或执行校准。{ "data": [ { "type": "scatter", "mode": "markers+text", "x": [32, 16, 8, 4], "y": [100, 99.5, 97, 85], "marker": {"color": ["#1c7ed6", "#22b8cf", "#f59f00", "#fa5252"], "size": [10, 12, 15, 18]}, "text": ["FP32", "FP/BF16", "INT8", "INT4"], "textposition": "top center", "name": "准确性" }, { "type": "bar", "x": [32, 16, 8, 4], "y": [100, 50, 25, 12.5], "marker": {"color": ["#ced4da", "#adb5bd", "#868e96", "#495057"]}, "name": "相对尺寸", "yaxis": "y2" }, { "type": "bar", "x": [32, 16, 8, 4], "y": [1, 1.5, 3, 3.5], "marker": {"color": ["#d0bfff", "#9775fa", "#7048e8", "#ae3ec9"]}, "name": "相对加速", "yaxis": "y3" } ], "layout": { "title": "典型量化权衡(示意性)", "xaxis": {"title": "位精度", "type": "category", "categoryorder": "array", "categoryarray": [32, 16, 8, 4]}, "yaxis": {"title": "准确性 (%)", "range": [80, 101], "titlefont": {"color": "#1f77b4"}, "tickfont": {"color": "#1f77b4"}}, "yaxis2": {"title": "模型尺寸 (%)", "range": [0, 105], "overlaying": "y", "side": "right", "showgrid": false, "titlefont": {"color": "#868e96"}, "tickfont": {"color": "#868e96"}}, "yaxis3": {"title": "推理加速(相对)", "range": [0, 4], "overlaying": "y", "side": "right", "position": 0.85, "showgrid": false, "titlefont": {"color": "#7048e8"}, "tickfont": {"color": "#7048e8"}}, "legend": {"x": 0.1, "y": -0.2, "orientation": "h"}, "margin": {"l": 50, "r": 150, "t": 50, "b": 100} } }从32位浮点数(FP32)到更低精度时的示意性权衡。准确性通常在INT8时略有下降,但在INT4时下降可能更明显。模型尺寸与位宽成比例减小。推理速度的提升在很大程度上依赖于硬件对低精度运算的支持。在部署量化模型之前,严格的评估是必要的。不仅要衡量诸如ASR的词错率(WER)或TTS的平均意见得分(MOS)等标准指标,还要评估模型在测试数据中具有挑战性的子集上的性能(例如,嘈杂音频、特定口音、复杂句子),以确保鲁棒性没有受到过度影响。目的是为您的特定应用找到计算效率和可接受性能之间的最佳平衡点。