GPTQ-for-LLaMa 量化分析和优化

技术

点击下方卡片,关注「集智书童」公众号

点击加入👉「集智书童」交流群

本文作者:白牛

随着 LLM(Large Language Model)的兴起,GitHub 出现了很多优秀的预训权重和训练方法。尽管 MOSS/LLaMa/GPT-J 等实现细节有差异,它们都基于 transformer 结构,所以在模型量化环节,方法大同小异。

OpenMMLab 团队成员针对开源项目 GPTQ-for-LLaMa 做了误差分析,并在此基础上增加一些工程改进。改进后的量化支持 <输入int8,权重 int4,无 zero_point>,有机会进一步加速推理。

目前关键代码已合并到 GPTQ-for-LLaMa,本文将分享参与的整个过程,希望对大家有所帮助和启发。

1. 术语介绍

考虑到计算机视觉从业者更多、更熟悉 CNN 结构,因此先介绍 GPTQ-for-LLaMa 使用的底层技术,已熟悉的话可直接跳过。

1.1 Transformer

Transformer 来自 2017 年发表的《Attention is all you need》,最初用来解决 NLP 领域的问题。针对循环神经网络(RNN)和长短时记忆网络(LSTM)的计算效率不足问题,论文提出了自注意力机制(Attention)和位置编码方法。

其中 Attention 的计算过程如下图所示:

picture.image

假设有一个输入序列,我们先为每个词创建三个向量:Query、Key 和 Value。接下来:

  1. 将每个词的 Query 向量与其他所有词的 Key 向量进行点积,以计算得分;

  2. 对得分使用 softmax 函数进行归一化。归一化得分代表输入序列中各词的关注度;

  3. 将归一化得分与 Value 向量相乘,使关注度较高的词的 Value 向量保留更多信息;

  4. 将加权后的 Value 向量相加,得到输出向量

可以看出,这个计算过程充满大量 MatMul,方便后续量化加速。

1.2 LLaMa

LLaMa 是 facebook 公司近期开源的预训练模型,网络结构基于 GPT-J 调整而来,主要由 transformer 构成。

参照官方发布的论文,它的主要贡献在于:

  • 提供了不同参数量的预训模型,目前有 7B、13B、33B 和 65B 版本。每 Billion 参数以 float32 表达,需要 4GB 存储空间

  • 训练和数据说明,如关闭 bias、论文也有大篇幅介绍开源数据

GitHub 有很多基于 LLaMa 的优秀项目,例如 llama.cpp 推理、alpaca-lora 训练和 Chinese-LLaMA-Alpaca 中文微调。

1.3 GPTQ

GPTQ 是一种 one-shot PTQ 方法。不同于之前使用统计手段(如 kl-divergence)获得最小/最大值量化参数,GPTQ 先计算权重的 Hessian 矩阵,再结合此矩阵和局部量化结果,逐步迭代权重。

在物理意义上,Hessian 矩阵对角线数值,表示多元函数沿坐标轴方向的曲率。因此相对于统计量化方法,GPTQ 更具有说服力。

在解决实际的模型落地问题中,“insight” 和 “Engineering trick” 需要结合起来,相辅相成。

2. 误差分析和改进

GPTQ-for-LLaMa 默认使用 GPTQ+RPTQ 量化方法,只量化 transformer attention 中的 MatMul 算子。最终算子输入用 fp16、权重使用 int4。

无论是否开启 --sym 选项,GPTQ-for-LLaMa 都需要 zero-point,实际上是非对称的。

2.1 baseline

我们先运行起来,微调代码,画出 attention 和 mlp 在不同阶段的权重误差。这里是运行参数:


              
$ git clone https://github.com/qwopqwop200/GPTQ-for-LLaMa.git
              
$ cd GPTQ-for-LLaMa
              
$ python3 llama.py ${7B_MODEL_DIR} c4 --wbits 4 --true-sequential --act-order --groupsize 128 > baseline.txt
          

可以得到这样的误差分布,横轴是 layer_id、纵轴是量化前后的单层 Matmul 误差:

picture.image

这和之前 MMDeploy 部署 FQ-ViT 到 ncnn 的测试结论是接近的:

  • MLP 对量化更敏感

  • 无论是 attention 还是 MLP,layer 16 之后误差明显上升

  • attention 中计算输出的权重,即图中的 o_proj,对量化不敏感

2.2 --observe 选项

量化过程中,GPTQ-for-LLaMa 对不同的 MatMul,使用相同的 groupsize=128。但事实上不同层的敏感度不同,那么符合直觉的做法,就是不同层参数不同。

于是我们实现了—observe 功能,通过自动选择参数,削掉 layer16 之后的误差。并且为了避免手工挑选 layername,内部使用 topk,针对 k 个当前最差的层重新量化。

2.3 优化 zero_point

我们从 ncnn 推理优化经验中得知,对称量化公式简单,arm kernel 可以直接累加sdot等指令的结果,加速比“吊打”非对称量化。但它的副作用是精度可能受损,所以在消除 zero_point 之前,我们先看模型权重分布情况,是否有改进空间。

picture.image

画出权重直方图后,可以看到数值范围在 -1.1~1.2 之间,完全没有离心值。良好的数值分布,是对称量化的基础。

我们调整了 quantize 函数的实现,核心变动在 quantize() 函数,其余适配修改即可:


              
# def quantize(x, scale, zero, maxq):
              
#     if maxq < 0:
              
#         return (x > scale / 2).float() * scale + (x < zero / 2).float() * zero
              
#     q = torch.clamp(torch.round(x / scale) + zero, 0, maxq)
              
#     return scale * (q - zero)
              

              
def quantize(x, scale, minq, maxq):
              
    q = torch.clamp(torch.round(x / scale), minq, maxq)
              
    return scale * q
          

重新运行,可得到对称量化版误差分布:

picture.image

简单验证一下结果,确保还没有乱码。


              
 ⁇  this is llama and goat meat. This meat has been raised by a small family business and is certified to be organic. The meat is then delivered to a local butcher shop, who takes the me
              
at and makes small batches
          

此时 <qmin=-7, qmax=7>,误差曲线不变,但误差最大值已经从 6e5 上升到了 9e5。

于是使用前面实现的 --observe 选项,降低最坏误差。

picture.image

我们又测试了 <qmin=-8,qmax=7> 的情况,分布依然符合预期。

2.4 引入 SNR

GPTQ-for-LLaMa 的误差只计算 weight 量化损失, 但实际量化工作中, 我们最关心的是定点输出和原浮点结果的数值差距。所以我们引入 SNR (信噪比) 方法来观察量化期间的损失情况, 及时避免程序“胡言乱语”。

顺带美化输出、流式打印表格,这是新版运行效果。

picture.image

此外,我们还增加了量化表导出功能 --quant-directory,把所有量化参数转为 toml+numpy 结合的格式。希望对开源项目 llama.onnx 起到帮助。

3. 总结

以下是我们本次微小的贡献:

  • 我们把 GPTQ-for-LLaMa 非对称量化公式改成对称量化,消除其中的 zero_point,降低计算量;

  • 增加 --observe 选项,以更小的 groupsize 补偿对称量化精度;

  • 增加 SNR error,确保输入可以从 float16 变成 int8。

  • 最终 kernel 变成 matmul(int8, int4) 的形式,相对于 matmul(float16, int4, zero_point) 计算,相信会有加速作用。

截止本文发稿前,GPTQ-for-LLaMa 作者增加了 observe 分支,正在基于 --observe 策略调整 triton kernel,以验证 CUDA 上最终加速比,同时尝试更低比特。

在 LLM 完整落地和产品化过程, 还有更多问题要回答:

  • 如何高效评估模型精度, 确保最终结果不受影响 ?

  • 怎么支持显存带宽不足的 NPU/FPGA,找出 CUDA 以外的方案 ?

  • 我们目前贡献的只是一堆 "Engineering trick"。从学术角度看,有没有"insight"办法 ?

一切还在等待我们探索,欢迎大家一起加入~

picture.image

[picture.image

目标检测落地Trick | Det-PTQ让2D和3D目标检测器都可以进行量化加速落地](https://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247507259&idx=1&sn=3016cc0807e2c7d89916d80329a92c81&chksm=feb83d85c9cfb4935bd6499b0fb7c86595a737189a0430407adba3532ce196b03e55d2bf248f&scene=21#wechat_redirect)

[picture.image

小目标检测技巧 | 全局上下文自适应稀疏卷积CEASA | 助力微小目标检测涨点](https://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247507072&idx=1&sn=744a82a90da5dee1e8e9188cf9c18da1&chksm=feb83c3ec9cfb528d106d2e5b958b602e23ff8904beec4fc9766f4491c55b4378ed0239a322b&scene=21#wechat_redirect)

[picture.image

目标检测落地必备Trick | 结构化知识蒸馏让RetinaNet再涨4个点](https://mp.weixin.qq.com/s?__biz=MzU5OTA2Mjk5Mw==&mid=2247506947&idx=1&sn=31322015dba900ea4d728545471fbf96&chksm=feb83cbdc9cfb5ab54bc26e328b9bb1271367ca6e3bc246b8ee382cbbd290c88488aaf8a690c&scene=21#wechat_redirect)

扫码加入👉「集智书童」交流群

(备注: 方向+学校/公司+昵称 )

picture.image

picture.image

picture.image

picture.image

picture.image

picture.image

想要了解更多:

前沿AI视觉感知全栈知识👉「分类、检测、分割、关键点、车道线检测、3D视觉(分割、检测)、多模态、目标跟踪、NerF」

行业技术方案 👉「AI安防、AI医疗、AI自动驾驶」

AI模型部署落地实战 👉「CUDA、TensorRT、NCNN、OpenVINO、MNN、ONNXRuntime以及地平线框架」

欢迎扫描上方二维码,加入「 集智书童-知识星球 」,日常分享论文、学习笔记、问题解决方案、部署方案以及全栈式答疑,期待交流!

免责声明

凡本公众号注明“来源:XXX(非集智书童)”的作品,均转载自其它媒体,版权归原作者所有,如有侵权请联系我们删除,谢谢。

点击下方“ 阅读原文 ”,

了解更多AI学习路上的 「武功秘籍」

0
0
0
0
关于作者
关于作者

文章

0

获赞

0

收藏

0

相关资源
边缘计算在视频直播场景的应用与实践
视频直播作为当前视频行业的核心场景之一,对于高清化、实时性、交互性要求较高,需要强大算力保障用户流畅观看与互动体验。本次分享主要从视频直播场景需求切入,介绍基于边缘计算的视频直播场景方案及其架构、应用与实践。
相关产品
评论
未登录
看完啦,登录分享一下感受吧~
暂无评论