征程 6 | linear 高精度输出配置方式

1. 常规情况

基础知识:

  1. 考虑到模型输出位置量化损失对模型精度的影响较大,工具链推荐模型以 linear/conv 结尾,此时支持高精度 int32 输出(在 quantized.onnx 中,转定点为 int32,在前面 calib+qat 阶段都是 float32),这几乎可以做到无损。
  2. 征程 6 工具链量化 setter 模板支持自动设置高精度输出,前提是 conv 输出直接 接 dequant,不作为其他 node 的输入。

输出位置结构示意图:

全流程代码如下:

import torch
from horizon_plugin_pytorch import set_march, March
set_march(March.NASH_M)
from horizon_plugin_pytorch.quantization import prepare, set_fake_quantize, FakeQuantState
from horizon_plugin_pytorch.quantization import QuantStub
from horizon_plugin_pytorch.quantization.hbdk4 import export
from horizon_plugin_pytorch.quantization.qconfig_template import (calibration_8bit_weight_16bit_act_qconfig_setter,qat_8bit_weight_16bit_fixed_act_qconfig_setter, default_calibration_qconfig_setter,ModuleNameQconfigSetter
) from horizon_plugin_pytorch.quantization.qconfig import get_qconfig, MSEObserver, MinMaxObserver
from horizon_plugin_pytorch.dtype import qint8, qint16
from torch.quantization import DeQuantStub
import torch.nn as nn
from horizon_plugin_pytorch.quantization import hbdk4 as hb4
from hbdk4.compiler import convert, save, hbm_perf, visualize, compileimport torch
import torch.nn as nn# 定义网络结构
class SmallModel(nn.Module):def __init__(self):super(SmallModel, self).__init__()# 第一个 Linear: 输入 [2, 100, 256] -> 输出 [2, 100, 256]self.linear1 = nn.Linear(256, 256)self.layernorm = nn.LayerNorm(256)  # 对最后一维进行归一化self.relu = nn.ReLU()# 第二个 Linear: 输入 [2, 100, 256] -> 输出 [2, 100, 60]self.linear2 = nn.Linear(256, 60)# 第三个 Linear: 输入 [2, 100, 60] -> 输出 [2, 100, 60]self.linear3 = nn.Linear(60, 60)self.quant = QuantStub()self.dequant = DeQuantStub()def forward(self, x):x = self.quant(x)# 第一个 Linearx = self.linear1(x)  # [2, 100, 256]x = self.layernorm(x)  # [2, 100, 256]x = self.relu(x)  # [2, 100, 256]# 第二个 Lineary = self.linear2(x)  # [2, 100, 60]# 第三个 Linearz = self.linear3(y)z = self.dequant(z)return z# 设置随机种子,保证每次生成的数据相同
torch.manual_seed(42)
example_input = torch.randn(2, 100, 256)
model = SmallModel()# 前向传播
output_x = model(example_input)
print("输入形状:", example_input.shape)
print("输出形状:", output_x.shape)# A global march indicating the target hardware version must be setted before prepare qat.
set_march(March.NASH_M)calib_model = prepare(model.eval(), example_input, qconfig_setter=(default_calibration_qconfig_setter,),)calib_model.eval()
set_fake_quantize(calib_model, FakeQuantState.CALIBRATION)
calib_model(example_input)calib_model.eval()                            
set_fake_quantize(calib_model, FakeQuantState.VALIDATION)
calib_out_x = calib_model(example_input)
print("calib输出shape:", calib_out_x.shape)qat_bc = export(calib_model, example_input)
# save(qat_bc, "qat.bc")
# visualize(qat_bc, "qat.onnx")
hb_quantized_model = convert(qat_bc, March.NASH_M)
# save(hb_quantized_model,"quantized.bc")
visualize(hb_quantized_model, "quantized_single.onnx")

查看 quantized.onnx,可以看到最后一个 conv 确实是 int32 高精度输出

2. 输出又输入

如果 conv1,既作为模型输出,又作为后续 conv2 的输入,此时应该怎么办?

关键代码如下:

def forward(self, x):x = self.quant(x)# 第一个 Linearx = self.linear1(x)  # [2, 100, 256]x = self.layernorm(x)  # [2, 100, 256]x = self.relu(x)  # [2, 100, 256]# 第二个 Lineary = self.linear2(x)  # [2, 100, 60]y_out = self.dequant(y)y = self.quant_out(y_out)# y = self.quant_out(y)# 第三个 Linearz = self.linear3(y)z = self.dequant(z)return x, y_out

注意,y_out = self.dequant(y)是必须要添加的,否则无法实现该效果。

全流程代码如下:

import torch
from horizon_plugin_pytorch import set_march, March
set_march(March.NASH_M)
from horizon_plugin_pytorch.quantization import prepare, set_fake_quantize, FakeQuantState
from horizon_plugin_pytorch.quantization import QuantStub
from horizon_plugin_pytorch.quantization.hbdk4 import export
from horizon_plugin_pytorch.quantization.qconfig_template import (calibration_8bit_weight_16bit_act_qconfig_setter,qat_8bit_weight_16bit_fixed_act_qconfig_setter, default_calibration_qconfig_setter,ModuleNameQconfigSetter
) from horizon_plugin_pytorch.quantization.qconfig import get_qconfig, MSEObserver, MinMaxObserver
from horizon_plugin_pytorch.dtype import qint8, qint16
from torch.quantization import DeQuantStub
import torch.nn as nn
from horizon_plugin_pytorch.quantization import hbdk4 as hb4
from hbdk4.compiler import convert, save, hbm_perf, visualize, compileimport torch
import torch.nn as nn# 定义网络结构
class SmallModel(nn.Module):def __init__(self):super(SmallModel, self).__init__()# 第一个 Linear: 输入 [2, 100, 256] -> 输出 [2, 100, 256]self.linear1 = nn.Linear(256, 256)self.layernorm = nn.LayerNorm(256)  # 对最后一维进行归一化self.relu = nn.ReLU()# 第二个 Linear: 输入 [2, 100, 256] -> 输出 [2, 100, 60]self.linear2 = nn.Linear(256, 60)# 第三个 Linear: 输入 [2, 100, 60] -> 输出 [2, 100, 60]self.linear3 = nn.Linear(60, 60)self.quant = QuantStub()self.quant_out = QuantStub()self.dequant = DeQuantStub()def forward(self, x):x = self.quant(x)# 第一个 Linearx = self.linear1(x)  # [2, 100, 256]x = self.layernorm(x)  # [2, 100, 256]x = self.relu(x)  # [2, 100, 256]# 第二个 Lineary = self.linear2(x)  # [2, 100, 60]y_out = self.dequant(y)y = self.quant_out(y_out)# 第三个 Linearz = self.linear3(y)z = self.dequant(z)return z, y_out# 设置随机种子,保证每次生成的数据相同
torch.manual_seed(42)
example_input = torch.randn(2, 100, 256)
model = SmallModel()# 前向传播
output_x, output_y = model(example_input)
print("输入形状:", example_input.shape)
print("输出形状:", output_x.shape, output_y.shape)# A global march indicating the target hardware version must be setted before prepare qat.
set_march(March.NASH_M)calib_model = prepare(model.eval(), example_input, qconfig_setter=(default_calibration_qconfig_setter,),)calib_model.eval()
set_fake_quantize(calib_model, FakeQuantState.CALIBRATION)
calib_model(example_input)calib_model.eval()                            
set_fake_quantize(calib_model, FakeQuantState.VALIDATION)
calib_out_x, calib_out_y= calib_model(example_input)
print("calib输出shape:", calib_out_x.shape)qat_bc = export(calib_model, example_input)
# save(qat_bc, "qat.bc")
# visualize(qat_bc, "qat.onnx")
hb_quantized_model = convert(qat_bc, March.NASH_M)
# save(hb_quantized_model,"quantized.bc")
visualize(hb_quantized_model, "quantized.onnx")

查看 quantized.onnx,linear2 符合预期,确实是 int32 高精度输出。

新加入的 dequant 与 quant 会变成 rescale

以上是征程 6EM 的默认做法,如果使用的是征程 6PH,conv like 算子输出直接就是 float32,在既作为输出,又作为下一阶段输入时,会存在 vpu 的 quantize(float32->int16/int8),如下图所示

如果想依旧沿用征程 6EM 的方式,可进行如下配置:

qat_bc._integer_conv = True
hb_quantized_model = convert(qat_bc, "nash-h")

具体选择哪种方式可实测 latency(建议考虑将模型 conv like 算子 c++ 反量化的耗时减少也加进去对比)

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

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

相关文章

过碳酸钠供应商哪家好?过碳酸钠厂家权威推荐:厂家、批发商及制造商推荐

过碳酸钠作为一类重要的环保型氧系漂白剂,在洗涤工业、水处理工程、纺织印染等多个领域均有广泛应用。其产品质量的优劣以及供应体系的稳定性,对下游产业的可持续发展有着至关重要的影响。目前,过碳酸钠市场参与者众…

过碳酸钠外贸公司推荐,优质厂家及供应商怎么选?出口资质厂商名录

过碳酸钠作为兼具漂白、消毒功能的环保化工材料,在日化、纺织、造纸等领域应用广泛,全球市场需求持续攀升。国内涌现出一批具备出口资质的生产厂商与专业外贸贸易公司,它们凭借稳定的产品质量与成熟的国际渠道,成为…

成膜助剂哪家好?成膜助剂供货商推荐!精选厂家、制造商与优质批发商

在涂料、印染、建筑等众多行业的生产链条中,成膜助剂作为关键辅料,承担着改善产品成膜性能、提升使用效果的重要作用。而在成膜助剂的流通与供应体系中,不同角色有着明确的定位与价值:成膜助剂厂家是技术研发与生产…

深入解析:kafka 2.X+zookeeper3.X 权限控制

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …

P10470 前缀统计

点击查看代码 #include<bits/stdc++.h>using namespace std;const int N=1e6; int n,m,idx; int cnt[N]; char str[N]; int son[N][26];void insert(char* str) {int p=0;for(int i=0;str[i];i++){int u=str[i]-…

天气+快递查询前端页面制作步骤(HTML,css)

搭建页面基础结构(HTML) 创建 index.html 文件,构建页面骨架,包含标题、天气查询区域、快递查询区域、结果展示区域:天气+快递查询助手天气&快递综合查询<!-- 天气查询区域 --><div class="que…

U3D测试

U3D测试一、引擎核心特性测试(区别于普通应用) 常见bug多个场景切换后,资源未清理,叠加显示; 多个场景切换后,资源不显示,为空; 多个场景切换后,App卡死; 多个场景切换后,内存泄漏,App崩溃; 进入某个场景…

AI硬件与芯片之争:从夸克眼镜到GPU通用性

最近刷科技新闻,看到几个挺有意思的消息,感觉AI和硬件的结合越来越紧密了,尤其是阿里推出的夸克AI眼镜,直接喊出要拿下“下一代人机交互入口”。这让我想起之前学人机交互课的时候,老师总说未来设备会越来越无缝,…

数据库故障的诊断方法与分析思路:实战经验总结

数据库故障的诊断方法与分析思路:实战经验总结引言 数据库故障处理是Oracle DBA的核心技能,缺乏实战经验的理论派往往在故障面前束手无策。 一、数据库安装类故障:防患于未然的核心环节 数据库安装看似简单,实则暗…

P4391 无线传输

点击查看代码 //最小循环节问题,实质也就是模板的简单变形了 //可以反过来推导一串字符cabca平移多长才能再使得之后的头和原先的尾重合,答案就是平移最小循环节的长度,因为最小循环节就是最小不重复片段,越过了最…

查看虚拟环境里安装了哪些包

要查看 yolo 虚拟环境里安装了哪些包,你可以使用以下几种方法。✅ 方法 1:激活环境后查看(最常用) 首先激活 yolo 环境: conda activate yolo然后查看所有已安装的包: conda list你会看到类似: # packages in e…

2025/11/29

2025/11/29《代码大全2》读书笔记二:工程思维是管理复杂度的武器 书中将软件开发类比建筑工程,核心观点是“前期设计决定系统生命力”,工程思维的本质是从“代码实现”跃迁到“系统全局”的考量。NASA项目数据显示,…

代码背后的哲学

《程序员修炼之道》这本书最打动我的地方,是它揭示了编程背后的哲学思考。它让我明白:优秀的代码不仅仅是技术的产物,更是思想的结晶。 "石头汤与煮青蛙" 这个故事让我重新思考了变革的艺术。在工作中,我…

编程之外的修行

《程序员修炼之道》这本书最吸引我的地方,是它超越了纯粹的技术层面,深入探讨了程序员的思维方式和职业发展。它让我明白:成为一名优秀的程序员,技术只是基础,更重要的是编程之外的修行。 "你的知识资产&quo…

2025/11/28

2025/11/28《代码大全 2》将代码规范视为软件开发的底层逻辑,核心观点是 “好代码应自解释、低理解成本”。书中强调,代码的生命周期比编写时间长 10 倍,规范的价值在于为未来节省维护成本。 实操案例中,变量命名需…

《代码大全2》读书笔记4

《代码大全2》第10至12章围绕代码构建的核心环节展开,从变量命名、数据类型使用到控制结构设计,系统阐述了提升代码质量的关键原则,为编程实践提供了兼具理论性与实用性的指导。 第10章聚焦变量命名的艺术,强调命名…

2025/11/30

2025/11/30《代码大全2》读书笔记三:团队协作是知识传递的桥梁 《代码大全2》指出,软件开发不是孤军奋战,协作的核心是高效传递知识、降低协同成本。书中强调,代码评审不是“挑错”,而是团队共享经验、统一标准的…

カワキヲアメク

无论你想不想看游记,我都建议你去把标题的歌听一遍。 This 即使我真的不想在这里写下什么。 沟槽的组题人,愿你的妈妈和某个在 D2T2 放非多项式复杂度题目的出题人的妈妈现在在同一个地方。似乎,我并没有做好准备。…

《代码大全2》读书笔记5

《代码大全2》第13至15章聚焦代码实现的细节优化与逻辑打磨,从循环结构优化、条件判断设计到异常处理规范,深入拆解编程核心环节的实操技巧,为写出高效、稳健的代码提供了细致指引。 第13章围绕循环结构的设计与优化…

完整教程:第162期 自定义目标检测的 YOLO 微调完整指南

pre { white-space: pre !important; word-wrap: normal !important; overflow-x: auto !important; display: block !important; font-family: "Consolas", "Monaco", "Courier New", …