2024-11-4

论文阅读 & 感想

这篇文章主要分析了将激活量化的难度迁移到权重量化上的可行性,以及提出了一个参数 表示迁移的难度,这个参数一般设置为 0.5。如果激活更加难以量化,则需要提高这个 值,反之,如果权重也比较难以量化,则需要减少这个值。
另一个印象深刻的点是,诸多模型的激活有这样的特点,其每个 Channel 内的数据方差很小,很稳定,不同 Channel 之间的数据方差很大,导致了极端值和偏差大。而量化工作的数学公式是依赖于极端值的,因此,对于非极端值的 Channel 来说,会导致大的误差。这也是迁移的一个原因。

同时也有一些问题(绿色划线),列举在下面。

问题

一些独立于文章之外的概念上的问题

  • 这里的计算机节点 node 是什么概念
    节点(Node) 节点是集群中的一个独立计算机或服务器。 在集群环境中,每个节点通常具有相似的配置和功能,并且可以相互通信和协作以完成共同的任务。 节点可以是·物理服务器·,也可以是·虚拟机·或·容器·等虚拟化技术实现的实例。

  • 张量在 0 处对称的作用和好处是什么
    在数据科学、机器学习等领域,输入张量的对称性可以被利用来优化计算资源和提高算法效率。例如,通过对称矩阵的子空间表示,可以显著加快算法的运行速度

  • 什么是外部维度
    在数学分析和机器学习领域中,“外部维度”可能指的是数据集中除了最大化模型性能可能直接使用的特征之外的变量。例如在预测销售数据的模型中,如果“销售额”是主要的目标,那么“广告支出”、“库存水平”、“节假日”等直接与销售活动有关的特征是模型的内部维度(直接用于预测的维度)。而“天气状况”、“竞争对手的活动”、“经济状况”等可能影响销售额的变量则被视为外部维度,因为它们不一定直接映射到模型的目标特征上。
    在这种情况下,外部维度可能需要通过其他方式整合(如特征工程)到模型中,使其成为预测销售额的有效组成部分。


2024-11-9

从知乎上找了一篇对应的解析文章 SmoothQuant的量化深入探究

2024-11-15

重新阅读文章,仍然存在的一些问题:
“Such quantizer uses the maximum absolute value to calculate ∆ so that it preserves the outliers in activation, which are found to be important for accuracy (Dettmers et al., 2022).” (Xiao 等, 2024, p. 2) 这种量化器使用最大绝对值来计算 Δ,以便保留激活中的异常值,这对准确性很重要(Dettmers et al., 2022)。 为什么使用在最大绝对值可以保证保留激活中的异常值

Pasted image 20241116184546.webp


“The total effective quantization bits would be largest when all the channels have the same maximum magnitude.” (Xiao 等, 2024, p. 4) 当所有通道具有相同的最大幅度时,总的有效量化比特将是最大的

Pasted image 20241116184752.webp

2024-11-16

阅读源码,论文结构

  • Smoothquant
    • Init. Py
    • Calibration. Py:获得输入和输出,进行模型参数的矫正
    • Fake_quant. Py:统一执行的量化函数(激活和权重),不过按标题是 QAT 操作才对
    • Opt. Py:似乎 是 OPT 架构的单独的代码
    • Ppl_eval:评价模型,计算其困惑度
    • Smoothquant_Smooth. Py:对模型做平滑处理,用于 ppl 的计算困惑度的过程中

2024-11-17

按通道 (channel) 量化 w 代码

@torch.no_grad()
def quantize_weight_per_channel_absmax(w, n_bits=8):
    # w: (out_features, in_features)
    # 计算每个通道的绝对值最大值,作为scale
    scales = w.abs().max(dim=-1, keepdim=True)[0]
    # 计算量化最大值
    q_max = 2 ** (n_bits - 1) - 1
    # 限制scale最小值,尺度范围
    # 进行归一化
    scales.clamp_(min=1e-5).div_(q_max)
    # 根据scale,对权重进行量化
    # mul_(scales) 是为了恢复尺度
    w.div_(scales).round_().mul_(scales)
    return w

对激活进行量化

@torch.no_grad()
def quantize_activation_per_tensor_absmax(t, n_bits=8):
    t_shape = t.shape
    # 将张量t变成一个二维张量
    t.view(-1, t_shape[-1])
    scales = t.abs().max()
    q_max = 2 ** (n_bits - 1) - 1
    scales.clamp_(min=1e-5).div_(q_max)
    t.div_(scales).round_().mul_(scales)
    return t

Fake_quant

这段代码执行的是模型的量化感知工作。具体来说,它通过收集模型在特定数据集上的激活值,计算这些激活值的最大绝对值,并使用这些值来调整模型的权重和偏置,从而实现模型的量化。

因为是调整模型的权重和偏置,因此是量化感知操作

OPT

将 Openai 的大模型 OPT 进行量化操作,是对特定结构的模型产生的量化方式。和其他模型的区别在于激活的量化尺度。本文件是对实现的量化后的 OPT 模型类的具体实现代码。

这里是原文描述

我们提供Llama, Mistral, Mixtral, Falcon, **OPT**, 和BLOOM模型的**激活通道尺度**。我们使用Pile验证集中的512个随机句子来获得这些尺度。你可以使用OPT演示(examples/smoothquant_opt_demo.ipynb)和Llama演示(examples/smoothquant_llama_demo.ipynb)来测试平滑和量化这些模型。
我们在 smoothquant/opt.py 中实现了量化后的 OPT 模型类,该类使用 INT8 线性层并结合量化尺度。

按内容总结

实现论文的部分是 smooth.py 函数,是论文迁移难度因子 的使用地方,其他的更多代码是对不同的模型(如 OPT)的具体量化复现。

一些代码问题

这里的语法是什么情况,主要是 max 和 dim 的操作,cat 是在拼接
weight_scales = torch.cat(
    [fc.weight.abs().max(dim=0, keepdim=True)[0] for fc in fcs], dim=0
)
weight_scales = weight_scales.max(dim=0)[0].clamp(min=1e-5)

# 更新 ln 和 fcs 的权重和偏置
    ln.weight.div_(scales)
    ln.bias.div_(scales)

    for fc in fcs:
        fc.weight.mul_(scales.view(1, -1))
@torch.no_grad()
def quantize_weight_per_channel_absmax(w, n_bits=8):
    # w: (out_features, in_features)
    # 计算每个通道的绝对值最大值,作为scale
    scales = w.abs().max(dim=-1, keepdim=True)[0]
    # 计算量化最大值
    q_max = 2 ** (n_bits - 1) - 1
    # 限制scale最小值,尺度范围
    # 进行归一化
    scales.clamp_(min=1e-5).div_(q_max)
    # 根据scale,对权重进行量化
    # 缩放,将权重变成一个整数值
    w.div_(scales).round_().mul_(scales)
    return w

smoothquant 量化的三个阶段

  • 校准阶段(offline),获得平滑参数
  • 平滑阶段(根据前一个阶段的参数,更新权重和激活的 diag 对角矩阵)
  • 推理阶段(执行在线推理

关于粒度