1. 首页 > 游戏攻略

一文深入解析量化训练工具的设计与精度调优 解析量是什么

作者:admin 更新时间:2025-02-06
摘要:导读:11月22日,新一期地平线「你好,开发者」工具链技术专场在智猩猩顺利完结直播。专场由地平线工具链量化训练工具研发负责人屈树谦主讲,主题为《地平线量化训练工具的设计与精度调优经验》。本文是此次专场主讲环节的实录整理。如果对直播回放以及Q&A有需求,可以点击阅,一文深入解析量化训练工具的设计与精度调优 解析量是什么

 

前言:

此刻朋友们对“魔兽127全图工具”都相对看重,小伙伴们都需要解析一些“魔兽127全图工具”的相关姿势。那么小编也在网上网罗了一些有关“魔兽127全图工具””的相关内容,希望看官们能喜爱,咱们一起来知道一下吧!

导读:

11月22日,新一期地平线「你好,开发者」工具链技术专场在智猩猩顺利完结直播。专场由地平线工具链量化训练工具研发负责人屈树谦主讲,主题为《地平线量化训练工具的设计和精度调优经验》。

本文是此次专场主讲环节的实录整理。如果对直播回放以及Q&A有需求,可以点击阅读原文前去观看。

屈树谦:我们好,我是来自地平线深度学习平台的屈树谦,主要是负责地平线工具链的量化训练工具。今日大家要讨论的Topic是《地平线量化训练工具的设计和精度调优经验。

我大概从这几个角度进行今日的讲解:

1.量化训练技术简介

2.量化训练工具面临的挑战

3.地平线量化工具设计与精度调优经验

4.未来寻觅方给

一、量化训练技术简介

我们都了解在芯片或端侧部署上,整数计算肯定比浮点计算快很多。这是壹个简单的图例。

从图上我们也可以看到,比如8b Add与相同的层,其实就是数量级的差别。因此从功耗与面积的角度来看,整数计算其实更适合做端侧的部署。大家征程系列芯片从征程2、征程3、征程5,到最近推出的征程6,都支持INT8或INT16计算。大家的工具就是将浮点模型部署到大家的芯片上。

二、量化训练工具面临的挑战

我们都了解,智驾场景存在一些量化问题:

1、智驾场景传感器类型、数量都相对多,比如摄像头、雷达等,不同类型数据数据范围差别相对大。以图像为例,我们都明白是INT(0-255);而雷达有很多位置信息,甚至有速度信息,所以它的数值范围很大,这些对于量化都是挑战相对大的。今日我也看到了一些同学的问题,比如输入层是不是可以用更低bit的量化?大家当前来看,其实还是相对难的。

2、智驾场景模型会越来越复杂,非常是今年我们都追求做端到端模型。端到端从感知到规控,它整个链路很长,每个阶段的模型结构都是有gap的,所以对量化的挑战也会越来越大。在大家企业内部之前也出现过做一些端到端模型的时候,做量化碰到很多问题。

3、FP32的数值精度是2⁻²³,对于INT8来说,只有1/256,就是256个数,所以量化不友好的现象是时有发生的。我们传统上认为都是正态的,所以量化起来很容易。但实际情况并不是这样的,非常是一些Transformer模型量化不太友好。

量化训练可以进一步减少量化部署精度相比浮点精度的损失。

我对量化训练的基础稍微说明一下,也许今日大部分同学都相对知道,但有些同学会不太熟。

量化就是从浮点到定点的映射过程,这里的公式是壹个均匀的、带着zero-point的非对称量化。大家地平线当前的量化训练工具主要还是对称的量化,zero-point是0。

反量化就是反给的过程。以 Conv为例,从输入到输出,比如INT、weight都是浮点。如果是量化的过程,它的真正计算过程就变成了前面两个是有量化节点的,在量化的时候两个输入是INT8,但是输出是INT32。所以Conv是INT8的计算。

牵扯到量化训练,量化训练是壹个先做量化,再做反量化的过程,就是壹个伪量化的节点。这个节点在量化训练的过程中是相对重要的,它等于于在浮点训练过程中,SIM在端侧部署时候的量化过程。它的输出也是FLOAT,这个FLOAT可以认为是壹个量化、反量化之后的FLOAT,跟前面的 FLOAT是不一样的。

三、地平线量化工具设计与精度调优经验

接下来重点讲讲地平线当前的量化攻略。

1、 基于已有浮点模型的finetune,无需用户从头训练。

当然这是有好有坏的,这也是在社区里我们最通用的一种方法:把浮点模型训好了,然后做一次finetune。它的成本相对低,目前的认知是在浮点的1/10以下。这里面也会有一些问题,在智驾场景的量产过程中,浮点模型本身就在不停地finetune,然后再加入QAT finetune,从理论上来讲也许会存在一些问题,但大家目前还没有碰到。

另外一条路,大家也可以让用户直接基于量化的模型,就是刚才Fake-quant模型,直接做从0最初的量化训练。这个在大家企业的一些场景模型上是有适用的,它对于模型迭代来说也许更稳一点。

2、梯度计算也是业界相对通用的一种方法,就是STE。

因为量化的函数是阶梯的,是求不了导的。所以业界一般常用的方法就是透传,直接把输出的量化梯度透传出去。专属的不同差异就是两头是饱与还是不饱与,这个地方要不容透传。

3、Scale升级的攻略,我们非常常用的是基于统计的方法,一般不会直接用Min、Max。比如Moving averavge的一种方法,就是根据一些当前batch与之前batch的数据做的统计。

还有一种就是基于学习的方法。Scale本身也是被学习的,它也可以用求梯度的方法来做,例如LSQ。这个地平线的攻略里面是支持的,还支持一种基于真正数据范围配置固定Scale的方法。 这种方法看着不那么高大上,但在很多场景都适用。对于一些数值范围,比如QAT或者Calibration塞的一些数据,不一定能够cover到一些真正的数值范围,所以这时候需要根据真正的数值范围算壹个固定Scale,按浮点的Min、Max,除以INT8,比如刚才说的-128~127的Min、Max。

4、还支持浮点模型FP16&FP32的部署。征程5上采用的是异构方法,一部分是在CPU上算的,征程6上会直接支持。

大家大概从去年下半年最初就在寻觅一种方法:Calibration+QAT。

最早的时候,大家并没有采用这样的方法来做QAT量化训练方案。我们也许觉得QAT已经很稳了,随便搞一下精度就会上来。其实不尽然,非常是Transformer模型出现之后,我们才发现了很多量化问题,也许有时候直接塞QAT都不一定能搞定。所以大家的攻略就是先做Calibration,再进行QAT。这种方法的好处是精度更有保证。在有些直接QAT上不去的case,通过这种方法是可以上去的。

大家当前大概1/3,甚至更多的参考模型是不需要QAT就可以直接满足精度的,按场景来看,大概是分类与分割模型偏多一点。当有了Calibration的Scale做基础来进行QAT时,可以让QAT的step数更少,可以最快地达到精度目标,所以整体的量化成本会更低。其实大家的用户都挺关注QAT或整套方案会带来多大的成本,除了人力的成本,还有机器的成本,比如我花了一周训了壹个模型,如果QAT再花个几天,也许就接受不了了。所以这种攻略可以最快达到最终部署的精度,也许之前需要花一天,今年半天就搞定。

鉴于刚才的好处,大家的Calibration攻略也在逐步完善,在业界相对常用的攻略,包括kl、percentile、MSE、max、AdaRound等,大家都有支持。

最近也支持了自动搜索的混合校准攻略,为每一层挑选最优的校准攻略。这其实也是来自于客户的需求,不想每个阶段攻略都配一遍,这对人力消耗的成本会相对大;另壹个是用户在运用的时候,不太懂应该选哪个,因为在某些case下面很难了解哪个是最好的。所以大家有壹个自动搜索攻略,当然自动搜索会相对耗机器资源,等于于用资源换一些人力,对我们会更友好一点。

下面列出来的是主要是一些CNN模型的精度。

从这里面看到的比如分类、分割的模型,大家直接做Calibration就可以达到了。下面这几个模型是需要做QAT的。

再说一下大家针对Transformer的量化做的一些工作。

在早期大家寻觅Transformer的时候,让大家很头疼。此前大家接触的CNN模型会相对多,因为当时的Transformer方案在面给真正场景的时候还不是很成熟。但目前来看,我们在做一些比如智驾场景的融合,会用一些Transformer Attention的方案,之前其实不会,所以一最初我们也试试了很多东西。目前大家针对这些复杂算子Layernorm、Softmax以及Gridsample,但Gridsample不能完全算是这里面的,提供了更友好的精度方案。用户可以不用感知,可以直接调社区的算子。大家会把它转到QAT的model上,内部主要是混合INT8与INT16,采用INT16化解一些精度问题,可以降低Transformer模型的量化难度。这些算子里面,比如GELU这种算子,大家没有感知到它有太大问题。

针对一些常用Attention结构,比如MultiScaleDeformableAttention,提供了精度与部署性能优化。

我大概选了几个模型,我们能看到一些分类、检测、车道线等各个场景的模型。

这里面的模型最终达到的精度看起来都是ok的。目前从QAT的角度来看,大家是可以化解Transformer的量化问题,不止INT8,还引入了INT16。

刚才我聊的是偏量化训练攻略这部分的工作会多一点,而PyTorch量化训练接口怎么挑选?也是壹个很头疼的问题。如果想要试试PyTorch量化的工具要如何做?

社区也许也提供了一些方案,但社区的接口永远都是Prototype、Beta,在很早期的阶段持续了很久。

量化训练问题本质上就是在壹个合适的位置上插入伪量化节点,也许还有一些节点替换的问题,但决定因素的问题是插入伪量化节点。同时,还要保持训练特性不变,不能插完之后,得到了Graph,但量化的运用体验与原来的浮点运用体验不一样。这张图是2022年底到2023年初的状态,PyTorch的 capture graph方法有很多。

Capture方法其实是很多的,从Script到Trace,再到FX、Dynamo,不同的level上有不同的方案。大家更关注要得到一张全图,如果没有全图,有时候做点事情还是挺难的。所以大家应该挑选啥子样的方案?一种是没有Graph的Eager,还是用FX或Dynamo。对于Dynamo,前一段刚发布了 2.1 Dynamo export 方案。这些方案其实都不是很最佳,每个方案都有自己的局限性,都会向算法同学带来一些没那么友好的东西,不能一把全都搞定。跟大家早期用的比如MXNet或者TF一样,直接把Graph的node都定义好了。这时候框架层面做起来就很简单,但也许对用户不太友好。

地平线今年支持的是Eager Mode与FX Mode两种接口。

Eager Mode的方法整体的方案上是没有图的。用户在真实做QAT的时候,他的体验是与做浮点一样的,可以做单步的调试。但因为没有图,所以在做算子融合的时候需要用户手动操作,比如融合Conv、BN与relu算子之后,量化更友好,部署也会更友好。这些是偏图优化的操作。

在Eager Mode上,部分算子需要用户手动替换,比如像加、减、乘、除。在浮点的阶段,大家可以随便调用这些算子,但是在QAT上是不一样的,如果想要add做量化,那就意味着要插一些量化节点进去。量化节点就是刚才大家看到的 Scale、zero-point等 。它们是有状态的参数,要变成壹个torch model。将function替换为module需要用户手动替换,所以这个方案也许会存在的问题是它的友好性。但是在配好了qconfig、prepare之后,还是ok的。

FX Mode就没有这样的困扰,因为它有Graph,大家可以在 Graph上做一些大家想做的工作。但FX Mode有一些语法上的问题。这种方法采用proxy,而非真正Tensor,有非真正Tensor来做symbolic trace,symbolic trace会与Python语法会存在一些兼容性的问题。

整体来说,这是大家目前的方案。大家也在卖力帮助用户提高量化接口的应用性。我相信后面会在这两个版本的基础上,再做一些更友好的版本出来。比如基于torch 2.1的export方法trace fx-graph。

接下来是硬件相关的优化。

1、目前的QAT还是和硬件绑定的,没有完全和硬件脱离。所以,它的目标更加贴近硬件的SIM量化,可以进一步降低从QAT模型到Quantized模型的损失。直观地说,如果你用的都是浮点,那么也许没有这个问题。但如果是在部署的时候也是定点的,还是会存在这些问题。毕竟前面是SIM的量化,后面是真正的定点,所以会有一些精度的gap。我们在刚才的那个表格里面也能看到,大家当前的Quantized比较QAT是掉的相对少的。

2、在保证精度的同时,尽量做到多算子进行量化,充分发挥硬件潜力。在之前的PPT我也说了,INT计算还是相对省的。

3、提供一些特殊场景的硬件高效算子。这些算子是在大家的硬件上做了专门地优化,把它们嵌入到工具里面,用户可以按需运用。

4、支持Quantized模型的仿真。基于GPU 与 X86的高性能仿真,大家现在也优化了几个版本。

5、支持稀疏化训练(2:4)。(2:4)稀疏也许是当前一种公认的对硬件相对友好的稀疏化攻略,硬件实现成本相对低,精度损失也是ok的。我没有在这里列精度的情况。稀疏化训练+量化整个全步骤下来,比较之前精度损失大概2%之内,这是大家当前的一些实验结论。它本身的步骤是基于浮点模型的, 浮点模型进来之后,先做稀疏化,再做量化,再到部署。

前面讲到了大家在很多场景的复杂模型量化训练的经验。大家内部也碰到了一些复杂模型,而且我认为这个模型会越来越复杂,至少目前没有看到这个事情变得越来简单,大家也有了一些经验:

第壹个是某些场景模型的输入,如雷达数据。对于雷达来说,不同channel的数字范围差别会相对大,不太适合量化。所以,大家提议用户做归一化之后,再到网络里面做量化,这时候的量化损失会相对小。

第二个是视觉Transformer,比如BEVFormer,有很多参考点、位置相关的信息;再比如Gridsample的Grid计算也是与位置相关的,不管是比较位置还是其他的,因为量化敏感度相对高,都需要更高的精度。大家提议是INT16量化,或根据真正的数据范围配置固定Scale。

这个我刚才也提到了,就是为啥子要做这样的工作?其实有时候为了做量化,这些工作是必备的。大家看到实验场景下QAT都是跑多遍数据集,但我们在真正场景上做模型的时候,都是按step算的,而不是epoch。step的话,我能在 QAT跑1000个step,所以能跑多少数据是不确定的。我们按照某个要求来选数据的时候,不一定能很合理地挑选,所以这个case很也许是需要配置固定Scale的,后面大家也可以让用户配置一些浮点进来。

第三个是检测等模型,比如网络输出与算法指标关系相对大,大家提议配置高精度输出,或者默认都配置高精度。

这是从其他地方找回来的一张图。

比如我们学到的Scale、Min、Max,都是基于统计的方法来得到的,有一些异常点会被去掉。但有些点是挺重要的,比如刚才说的位置的点,如果无脑地做饱与是有问题的。

这就是大家对复杂模型的调优经验。当前大家企业内部与很多的企业外的量产客户都用了这套工具。

下面是丰富的精度调优工具。这边我列了里面很多的工具,包括一些模型结构的检查工具、排查共享op、算子融合、量化设置等。

共享op对于浮点用户来说,也许很多时候没啥子概念。非常是PyTorch里面,比如像一些检测的头里面,也许某壹个Conv得过好几遍,但是共享op对量化不一定友好。共享op的问题在于:本来是壹个Per-Tensor 的 Scale,但共享了之后就等于于是Multi-Tensor的Scale,壹个Scale管着多个Tensor。除非每次跑多个分支的时候,它的数值范围分布差别很小,这个时候是没有问题的;一旦有一些差别的时候,精度就有问题了。所以大家是不主推我们在QAT阶段运用共享op的,当然有一些工具可以check出来。

下面是一些提供相似度、统计量的工具,方便我们查找量化敏感层。

还有支持单步调试的工具。单步调试与浮点的运用体验是一致的,这就像PyTorch最大的优势就是Python程序,我们都一样是Python程序,没有变成别的东西。

最后壹个是支持部署一致性对齐工具。

调试需要付出一定的代价,不是不收费的。至少大家还没有壹个非常优秀的metric一把搞定全部的case。所以需要通过多指标来共同解析,哪些地方也许会带来量化问题。

大家内部也在持续地寻觅,如何把这个事情做得更好?比如会试试让我们找bad case,如果我们直接跑这些工具,也许有时候反映不出来。但也许找到壹个bad case之后就ok了。这就与debug程序一样,大家试试通过类似的攻略来提高,后面也会持续完善。

这是当前的精度调优的壹个步骤图,我就不具体展开了。

在浮点、Calibration、QAT、Quantized各个阶段都也许会有一些量化问题。比如Calibration,我没有期望Calibration一把就能达到损失1%以内,很多时候是达差点的,这时候需要我们调到QAT上,网络结构,Calibration攻略或量化设置都也许有问题。

QAT转换到Quantized模型的问题在于精度也许会掉,掉的问题有多种,我举壹个相对典型的例子:某壹个非线性的激活,比如 EXP,看着就很怪异,大家量化的时候会把它变成查表,因为查表在硬件里是最好的,算的速度也非常快。但在这时候你的表如何找、如何定表区间,这些都是问题。大家内部是会自动来查找这些东西,但确实出现过1~2个case,大家查到的表区间也是不太合理的,这时候需要做微调。

再主推新一期地平线「你好,开发者」工具链技术专场:12月6日,地平线模型转换与量化工具负责人何道远将主讲《地平线模型转换和训练后量化部署》,报名通道放开中,欢迎扫码参与~

四、未来寻觅方给

最后是大家未来的寻觅方给。

还是会持续寻觅复杂场景模型的量化部署,因为今年的模型确实越来越复杂。

数据的量化部署、量化调优、精度调优的步骤也要持续完善。之前PPT出现过的有一些模型,这些模型确实要花不少时间debug。如果是壹个完全不懂量化算法的人,不一定能把量化完全搞定。某一些case的量化不友好,也许是因为绑定了输入、输出的物理内涵。作为壹个做量化工具的人,有时候不一定能够感知到这些物理内涵。所以我们都要互相懂。做量化的同学要懂一些算法,做算法同学要懂一些量化。目前来看,大家认为这是不可避免的,只是懂的程度的问题。大家也在持续完善,希望让我们尽量少懂一点,能一把或者几把就搞定了。

提高算法迭代的效率。毕竟我们都在抢时间、冲量产,我们已经花了很久来调浮点模型的精度了,不想再花这么长时间来做量化。大家也希望把这套步骤做的更完善一些,可以提高迭代效率。

寻觅更低bit的混合量化。也许不只是更低bit,包括INT8、INT16,FP16甚至更低。因为硬件上会支持各种各样的数据类型,这些数据类型在啥子情况下才是硬件性能最优的?对于QAT来说,确实有很多空间可以寻觅。QAT对于量化的问题,它的容忍度会更高一点,所以它更有也许会得到部署精度更优的模型。

寻觅LLM大模型的量化部署。我今日讲的内容还是量化训练更多一些,大模型的问题也许在于没办法做完整的finetune,把全部的数据再来一遍,这个也许是我们不能接受的。当前我们是只是跑一点数据,类似刚才说的复杂模型,我们都是跑step,而不是跑epoch。如果有的跑step数少,有的跑step数多,带来的精度就不一样。

这些就是大家要寻觅的一些后续的工作。

我今日要讲的内容就是这么多,谢谢我们。