大模型量化技术实践指南:GPTQ、AWQ、BitsandBytes 和 Unsloth

在大模型(LLM)的时代,我们需要了解量化技术,以便在本地电脑上运行这些模型,因为它们的规模非常庞大。然而,实现量化的方法有很多,这让像我这样的初学者很容易感到困惑。本文介绍了我们必须掌握的主要量化技术,并附带了如何在 Google Colab 环境中实现它们的源码。

量化概述  

量化是一种将浮点数映射为低位整数的技术。它在减少 LLM 的模型大小和推理成本方面非常有效。例如,当我们将一个大约 4 × 7B = 28GB(float32)的 7B 模型量化为 float16 时,大小可以减少到 2 × 7B = 14GB。如果进一步将 float32 量化为 int8,模型大小甚至可以降至 1 × 7B = 7GB

下图展示了 LLM 中常见的数据类型数据类型的位表示。

图片

那么,我们究竟如何减少位宽呢?答案是通过 “舍入”(rounding)将数值从一种数据类型转换为另一种。为了更直观地理解量化的概念,我们将学习两种基本的舍入方法:零点量化(Zero-point quantization)绝对最大值量化(Absolute maximum quantization)

零点量化(Zero-point quantization)

零点量化通过线性映射,将原始数据的最小值和最大值对应到目标数据类型的最小值和最大值。例如,当我们将 FP16 数值转换为 Int8 时,就会用到这种量化方法。下图展示了这一过程。

图片

我们希望将数据缩放到 Int8 范围(在本例中为 0 ~ 255)。因此,我们需要计算数据在原始尺度中的相对值,并通过乘以 Int8 量化范围(255)来进行重新缩放。其计算公式如下所示:

图片

其中,n 是用于量化的位数(在本例中为 8)。需要注意的是,如果我们希望将数值缩放到 -127 ~ 127,则需要从上述结果中减去 127,然后对结果进行舍入。

这种方法比其他量化方法能够更精确地表示原始数据。但另一方面,它需要更复杂的计算,因此在实际应用中,我们需要在精度计算复杂度之间进行权衡。

绝对最大值量化(Absolute Maximum Quantization)

绝对最大值量化(Absolute Maximum Quantization)将原始数据中的最大绝对值映射到目标数据类型的有符号范围。仍然以 FP16 到 Int8 的转换为例。为了简化问题,我们使用受限的量化范围,即 -127 ~ 127(供参考,完整的量化范围是 -128 ~ 127)。下图展示了这种量化方法。

图片

我们首先计算数据中的最大绝对值,然后利用该值对原始数据进行重新缩放。其计算公式如下所示:

图片

这种方法在计算上比零点量化更简单。然而,它容易受到数据中离群值(outliers)的影响,因此在使用时需要仔细检查数据是否适合这种方法。

这些方法都属于 “舍入至最近值”(Round-to-Nearest, RTN) 量化技术。

然而,朴素量化(naive quantization) 存在精度下降的问题,因为减少位数的同时,也会丢失部分信息。因此,现代量化技术的目标是在减少位宽的同时尽可能降低精度损失。目前,主要有两种主流的现代量化技术:

1. 量化感知训练(Quantization Aware Training, QAT)

QAT 允许在量化模型的同时进行微调(fine-tuning),以恢复因量化导致的精度下降。相比于后训练量化(PTQ,见下文),QAT 可以更好地保持模型的准确性,但它通常需要额外的训练,并且计算成本较高,例如需要 A100 或 H100 等高性能计算资源。

2. 后训练量化(Post-Training Quantization, PTQ)

PTQ 允许对预训练模型进行量化,而无需额外训练。因此,它可以减少量化过程中对 GPU 显存(VRAM)的需求,是更具实用性的解决方案。近年来,研究人员在这一方向上投入了大量研究,开发了许多高效的 PTQ 方法。

在本博客中,我们将学习以下流行的量化技术:

  • GPTQ(Group-wise Precision Tuning Quantization)

  • AWQ(Activation-aware Weight Quantization)

  • Bitsandbytes(QLoRA)

其中,GPTQ 和 AWQ 属于 PTQ 方法,而 QLoRA 属于 QAT 方法。这些算法已经集成到 transformers 库中,因此用户可以高效地使用它们。在接下来的部分,我们将简要介绍这些算法的理论基础。

 GPTQ  

GPTQ(Group-wise Precision Tuning Quantization,分组精确调整量化)2022 年提出的早期成功的量化算法之一。当时,该技术首次成功地将 BLOOM 或 OPT-175B 等 175B 规模的大模型量化为 4-bit

GPTQ 采用逐行量化(per-row quantization),即独立地量化权重矩阵的每一行,以找到最优的量化权重,从而最小化量化误差

为了实现高精度量化,GPTQ 利用 Hessian 矩阵计算剩余权重的最优更新,从而减少量化带来的信息损失。需要注意的是,GPTQ 保留嵌入层(embedding layer)和输出层(output layer)为 FP16 以维持模型精度

下面的伪代码描述了 GPTQ 算法的工作原理:

图片

根据论文,使用单个 A100 GPU(80GB VRAM)大约需要四个小时就可以量化 175B 参数模型。OPT-175B 的量化结果如下表所示。

图片

困惑度(perplexity)衡量模型预测句子中下一个单词的能力。因此,困惑度值降低,这意味着模型对其预测更有信心。在上表中,与 16 位精度相比,通过 GPTQ 量化的模型将困惑度值的增加保持在尽可能小的水平。

AWQ  

AWQ(Activation-aware Weight Quantization,激活感知权重量化)最近是最流行的量化算法之一。该算法侧重于对 LLM 性能非常重要的显著权重。作者的研究表明,LLM 的权重比例很小(0.1~1%),对量化误差有显著影响。他们利用激活幅度来找到这一小部分权重,并应用每通道缩放来减轻显著权重的量化误差。此过程的说明如下图 (c) 所示。

图片

下表展示了 Llama-2 和 LLaMA 模型的 AWQ 结果。从中可以看出,AWQ 可以获得比舍入到最近 (RTN) 量化和 GPTQ 更好的困惑度。

图片

请注意,根据论文,对于某些模型(例如 Mistral 模型和指令调整模型),AWQ 有时不如 GPTQ。当我们量化 LLM 时,我们应该比较这些算法的结果并选择最佳算法。

BitsandBytes  

BitsandBytes 是一个将模型量化为 8 位或 4 位的量化库。由于其方便性和有效性,它是最常见的量化库。

BitsandBytes 的 8 位量化基于 LLM.int8() 论文。为了减轻量化误差,它将模型权重的敏感异常值保留在 FP16 中,将其他异常值保留在 INT8 中,然后分别进行矩阵乘法。最后,将它们相加以返回 FP16 格式。下图显示了此过程。

图片

该技术可应用于高达 170B 规模的模型,但运行 170B 模型仍需要 8 x 24GB VRAM,运行 66B 模型则需要 4 x 24GB VRAM。在消费级 GPU 上运行大型模型仍然不够。

因此,开发了 4 位量化来解决这个问题。Bitsandbytes 的 4 位量化通常与 QLoRA 一起使用,以微调量化后的 LLM。直观地说,QLoRA 以 4 位量化目标模型,使其冻结,然后使用 LoRA 对冻结的 4 位模型进行微调。以下是完全微调、LoRA 和 QLoRA 之间的比较。

图片

从技术上讲,QLoRA 主要利用了以下特性。

  • 4 位 NormalFloat 量化

    该技术利用了预训练的神经网络权重具有正态分布的事实,并引入了称为 4 位 NormalFloat 类型的新数据类型,这确保了每个量化箱中的预期值数量相等。

  • 分页优化器

    QLoRA 应用分页优化器来避免 GPU 内存突然激增。分页优化器使用 NVIDIA 统一内存功能自动在 CPU 和 GPU 之间切换页面到页面的传输(在这种情况下,你可以想象 GPU 页面类似于内存中的 CPU 页面)。

  • 双重量化

    当你将量化应用于模型权重时,你需要与模型权重具有相同数据类型的量化常数。由于 LLM 中有许多参数,量化常数也会给内存空间带来负担。为了最大限度地减少每个参数的内存占用,作者对量化常数进行了量化。

下表显示了参数大小与 GPU VRAM 消耗的关系。

图片

请注意,内存列显示模型的内存需求,因此它不包含微调部分。虽然这取决于数据集或超参数设置,但我们可以使用消费级 24GB VRAM 机器微调多达 13B 参数模型。

当零样本 LLM 精度不足以完成我们的目标任务时,我们应该使用 QLoRA。对于现实世界的 AI 项目,我们经常使用这种技术,因为基础模型通常不适用于特定的现场数据。

Unsloth  

虽然 Unsloth 不是量化方法,但我想介绍这个用于 LLM 的开源超高效微调库。Unsloth 是一个完全集成参数高效微调方法(如 LoRA 和 QLoRA)的库。它针对开源著名 LLM 优化了每个内核,并减少了高达约 80% 的内存使用率!例如,它支持DeepSeek-R1、Llama、Mistral、Phi、Qwen 和 Gemma 这些开源 LLM。

图片

Unsloth 与 HuggingFace 和 vllm 兼容,我们可以在它们之间互换格式。当模型受支持时,我们应该使用 Unsloth 来节省内存并提高性能。

就在最近(2024 年 12 月 4 日),Unsloth 发布了一种新的量化方法,称为 Unsloth — 动态 4 位量化(Dynamic 4-bit quantization)。该技术建立在 BitsandBytes 4 位量化之上,并确定是否动态量化某些参数。

图片

到目前为止,我们已经看到了流行的量化技术和库。总之,我们可以在以下情况下使用这些量化技术。

  • 想在零样本设置中使用 LLM → GPTQ 或 AWQ

  • 想使用带有自己数据的微调 LLM → QLoRA(BitsandBytes 或 Unsloth)

量化实战 

https://gist.github.com/tanukon/41fd470ae66697e744c01e23934fb270

https://medium.com/generative-ai/practical-guide-of-llm-quantization-gptq-awq-bitsandbytes-and-unsloth-bdeaa2c0bbf6

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

C51 Proteus仿真实验16:4X4矩阵键盘控制条形LED显示

说明 按下的按键值越大点亮的LED越多 Proteus仿真 注意: K1、K5、K9、K13左边引脚连接的是P1.0 K2、K6、K10、K14左边引脚连接的是P1.1 K3、K7、K11、K15左边引脚连接的是P1.2 K4、K8、K12、K16左边引脚连接的是P1.3 K1、K2、K3、K4右边引脚连接的是P1.4 K5、K6、…

Hive的架构

1. 概念 Hive 是建立在 Hadoop 上的数据仓库工具,旨在简化大规模数据集的查询与管理。它通过类 SQL 语言(HiveQL)将结构化数据映射为 Hadoop 的 MapReduce,适合离线批处理,尤其适用于数据仓库场景。 2. 数据模型 表&a…

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集

P8686 [蓝桥杯 2019 省 A] 修改数组--并查集 题目 解析代码 题目 解析 首先先让所有的f(i)i,即每个人最开始的祖先都是自己,然后就每一次都让轮到那个数的父亲1,第二次出现的时候就直接用父亲替换掉 并查集适用场景 …

GitHub上传项目

总结(有基础的话直接执行这几步,就不需要再往下看了): git init 修改git的config文件:添加:[user]:name你的github用户名 email你注册github的用户名 git branch -m master main git remote add origin 你的URL gi…

关于Windows输入法切换的一些总结

语言和键盘的关系(第一层是语言 语言下一层是键盘) 如下图:语言就是 中文 英文 阿拉伯文之类的 键盘就是 语言中文下的:XX输入法 语言的切换 和 键盘(输入法)的切换 (用windos空格 可以切换…

C# Unity 唐老狮 No.7 模拟面试题

本文章不作任何商业用途 仅作学习与交流 安利唐老狮与其他老师合作的网站,内有大量免费资源和优质付费资源,我入门就是看唐老师的课程 打好坚实的基础非常非常重要: 全部 - 游习堂 - 唐老狮创立的游戏开发在线学习平台 - Powered By EduSoho 如果你发现了文章内特殊的字体格式,…

搜广推校招面经三十九

小红书﹣图搜 一、两个整数的汉明距离 两个整数之间的汉明距离是指这两个数字对应二进制位相同位置不同的个数。换句话说,它就是将一个整数变成另一个整数所需要改变的二进制位的数量。例如,如果两个整数在它们的二进制表示中有三个位置上的…

conda list <package> 指令输出的build和channel含义

Build:表示当前安装包的 构建版本,即该包的编译、构建、发布的具体版本。通常包含一些额外的标识,帮助你区分同一包的不同版本。 Channel: 表示该包的 来源渠道,即该包是从哪个 Anaconda 仓库(频道&#…

Windows下配置Flutter移动开发环境以及AndroidStudio安装和模拟机配置

截止 2025/3/9 ,版本更新到了 3.29.1 ,但是为了防止出现一些奇怪的bug,我安装的还是老一点的,3.19,其他版本的安装同理。AndroidStudio用的是 2024/3/1 版本。 — 1 环境变量(Windows) PUB_H…

Linux系统编程--线程同步

目录 一、前言 二、线程饥饿 三、线程同步 四、条件变量 1、cond 2、条件变量的使用 五、条件变量与互斥锁 一、前言 上篇文章我们讲解了线程互斥的概念,为了防止多个线程同时访问一份临界资源而出问题,我们引入了线程互斥,线程互斥其实…

学习小程序开发--Day1

项目学习开篇 项目架构 项目进程 创建uni-app项目 通过HBuilderX创建 小结 page.json 和 tabBar 目录文件 pages.json的配置

在word下写公式

需求 word的可视化编辑公式是好的,但是很丑(见下图) 我希望公式是这样的(见下图) 解决方案 1.先转换为“线性”(即Latex格式) 2.得到下面这个玩意,把\mathrm去掉(功能是…

uniapp,自绘仪表盘组件(基础篇)

文章目录 一、为什么需要自绘仪表盘?二、准备知识三、实现基础仪表盘1. 组件模板结构2. 核心绘制逻辑3. 样式优化 四、使用示例五、核心实现原理六、扩展方向七、常见问题 一、为什么需要自绘仪表盘? 在物联网、数据监控等场景中,仪表盘是常…

导入 Excel 规则批量修改或删除 Excel 表格内容

我们前面介绍过按照规则批量修改 Excel 文档内容的操作,可以对大量的 Excel 文档按照一定的规则进行统一的修改,可以很好的解决我们批量修改 Excel 文档内容的需求。但是某些场景下,我们批量修改 Excel 文档内容的场景比较复杂,比…

Python贝壳网二手小区数据爬取(2025年3月更)

文章目录 一、代码整体架构解析二、各部分代码详解1. main()主函数解析2. 会话初始化(伪装浏览器身份)3. 动态参数生成(反爬虫核心机制)4. 列表页抓取(获取小区列表)5. 列表页解析(提取小区信息…

C++的内存管理

1. C/C内存分布 我们先来看下面的一段代码和相关问题 int globalVar 1; static int staticGlobalVar 1; void Test() {static int staticVar 1;int localVar 1;int num1[10] { 1, 2, 3, 4 };char char2[] "abcd";const char* pChar3 "abcd";int…

mac本地代理nginx,解决跨域问题

brew install nginxbrew info nginxnginx配置文件 /opt/homebrew/etc/nginx/nginx.conf 如何打开呢? open /opt/homebrew 启动nginx brew services start nginx改配置: server {listen 8080;server_name localhost;#charset koi8-r;#access_…

Clion快捷键、修改字体

文章目录 一、Clion快捷键1.撤销:crtl Z2.重做:crtl shift Z3.删除该行:crtl Y4.多行后退:选中多行 Tab5.多行缩进:选中多行 shift Tab 二、修改注释的斜体 一、Clion快捷键 1.撤销:crtl Z 2.重做…

【漫话机器学习系列】126.多项式回归(Polynomial Regression)

多项式回归(Polynomial Regression) 1. 什么是多项式回归? 多项式回归(Polynomial Regression)是一种用于建模非线性关系的回归分析技术。它是线性回归的一种扩展形式,允许模型通过增加自变量的高次项来更…

python网络爬虫开发实战之基本库使用

目录 第二章 基本库的使用 2.1 urllib的使用 1 发送请求 2 处理异常 3 解析链接 4 分析Robots协议 2.2 requests的使用 1 准备工作 2 实例引入 3 GET请求 4 POST请求 5 响应 6 高级用法 2.3 正则表达式 1 实例引入 2 match 3 search 4 findall 5 sub 6 com…