Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)

本文主要是介绍Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

目录

1. 介绍

2. 基本概念

2.1 映射函数

2.2 量化参数

2.3 校准

2.4 对称与非对称量化

2.5 Per-Tensor and Per-Channel

2.6 PTQ

2.7 QAT

2.8 敏感性分析

2.6 退火学习率

3. 几点建议

4. 总结


1. 介绍

Practical Quantization in PyTorch | PyTorchQuantization is a cheap and easy way to make your DNN run faster and with lower memory requirements. PyTorch offers a few different approaches to quantize your model. In this blog post, we’ll lay a (quick) foundation of quantization in deep learning, and then take a look at how each technique looks like in practice. Finally we’ll end with recommendations from the literature for using quantization in your workflows.icon-default.png?t=N7T8https://pytorch.org/blog/quantization-in-practice/#fundamentals-of-quantization

本文介绍了量化的基本概念和实践应用:

  • 映射函数:将浮点值映射到整数空间,常用的映射函数是线性变换。
  • 量化参数:包括比例因子 ( S ) 和零点 ( Z ),用于确定输入数据的范围和偏移。
  • 校准:确定量化过程中所需的缩放因子和零点,常用方法包括 MaxMin、Percentile、Entropy、MSE 和 Diffs。
  • 对称与非对称量化:对称量化无需计算零点偏移,而非对称量化则需要。
  • Per-Tensor 和 Per-Channel:Per-Tensor 使用相同的量化参数,而 Per-Channel 则为每个通道使用不同的量化参数。
  • PTQ(训练后静态量化):适用于大型模型,通过模块融合和定期校准来减少量化误差。
  • QAT(量化感知训练):通过在训练过程中模拟量化误差来提高小型模型的量化精度。
  • 敏感性分析:确定哪些层对量化最敏感,并保留这些层的 FP32 精度。
  • 退火学习率:通过动态调整学习率来帮助模型更好地收敛。

2. 基本概念

2.1 映射函数

映射函数是一个将值从浮点映射到整数空间的函数。

常用的映射函数是线性变换,由下式给出:

Q_{r}=round(r/S+Z)

其中,r是输入,S和Z是量化参数。

可以将量化后的模型重新转换为浮点空间,反函数由下式给出:

\widetilde{r}=(Q_{r}-Z)\cdot S

\widetilde{r}\neq r,它们的差值构成了量化误差。

2.2 量化参数

映射函数有两个参数:比例因子 S 和零点 Z。

比例因子 S

S 就是输入范围与输出范围的比率:

S=(\beta_{U}-\alpha _{L})/(\beta_{q}-\alpha _{q})

\beta_{U}\alpha _{L}:输入的裁剪范围,即允许输入数据的边界值。这个范围定义了输入数据中哪些值会被保留并映射到量化后的输出空间,而超出这个范围的值会被剪切(截断)。

例如,对于一个输入范围 [-5.0, 10.0],所有小于-5.0的值会被剪切为-5.0,所有大于10.0的值会被剪切为10.0,以确保输入数据在量化过程中不会因为极端值而导致量化精度的显著下降

零点 Z

Z 为偏差量,以确保输入空间中的 0 完美映射到量化空间中的 0。

1). 偏移调整:零点作为偏移量,将缩放后的数据移动到量化范围内。例如,在无符号量化中,零点可以将负值移动到正值范围内。

2). 对称量化:在对称量化中,零点通常为零,因为浮点范围和量化范围是对称的。

3). 非对称量化:在非对称量化中,零点用于调整量化范围,使其适应非对称的浮点数据分布。

2.3 校准

校准(Calibration)的目的是为了确定量化过程中所需的缩放因子(scale factor)和零点(zero point),以便将浮点数转换为整数表示。

Vitis AI 中,3.2.3 局部量化设置 2.Method,提供了不同的校准方法:maxmin、percentile、entropy、mse、diffs。

  • MaxMin:使用校准数据的最大值和最小值来确定范围。这是最简单的方法,但容易受到异常值的影响。
  • Percentile:基于数据的分位数来确定范围,通常使用 99.9% 分位数来避免异常值的影响。
  • Entropy:使用信息熵(如 KL 散度)来最小化原始浮点值和量化值之间的信息损失。这种方法可以最大化保留信息,但计算复杂度较高。
  • MSE(Mean Squared Error):通过最小化原始值和量化值之间的均方误差来确定范围。这种方法在保留模型精度方面表现良好。
  • Diffs:基于数据的差异来确定范围,具体实现可能因工具而异。

量化观察器:

import torch
from torch.quantization.observer import MinMaxObserver, MovingAverageMinMaxObserver, HistogramObserver
C, L = 3, 4
# 使用正态分布生成两个随机张量作为输入数据
normal = torch.distributions.normal.Normal(0,1)
inputs = [normal.sample((C, L)), normal.sample((C, L))]
print(inputs)observers = [MinMaxObserver(), MovingAverageMinMaxObserver(), HistogramObserver()]
for obs in observers:for x in inputs: obs(x) print(obs.__class__.__name__, obs.calculate_qparams())

执行结果:

[tensor([[-0.1551,  0.4171,  0.0281,  0.8844],[-0.0766,  1.4027,  0.1924,  0.8369],[ 0.7786,  1.0915,  0.4398, -1.8102]]),tensor([[-1.2902, -1.3943, -1.6080,  0.1695],[-0.9307, -0.5508,  0.6164, -2.2461],[-1.1094, -0.3126,  0.5751,  0.6137]])]MinMaxObserver (tensor([0.0143]), tensor([157], dtype=torch.int32))
MovingAverageMinMaxObserver (tensor([0.0126]), tensor([144], dtype=torch.int32))
HistogramObserver (tensor([0.0125]), tensor([141], dtype=torch.int32))

上述结果中,含缩放因子(tensor([0.0143])),零点(tensor([157], dtype=torch.int32))。

通过这个例子,可以看到不同的观察器在处理相同的数据时,可能会生成不同的量化参数。这有助于理解不同观察器的行为和它们在量化过程中可能产生的影响。 

2.4 对称与非对称量化

对称量化方案

对称量化方案(Symmetric quantization schemes),将输入范围集中在 0 附近,无需计算零点偏移。范围计算如下:

-\alpha _{L}=\beta _{U}=max(\left | max(r) \right |,\left | min(r) \right |)

对于倾斜信号(如非负激活),这可能会导致量化分辨率不佳,因为剪切范围包含永远不会出现在输入中的值。

非对称量化方案

非对称量化方案(Asymmetric quantization schemes),将输入空间的最小和最大观测值分配给(\beta_{U},\alpha _{L})。范围计算如下:

\beta_{U}=max(r), \alpha _{L}=min(r)

对于量化非负激活非常有用(如果输入张量从不为负,则不需要输入范围包含负值)。

import torch
import matplotlib.pyplot as plt
import numpy as np# 从帕累托分布中生成的激活值样本
act = torch.distributions.pareto.Pareto(1, 10).sample((1, 1024))
# 从正态分布中生成的权重样本,并将其展平
weights = torch.distributions.normal.Normal(0, 0.12).sample((3, 64, 7, 7)).flatten()def get_range(x, scheme):if scheme == 'asymmetric':return x.min().item(), x.max().item()elif scheme == 'symmetric':beta = torch.max(x.max(), x.min().abs())return -beta.item(), beta.item()# 计算直方图、边界、以及直方图中非零部分的25%和95%分位数。
def prepare_data(data, scheme):boundaries = get_range(data, scheme)hist, bin_edges = np.histogram(data.numpy(), bins=100, density=True)ymin, ymax = np.quantile(hist[hist > 0], [0.25, 0.95])return hist, bin_edges, boundaries, ymin, ymax# 准备激活和权重数据
act_asymmetric = prepare_data(act, 'asymmetric')
act_symmetric  = prepare_data(act, 'symmetric')
weights_asymmetric = prepare_data(weights, 'asymmetric')
weights_symmetric  = prepare_data(weights, 'symmetric')# 绘图循环
fig, axs = plt.subplots(2, 2, figsize=(12, 8))
titles = ["Activation, Asymmetric-Quantized", "Activation, Symmetric-Quantized", "Weights, Asymmetric-Quantized", "Weights, Symmetric-Quantized"]
data_list = [act_asymmetric, act_symmetric, weights_asymmetric, weights_symmetric]for ax, data, title in zip(axs.flatten(), data_list, titles):hist, bin_edges, boundaries, ymin, ymax = dataax.hist(bin_edges[:-1], bin_edges, weights=hist)ax.vlines(x=boundaries, ls='--', colors='purple', ymin=ymin, ymax=ymax)ax.set_title(title)plt.tight_layout()
plt.show()

结果:

2.5 Per-Tensor and Per-Channel

Per-Tensor:整个张量使用相同的比例因子 S 和零点 Z。

Per-Channel:每个通道使用一组比例因子 S 和零点 Z。

Per-Channel 可以减少量化误差,因为异常值只会影响它所在的通道,而不是整个张量。 

2.6 PTQ

训练后静态量化(Post-Training Static Quantization)。

PTQ 方法非常适合大型模型(>10M),但在较小的模型中准确性会受到影响。

模块融合将多个顺序模块(例如: [Conv2d, BatchNorm, ReLU] )合并为一个。融合模块意味着编译器只需要运行一个内核而不是多个;这可以通过减少量化误差来加快速度并提高准确性。

静态量化模型可能需要定期重新校准,以保持对分布漂移的鲁棒性。

2.7 QAT

量化感知训练(Quantization-aware Training)。

QAT 通过将量化误差包含在训练损失中来解决小型模型(<10M)量化数值精度的损失。

所有权重和偏差都存储在 FP32 中,正常进行反向传播。然而,在前向传播中,量化是通过 FakeQuantize 模块进行内部模拟的。FakeQuantize 对数据进行量化并立即反量化,从而添加类似于量化推理期间可能遇到的量化噪声。因此,最终的损失考虑了任何预期的量化误差。

QAT 比 PTQ 具有更高的准确度。

在 QAT 中重新训练模型的计算成本可能是数百个 epoch。

import torch
from torch import nnbackend = "fbgemm"  # 在x86 CPU上运行。如果在ARM上运行,请使用 "qnnpack"。m = nn.Sequential(nn.Conv2d(2,64,8),nn.ReLU(),nn.Conv2d(64, 128, 8),nn.ReLU()
)"""融合模块"""
torch.quantization.fuse_modules(m, ['0','1'], inplace=True) # 融合第一对Conv-ReLU
torch.quantization.fuse_modules(m, ['2','3'], inplace=True) # 融合第二对Conv-ReLU"""插入量化和去量化节点"""
m = nn.Sequential(torch.quantization.QuantStub(), *m, torch.quantization.DeQuantStub())"""准备进行量化感知训练"""
m.train()
m.qconfig = torch.quantization.get_default_qconfig(backend)
torch.quantization.prepare_qat(m, inplace=True)"""训练循环"""
n_epochs = 10
opt = torch.optim.SGD(m.parameters(), lr=0.1)
loss_fn = lambda out, tgt: torch.pow(tgt-out, 2).mean()
for epoch in range(n_epochs):x = torch.rand(10,2,24,24)  # 生成随机数据out = m(x)  # 通过模型传递数据loss = loss_fn(out, torch.rand_like(out))  # 计算损失opt.zero_grad()  # 清除梯度loss.backward()  # 反向传播opt.step()  # 更新参数"""转换为量化模型"""
m.eval()  # 设置为评估模式
torch.quantization.convert(m, inplace=True)  # 转换模型为量化版本

2.8 敏感性分析

并非所有层对量化的响应都相同,有些层对精度下降比其他层更敏感。

确定最小化精度下降的最佳层组合非常耗时。

进行一次一个的敏感性分析,可以确定哪些层最敏感,并保留这些层的 FP32 精度。

实验中,仅跳过 2 个卷积层(MobileNet v1 中总共 28 个)即可获得接近 FP32 的精度。

2.6 退火学习率

退火学习率(Annealing learning rate)是一种动态调整学习率的方法,灵感来自于物理中的退火过程。退火是指通过逐渐降低温度来减少系统的能量,从而达到更稳定的状态。在机器学习中,退火学习率计划(Annealing learning rate schedule)通过逐渐降低学习率来帮助模型更好地收敛,避免陷入局部最优解。

常见的 Annealing learning rate schedule 方法包括:

  • 指数衰减(Exponential Decay):学习率按指数函数逐渐减小。
  • 余弦退火(Cosine Annealing):学习率按余弦函数周期性减小。
  • 分段衰减(Step Decay):学习率在特定的训练轮次后按固定比例减小。

3. 几点建议

需要注意的几点:

1. 大型模型(参数超过1000万)对量化误差更具鲁棒性。

2. 从预训练的32位量化模型比从头训练INT8模型提供更好的准确性。

3. 通过运行时剖析模型,可以帮助识别在推理中造成瓶颈的层。

4. 动态量化是一个简单的第一步,特别是如果你的模型有很多线性或递归层。

5. 对于权重量化,使用带有MinMax观察器的对称通道量化。对于激活量化,使用带有移动平均MinMax观察器的仿射张量量化。

6. 使用 SQNR 等指标来识别哪些层最容易受到量化误差的影响。关闭这些层的量化。

7. 使用量化感知训练(QAT)进行微调,训练时间约为原始训练计划的10%,并采用从初始训练学习率的1%开始的退火学习率计划。

4. 总结

量化技术在深度学习模型优化中具有重要作用,通过合理选择量化方法和参数,可以在不显著降低模型精度的情况下,显著提高模型的推理速度和内存效率。

本文记录的概念和建议能帮助在今后的实际应用中更好地利用量化技术。

这篇关于Vitis AI 进阶认知(Torch量化基础+映射+量化参数+对称性+每通道+PTQ+QAT+敏感性)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1095297

相关文章

Ilya-AI分享的他在OpenAI学习到的15个提示工程技巧

Ilya(不是本人,claude AI)在社交媒体上分享了他在OpenAI学习到的15个Prompt撰写技巧。 以下是详细的内容: 提示精确化:在编写提示时,力求表达清晰准确。清楚地阐述任务需求和概念定义至关重要。例:不用"分析文本",而用"判断这段话的情感倾向:积极、消极还是中性"。 快速迭代:善于快速连续调整提示。熟练的提示工程师能够灵活地进行多轮优化。例:从"总结文章"到"用

Spring Security 从入门到进阶系列教程

Spring Security 入门系列 《保护 Web 应用的安全》 《Spring-Security-入门(一):登录与退出》 《Spring-Security-入门(二):基于数据库验证》 《Spring-Security-入门(三):密码加密》 《Spring-Security-入门(四):自定义-Filter》 《Spring-Security-入门(五):在 Sprin

AI绘图怎么变现?想做点副业的小白必看!

在科技飞速发展的今天,AI绘图作为一种新兴技术,不仅改变了艺术创作的方式,也为创作者提供了多种变现途径。本文将详细探讨几种常见的AI绘图变现方式,帮助创作者更好地利用这一技术实现经济收益。 更多实操教程和AI绘画工具,可以扫描下方,免费获取 定制服务:个性化的创意商机 个性化定制 AI绘图技术能够根据用户需求生成个性化的头像、壁纸、插画等作品。例如,姓氏头像在电商平台上非常受欢迎,

Java进阶13讲__第12讲_1/2

多线程、线程池 1.  线程概念 1.1  什么是线程 1.2  线程的好处 2.   创建线程的三种方式 注意事项 2.1  继承Thread类 2.1.1 认识  2.1.2  编码实现  package cn.hdc.oop10.Thread;import org.slf4j.Logger;import org.slf4j.LoggerFactory

从去中心化到智能化:Web3如何与AI共同塑造数字生态

在数字时代的演进中,Web3和人工智能(AI)正成为塑造未来互联网的两大核心力量。Web3的去中心化理念与AI的智能化技术,正相互交织,共同推动数字生态的变革。本文将探讨Web3与AI的融合如何改变数字世界,并展望这一新兴组合如何重塑我们的在线体验。 Web3的去中心化愿景 Web3代表了互联网的第三代发展,它基于去中心化的区块链技术,旨在创建一个开放、透明且用户主导的数字生态。不同于传统

AI一键生成 PPT

AI一键生成 PPT 操作步骤 作为一名打工人,是不是经常需要制作各种PPT来分享我的生活和想法。但是,你们知道,有时候灵感来了,时间却不够用了!😩直到我发现了Kimi AI——一个能够自动生成PPT的神奇助手!🌟 什么是Kimi? 一款月之暗面科技有限公司开发的AI办公工具,帮助用户快速生成高质量的演示文稿。 无论你是职场人士、学生还是教师,Kimi都能够为你的办公文

Andrej Karpathy最新采访:认知核心模型10亿参数就够了,AI会打破教育不公的僵局

夕小瑶科技说 原创  作者 | 海野 AI圈子的红人,AI大神Andrej Karpathy,曾是OpenAI联合创始人之一,特斯拉AI总监。上一次的动态是官宣创办一家名为 Eureka Labs 的人工智能+教育公司 ,宣布将长期致力于AI原生教育。 近日,Andrej Karpathy接受了No Priors(投资博客)的采访,与硅谷知名投资人 Sara Guo 和 Elad G

C++11第三弹:lambda表达式 | 新的类功能 | 模板的可变参数

🌈个人主页: 南桥几晴秋 🌈C++专栏: 南桥谈C++ 🌈C语言专栏: C语言学习系列 🌈Linux学习专栏: 南桥谈Linux 🌈数据结构学习专栏: 数据结构杂谈 🌈数据库学习专栏: 南桥谈MySQL 🌈Qt学习专栏: 南桥谈Qt 🌈菜鸡代码练习: 练习随想记录 🌈git学习: 南桥谈Git 🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈🌈�

如何在页面调用utility bar并传递参数至lwc组件

1.在app的utility item中添加lwc组件: 2.调用utility bar api的方式有两种: 方法一,通过lwc调用: import {LightningElement,api ,wire } from 'lwc';import { publish, MessageContext } from 'lightning/messageService';import Ca

零基础学习Redis(10) -- zset类型命令使用

zset是有序集合,内部除了存储元素外,还会存储一个score,存储在zset中的元素会按照score的大小升序排列,不同元素的score可以重复,score相同的元素会按照元素的字典序排列。 1. zset常用命令 1.1 zadd  zadd key [NX | XX] [GT | LT]   [CH] [INCR] score member [score member ...]