大模型量化技术原理-SmoothQuant

news2024/11/20 18:23:22

近年来,随着Transformer、MOE架构的提出,使得深度学习模型轻松突破上万亿规模参数,从而导致模型变得越来越大,因此,我们需要一些大模型压缩技术来降低模型部署的成本,并提升模型的推理性能。
模型压缩主要分为如下几类:

  • 剪枝(Pruning)
  • 知识蒸馏(Knowledge Distillation)
  • 量化Quantization)

本系列将针对一些常见大模型量化方案(GPTQ、LLM.int8()、SmoothQuant、AWQ等)进行讲述。

  • 大模型量化概述
  • 量化感知训练:
    • 大模型量化感知训练技术原理:LLM-QAT
    • 大模型量化感知微调技术原理:QLoRA
  • 训练后量化:
    • 大模型量化技术原理:GPTQ、LLM.int8()
    • 大模型量化技术原理:SmoothQuant
    • 大模型量化技术原理:AWQ、AutoAWQ
    • 大模型量化技术原理:SpQR
    • 大模型量化技术原理:ZeroQuant系列
  • 大模型量化技术原理:总结

而本文主要针对大模型量化技术 SmoothQuant 进行讲述。

另外,我撰写的大模型相关的博客及配套代码均整理放置在Github:llm-action,有需要的朋友自取。

背景

LLM.int8() 发现当 LLMs 的模型参数量超过 6.7B 的时候,激活中会成片的出现大幅的离群点(outliers),朴素且高效的量化方法(W8A8、ZeroQuant等)会导致量化误差增大,精度下降。

image.png

但好在新出现的离群特征(Emergent Features)的分布是有规律的。通常,这些离群特征只分布在 Transformer 层的少数几个维度。针对这个问题,LLM.int8() 采用了混合精度分解计算的方式(离群点和其对应的权重使用 FP16 计算,其他量化成 INT8 后计算)。虽然能确保精度损失较小,但由于需要运行时进行异常值检测、scattering 和 gathering,导致它比 FP16 推理慢。

image.png

这些激活上的离群点会出现在几乎所有的 token 上但是局限于隐层维度上的固定的 channel 中;给定一个 token,不同 channels 间的方差会很大,但是对于不同的 token,相同 channel 内的方差很小。考虑到激活中的这些离群点通常是其他激活值的 100 倍,这使得激活量化变得困难。

以上是大模型量化困难的原因,总结下来就三点:

  • 激活比权重更难量化(之前的工作LLM.int8()表明,使用 INT8 甚至 INT4 量化 LLM 的权重不会降低准确性。)
  • 异常值让激活量化更困难(激活异常值比大多数激活值大约 100 倍。 如果我们使用 INT8 量化,大多数值将被清零。)
  • 异常值持续存在于固定的通道(channel)中(固定通道存在异常值,并且异常值通道值较大)

image.png

根据量化参数s(数据量化的间隔)和z(数据偏移的偏置)的共享范围,即量化粒度的不同,量化方法可以分为逐层量化(per-tensor)、逐通道(per-token & per-channel 或者 vector-wise quantization )量化和逐组量化(per-group、Group-wise)。

image.png

作者对比了 per-channel、per-token、per-tensor 激活量化方案。在这几种不同的激活量化方案中。per-tensor量化是最高效的实现方式。但只有逐通道量化(per-channel)保留了精度,因它与 INT8 GEMM 内核不兼容。即per-channel量化不能很好地映射到硬件加速的GEMM内核(硬件不能高效执行,从而增加了计算时间)。

image.png

为了进行 vector-wise quantization 以有效利用 INT8 GEMM 内核,我们只能使用外部维度(即Token维度 T 和 通道外维度 C 0 C_0 C0)的缩放因子,不能使用内部维度(即通道内维度 C i C_i Ci),因此,先前的工作对激活都采用了per-token量化,但并不能降低激活的难度。

于是 SmoothQuant 提出了一种数学上等价的逐通道缩放变换(per-channel scaling transformation),可显著平滑通道间的幅度,从而使模型易于量化,保持精度的同时,还能够保证推理提升推理速度。

image.png

SmoothQuant 技术原理

SmoothQuant (论文:SmoothQuant: Accurate and Efficient Post-Training Quantization for Large Language Models)是一种同时确保准确率且推理高效的训练后量化 (PTQ) 方法,可实现 8 比特权重、8 比特激活 (W8A8) 量化。由于权重很容易量化,而激活则较难量化,因此,SmoothQuant 引入平滑因子s来平滑激活异常值,通过数学上等效的变换将量化难度从激活转移到权重上。

image.png

常规的矩阵乘如下:

Y = X W Y=XW Y=XW

SmoothQuant 对激活进行 smooth,按通道除以 smoothing factor。为了保持线性层数学上的等价性,以相反的方式对权重进行对应调整。SmoothQuant 的矩阵乘如下:

Y = ( X d i a g ( s ) − 1 ) ⋅ ( d i a g ( s ) − 1 W ) = X ^ W ^ Y=(Xdiag(s)^{-1}) \cdot (diag(s)^{-1}W)=\hat{X} \hat{W} Y=(Xdiag(s)1)(diag(s)1W)=X^W^

$X \in R ^{T \times C_i} $ 在 channel 维度(列)上每个元素除以  s i s_i si ,$ W \in R ^{ C_i \times C_0} 则在每行上每个元素乘以  则在每行上每个元素乘以  则在每行上每个元素乘以 s_i$ 。这样 Y 在数学上是完全相等的,平滑因子s的计算公式下面会讲述。

将量化难度从激活迁移到权重

为了减小量化误差,可以为所有 channels 增加有效量化 bits。当所有 channels 都拥有相同的最大值时,有效量化 bits 将会最大。

一种做法是让  s j = m a x ( ∣ X j ∣ ) , j = 1 , 2 , . . . , C j s_j=max(|X_j|),j=1,2,...,C_j sj=max(Xj),j=1,2,...,Cj ,  C j C_j Cj 代表第 j 个 input channel。各 channel 通过除以  s j s_j sj 后,激活 channels 都将有相同的最大值,这时激活比较容易量化。但是这种做法会把激活的量化难度全部转向权重,导致一个比较大的精度损失。

另一种做法是让 s j = 1 / m a x ( ∣ W j ∣ ) s_j=1/max(|W_j|) sj=1/max(Wj),这样权重 channels 都将有相同的最大值,权重易量化,但激活量化误差会很大。

因此,我们需要在 weight 和 activation 中平衡量化难度,让彼此均容易被量化。本文作者通过加入一个超参 $ \alpha  (迁移强度),来控制从激活值迁移多少难度到权重值。一个合适的迁移强度值能够让权重和激活都易于量化。  (迁移强度),来控制从激活值迁移多少难度到权重值。一个合适的迁移强度值能够让权重和激活都易于量化。  (迁移强度),来控制从激活值迁移多少难度到权重值。一个合适的迁移强度值能够让权重和激活都易于量化。 \alpha  太大,权重难以量化,  太大,权重难以量化,  太大,权重难以量化, \alpha $ 太小激活难以量化。

image.png

通过实验发现,针对 OPT 和 BLOOM 模型, $ \alpha = 0.5  是一个很好的平衡点;针对 G L M − 130 B ,该模型有 30 =0.5 是一个很好的平衡点;针对 GLM-130B,该模型有 30%的异常值,激活值量化难度更大,可以选择  =0.5 是一个很好的平衡点;针对GLM130B,该模型有30 \alpha $=0.75 。

下图展示了当 α 为 0.5 时 SmoothQuant 的主要思想。

image.png

平滑因子 s 是在校准样本上获得的,整个转换是离线执行的。在运行时,激活是平滑的,无需缩放,具体步骤如下:

  1. 校准阶段(离线)

image.png

平滑因子s的计算公式如下:

image.png

  • $ \alpha $ 表示迁移强度,为一个超参数,控制将多少激活值的量化难度迁移到权重量化。
  • C C C 表示激活的输入通道数。
  1. 平滑阶段(离线)

image.png

X ^ , W ^ \hat{X}, \hat{W} X^,W^ 的计算公式如下:

  • $\hat{W}=diag(s) W $
  • X ^ = X d i a g ( s ) − 1 \hat{X}=X diag(s)^{-1} X^=Xdiag(s)1
  1. 推理阶段(在线,部署模型)

image.png

平滑之后的激活的计算公式如下:

Y = X ^ W ^ Y = \hat{X} \hat{W} Y=X^W^

将 SmoothQuant 应用于 Transformer 块

在Transformer 块中,将所有计算密集型算子(如:线性层、batched matmul (BMMs) )使用 INT8 运算,同时将其他轻量级算子(如:LayerNorm/Softmax)使用 FP16 运算 ,这样可以均衡精度和推理效率。

image.png

SmoothQuant 推理性能及精度

SmoothQuant可以无损地量化所有超过100B参数的开源LLM。

根据量化方式不同,作者提出三种策略 O1、O2、O3,其计算延迟依次降低。SmoothQuant的O1和O2级成功地保持了浮点精度,而O3级(per-tensor static)使平均精度下降了0.8%,可能是因为静态收集的统计数据与真实评估样本的激活统计数据之间的差异。

image.png

OPT-175B 使用 SmoothQuant 进行 int8 量化之后保持了与FP16相当的精度。

image.png

对于不同的LLM,SmoothQuant 相比其他量化方法(如:LLM.int8()、ZeroQuant等)具有更高的精度。

image.png

作者将SmoothQuant集成到PyTorch和FasterTransformer中,与 FP16 相比,获得高达1.56倍的推理加速,并将内存占用减半,并且模型越大,加速效果越明显。

image.png

SmoothQuant 应用

官方示例:

  • generate_act_scales.py:生成激活 scales
  • export_int8_model.py:平滑、量化以及导出INT8模型
  • smoothquant_opt_demo.ipynb:SmoothQuant 伪量化示例
  • smoothquant_opt_real_int8_demo.ipynb:SmoothQuant 真正的量化示例

使用 FP16 模拟 8 比特动态 per- tensor 权重和激活量化,即伪量化。

import torch
from transformers.models.opt.modeling_opt import OPTAttention, OPTDecoderLayer, OPTForCausalLM
from smoothquant.smooth import smooth_lm
from smoothquant.fake_quant import W8A8Linear

# 模型量化
def quantize_model(model, weight_quant='per_tensor', act_quant='per_tensor', quantize_bmm_input=True):
    for name, m in model.model.named_modules():
        if isinstance(m, OPTDecoderLayer):
            m.fc1 = W8A8Linear.from_float(m.fc1, weight_quant=weight_quant, act_quant=act_quant)
            m.fc2 = W8A8Linear.from_float(m.fc2, weight_quant=weight_quant, act_quant=act_quant)
        elif isinstance(m, OPTAttention):
            # Her we simulate quantizing BMM inputs by quantizing the output of q_proj, k_proj, v_proj
            m.q_proj = W8A8Linear.from_float(
                m.q_proj, weight_quant=weight_quant, act_quant=act_quant, quantize_output=quantize_bmm_input)
            m.k_proj = W8A8Linear.from_float(
                m.k_proj, weight_quant=weight_quant, act_quant=act_quant, quantize_output=quantize_bmm_input)
            m.v_proj = W8A8Linear.from_float(
                m.v_proj, weight_quant=weight_quant, act_quant=act_quant, quantize_output=quantize_bmm_input)
            m.out_proj = W8A8Linear.from_float(m.out_proj, weight_quant=weight_quant, act_quant=act_quant)
    return model



# 原生 W8A8 模型量化
model_fp16 = OPTForCausalLM.from_pretrained('facebook/opt-13b', torch_dtype=torch.float16, device_map='auto')
model_w8a8 = quantize_model(model_fp16)
print(model_w8a8)


# SmoothQuant  W8A8 模型量化(伪量化)
model = OPTForCausalLM.from_pretrained('facebook/opt-13b', torch_dtype=torch.float16, device_map='auto')
# 激活scales
act_scales = torch.load('../act_scales/opt-13b.pt')
smooth_lm(model, act_scales, 0.5)
model_smoothquant_w8a8 = quantize_model(model)
print(model_smoothquant_w8a8)

作者使用 CUTLASS INT8 GEMM 内核为 PyTorch 实现 SmoothQuant 真正的 INT8 推理,这些内核被包装为 torch-int 中的 PyTorch 模块。加载SmoothQuant量化后的模型示例如下:

from smoothquant.opt import Int8OPTForCausalLM

def print_model_size(model):
    # https://discuss.pytorch.org/t/finding-model-size/130275
    param_size = 0
    for param in model.parameters():
        param_size += param.nelement() * param.element_size()
    buffer_size = 0
    for buffer in model.buffers():
        buffer_size += buffer.nelement() * buffer.element_size()

    size_all_mb = (param_size + buffer_size) / 1024**2
    print('Model size: {:.3f}MB'.format(size_all_mb))

model_smoothquant = Int8OPTForCausalLM.from_pretrained(
    'mit-han-lab/opt-30b-smoothquant', torch_dtype=torch.float16, device_map='auto')
print_model_size(model_smoothquant)

SmoothQuant 生态

目前,SmoothQuant 已经集成到了英伟达的 TensorRT-LLM 推理加速工具以及英特尔的 Neural-Compressor 模型压缩工具包中。

总结

本文简要介绍了诞生的SmoothQuant背景和技术原理,作者提到激活值比权重更难量化,因为权重数据分布一般比较均匀,而激活异常值多且大让激活值量化变得更艰难,但是异常值只存在少数通道(Channel)内(单一 token 方差很大(异常值会存在于每一个 token 中),单一 channel 方差会小很多)。

因此,SmoothQuant 诞生。SmoothQuant 通过平滑激活层和权重后,再使用per-tensor或per-token量化,实现W8A8。根据量化方式不同,作者提出三种策略 O1、O2、O3,计算延迟依次降低。与其他量化方法相比,该方法可以保持较高的精度,同时,具有更低的延迟。

码字不易,如果觉得我的文章能够能够给您带来帮助,期待您的点赞收藏加关注~~

参考文档

  • https://github.com/mit-han-lab/smoothquant
  • https://arxiv.org/pdf/2211.10438.pdf
  • https://github.com/mit-han-lab/smoothquant/blob/main/assets/SmoothQuant.pdf
  • https://blog.csdn.net/LoveJSH/article/details/132114469
  • 大语言模型的模型量化(INT8/INT4):https://zhuanlan.zhihu.com/p/627436535
  • SmoothQuant Real-INT8 Inference for PyTorch:https://github.com/mit-han-lab/smoothquant/blob/main/examples/smoothquant_opt_real_int8_demo.ipynb
  • SmoothQuant on OPT-13B:https://github.com/mit-han-lab/smoothquant/blob/main/examples/smoothquant_opt_demo.ipynb

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

老卫带你学---leetcode刷题(130. 被围绕的区域)

130. 被围绕的区域 问题 给你一个 m x n 的矩阵 board ,由若干字符 ‘X’ 和 ‘O’ ,找到所有被 ‘X’ 围绕的区域,并将这些区域里所有的 ‘O’ 用 ‘X’ 填充。 示例 1: 输入:board [[“X”,“X”,“X”,“X”]…

本届挑战赛亚军方案:基于大模型和多AGENT协同的运维

“轻舟已过万重山团队”荣获本届挑战赛亚军,该团队来自华为集团IT-UniAI 产品和openEuler系统智能团队。 方案介绍 自ChatGPT问世以来,AI迎来了奇点iPhone时刻,这一年来大模型深入影响企业办公,金融,广告,…

springboot+maven项目导入本地jar包,以有打包错误问题

1 本地jar包放置路径为: 2添加Modules File->project settings–>Modules–>Dependencies–>–>, 3 添加 Libraies 至此 项目即可成功运行。 mvn 打包错误,需要 运行以下命令 mvn install:install-file -Dfile${project.basedir}/s…

源码安装nginx保姆级教程

一.目录存放 1./usr/lib/syste,md/system/:每个服务最主要的启动脚本设定 2. /run/systemd/system/:系统执行过程中所产生的服务脚本,这些脚本的优先序要比 /usr/lib/systemd/system/ 高! 3./etc/systemd/system/:管…

c语言day4 运算符 表达式 三大控制结构

1: 2: 输入一个年月日 计算这是这一年的第几天 17 int year,month,day;18 printf("请输入年份 月份 日期");19 scanf("%d %d %d",&year,&month,&day);20 int feb28;21 if(year%40&&year%1…

AI大模型-启航

文章目录 什么是大模型?(大体现在参数量巨大)大模型将会改变那些行业(大模型有哪些作用?)如何搞数据训练模型?LangChain带来的技术变革LangChain架构 什么是大模型?(大体…

【深度学习笔记】深度卷积神经网络——NiN

网络中的网络(NiN) LeNet、AlexNet和VGG都有一个共同的设计模式:通过一系列的卷积层与汇聚层来提取空间结构特征;然后通过全连接层对特征的表征进行处理。 AlexNet和VGG对LeNet的改进主要在于如何扩大和加深这两个模块。 或者&am…

Linux中如何在创建子线程的时候设置为分离属性

#include<stdio.h> #include<stdlib.h> #include<string.h> #include<sys/types.h> #include<unistd.h> #include <pthread.h> void *mythread(void *arg) {printf("id[%ld]\n",pthread_self()); } int main() { //定义pthread_…

【Java程序设计】【C00324】基于Springboot的高校疫情防控管理系统(有论文)

基于Springboot的高校疫情防控管理系统&#xff08;有论文&#xff09; 项目简介项目获取开发环境项目技术运行截图 项目简介 这是一个基于Springboot的高校疫情防控系统&#xff0c;本系统有管理员、学校管理员、学院管理员、教师以及学生五种角色&#xff1b; 管理员&#x…

camunda7流程引擎外部任务(External Task)如何使用

camunda7流程引擎支持两种执行服务任务的方式: 内部任务&#xff1a;同步调用与流程应用程序一起部署的代码外部任务&#xff1a;在列表中提供可由员工轮询的工作单元 第一个选项可以通过委托代码&#xff08;Delegation&#xff09; 或者脚本&#xff08;Script&#xff09;…

从零开始手写RPC框架(1)

学习java后端也有一段时间了&#xff0c;在网上寻一些教程和github上的开源库&#xff0c;学习从零开始手写一个RPC&#xff0c;学习各位大牛的代码适当修改&#xff0c;并贴上自己的一些见解和注释。 目录 RPC简介RPC和HttpClient的区别和共同点常见RPC框架 RPC框架设计常见序…

白宫敦促开发者弃用C和C++,转而使用“内存安全”的编程语言。

美国白宫国家网络总监办公室&#xff08;ONCD&#xff09;在一份新报告中呼吁开发者停止使用C或C等编程语言&#xff0c;转而使用“内存安全编程语言”&#xff0c;这是美国总统拜登网络安全战略的一部分&#xff0c;旨在保护网络空间的基础构建块。内存安全是指防止因内存访问…

6.WEB渗透测试-前置基础知识-AI应用

内容参考于&#xff1a; 易锦网校会员专享课 上一个内容&#xff1a;5.WEB渗透测试-前置基础知识-常用的dos命令-CSDN博客 1.AI在生活中扮演的角色越来越重要&#xff0c;AI现在可以用来帮我们办许多事情 目前比较好用的AI模型例如Chatgpt&#xff0c;Claude&#xff0c;必应…

推荐一款ssh工具 xshell替代品 electerm

下载地址 electerm&#xff1a; https://electerm.github.io/electerm/ windows版本 产品优势 复制粘贴&#xff0c;可以直接使用ctrlc/v 非常的方便 而且不想xshell 需要账号登陆&#xff0c;有更新弹窗&#xff0c;自身集成了sftp 界面设计更新&#xff0c;比MobaXterm的…

TCP的三次握手和四次挥手 | 查看网络状态

三次握手和四次挥手是在计算机网络中用于建立和终止TCP连接的协议。这两个过程是TCP协议的重要组成部分&#xff0c;确保数据的可靠传输。 三次握手指的是在客户端和服务器之间建立连接时的步骤。具体流程如下&#xff1a; 客户端向服务器发送一个连接请求报文段&#xff08;…

0201sherlock(福尔摩斯)-通过名称寻找媒体账号(地址)-github-开源项目学习

文章目录 一 项目简介二 项目安装和演示1 安装2 演示 三 源码分析1 项目结构2 主程序源代码分析 四 添加自定义网址结语 一 项目简介 二 项目安装和演示 1 安装 # clone the repo $ git clone https://github.com/sherlock-project/sherlock.git# change the working direct…

推荐几款优秀免费开源的导航网站

&#x1f9a9;van-nav 项目地址&#xff1a;van-nav项目介绍&#xff1a;一个轻量导航站&#xff0c;汇总你的所有服务。项目亮点&#xff1a;全平台支持&#xff0c;单文件部署&#xff0c;有配套浏览器插件。效果预览 &#x1f9a9;发现导航 项目地址&#xff1a;nav项目…

【开源项目】自动字幕生成和字幕翻译

文章目录 1. 安装ffmpeg2. 克隆项目3. 配置项目运行环境4. 填写配置文件5. 运行项目&#xff08;仅使用CPU&#xff09; 项目地址&#xff1a;Github - qinL-cdy/auto_ai_subtitle 项目原理&#xff1a;使用ffmpeg提取视频的音频&#xff0c;使用whisper将音频转写为字幕&#…

消息中间件之RocketMQ源码分析(二十三)

Broker的关机恢复机制 概述 Broker关机恢复是指恢复CommitLog、Consume Queue、Index File等数据文件。Broker关机分为正常调用命令关机和异常被迫进程终止关机两种情况。恢复过程的设计目标是使正常停止的进程实现零数据丢失&#xff0c;异常停止的进程实现最少量的数据丢失…

Python:练习:输出int值a占b的百分之几。例如:输入1和4,输出:25%。

案例&#xff1a; 输出int值a占b的百分之几。例如&#xff1a;输入1和4&#xff0c;输出&#xff1a;25%。 思考&#xff1a; 所有的一步步思考&#xff0c;最后综合起来。 首先&#xff0c;确定 输出&#xff0c;那么就用input&#xff0c;而且是int值&#xff0c;所以肯定…