MNN icon indicating copy to clipboard operation
MNN copied to clipboard

有关QAT的量化和直接离线量化的问题

Open Shaquille-Wu opened this issue 4 years ago • 18 comments

小弟在用QAT量化模型时遇到一些性能瓶颈,想请阿里的大神们给解释一下
如果直接使用quantized.out对原始.mnn文件进行量化,生成量化模型,这个没问题 如果参照README的关于QAT的方法进行量化训练的话(就是参照MobileNetV2Utils.cpp的代码),正常生成量化模型,但是会生成一堆多余的op: FloatToInt8->Scale->Int8ToFloat,导致最后量化模型的运算速度还不如fp32的模型。按说这堆FloatToInt8/Scale/Int8ToFloat都可以合并掉,不知道有什么方法能合并?

Shaquille-Wu avatar Dec 11 '20 16:12 Shaquille-Wu

是因为scale这个算子不支持量化吧?

xafha avatar Dec 30 '20 07:12 xafha

对的, 这个Scale是QAT的过程产生的,并非说是网络本身造成的 这是因为qat的那个例子里面没有针对训练后的graph做优化,缺少一个OptimizeNet的过程 不知道MNN能否在QAT之后加上这个OptimizeNet? 我们经过对比发现QAT的效果比KL和ADMM都好,所以很期待能给QAT加上完整的Graph的优化

Shaquille-Wu avatar Dec 31 '20 07:12 Shaquille-Wu

不太可能出现你说的的情况,离线量化之后没有这个scale?

yyfcc17 avatar Dec 31 '20 07:12 yyfcc17

这个scale如果能合并,在原始模型到MNN的转换过程中就会优化掉这个scale

yyfcc17 avatar Dec 31 '20 07:12 yyfcc17

不是quantize_tool造成的,是QAT的那个demo造成的 quantize_tool本身不能QAT, QAT的工作只能通过那个demo完成,因此那个demo调用的接口,还没完善我说的功能

Shaquille-Wu avatar Jan 28 '21 15:01 Shaquille-Wu

这个scale你的MNN模型里面没有,QAT训练之后有了?

yyfcc17 avatar Feb 09 '21 07:02 yyfcc17

不是quantize_tool造成的,是QAT的那个demo造成的 quantize_tool本身不能QAT, QAT的工作只能通过那个demo完成,因此那个demo调用的接口,还没完善我说的功能

我用那个demo做QAT的时候,做一个简单的二分类任务,训练loss是nan。请问你没出遇到过这种状况吗?

12z34x avatar Jun 02 '21 13:06 12z34x

这个scale你的MNN模型里面没有,QAT训练之后有了?

你好我用那个demo做QAT的时候,做一个简单的二分类任务,训练loss是nan。请问你没出遇到过这种状况吗

12z34x avatar Jun 02 '21 14:06 12z34x

用这个量化即可 https://github.com/alibaba/MNN/tree/master/tools/MNNPythonOfflineQuant

yyfcc17 avatar Jun 04 '21 02:06 yyfcc17

用这个量化即可 https://github.com/alibaba/MNN/tree/master/tools/MNNPythonOfflineQuant

你好,我的意思是这样的:我已经成功地完成了后量化,但是训练中量化会比后量化掉点更少,所以我想基于这个框架进行qat。然后我使用你们的demo进行简单的二分类任务,数据和代码几乎一致,但是训练损失(默认交叉熵)一直是nan,我想问一下你们是否遇到过这种情况。 我觉得可能的一个原因是,我的模型是多输出的,而我模仿demo中的代码加载模型: net = nn.load_module_from_file(model_file, input_names=["actual_input_1"],output_names=["output3"]) 再使用和demo相同的代码: nn.compress.train_quant(net, quant_bits=8) 得到了“Invalide module for quantized”这个报错,是不是这个原因导致的训练loss为nan?

12z34x avatar Jun 07 '21 01:06 12z34x

是因为MNN训练框架还不成熟,可能有bug,我建议你直接用这个python离线量化工具即可,不要用训练量化

yyfcc17 avatar Jun 07 '21 02:06 yyfcc17

是因为MNN训练框架还不成熟,可能有bug,我建议你直接用这个python离线量化工具即可,不要用训练量化

好的,感谢及时的恢复,试试python的离线量化。

12z34x avatar Jun 07 '21 02:06 12z34x

是因为MNN训练框架还不成熟,可能有bug,我建议你直接用这个python离线量化工具即可,不要用训练量化

您好,还想问一下,QAT demo中的模型是哪个.mnn模型呢,我想跑出demo。

12z34x avatar Jun 07 '21 09:06 12z34x

https://www.yuque.com/mnn/cn/vg3to5

yyfcc17 avatar Jun 07 '21 09:06 yyfcc17

https://www.yuque.com/mnn/cn/vg3to5

您好,我根据您提供的这份代码,按着代码里的方式重新加载了我的模型,发现貌似可以进行QAT了。但我使用以下两种方法进行(全部开启了step(loss)): 1.使用pytorch的交叉熵来计算loss,loss显示正常,再转成mnn格式 2.使用mnn的交叉熵来计算loss,loss显示为nan。 结果是,两方法训练后的模型都会比原始模型精度低一点,但大小是其1/4。所以我认为,第二种方法的loss显示为nan,只是显示错误吧。同时,在一些参数情况下方法1得到的模型会比方法2得到的模型精度高一些,但大小一样。 然后,我还有以下几点疑惑: 1)上述两种方法得到的模型,其精度会是int8的吗? 2)上述两种方法得到的模型,其在计算过程中也是用int8计算,而不是在计算过程中转成了float? 3)为什么我注释掉了step(loss)那行代码,两种方法都不能保存模型了。 4)上述得到的模型就是QAT模型吧,不需要再用量化工具和验证集量化(矫正)一遍吧,因为我后来又对它们量化了一遍,但.mnn无法对相应的结果模型进行测试了(报错segmentation fault)

12z34x avatar Jun 07 '21 13:06 12z34x

四分之一大小就是量化模型,你用netron可视化看看吧 again,MNN训练框架现在不成熟,可能还有bug,建议直接使用python离线量化工具

yyfcc17 avatar Jun 08 '21 02:06 yyfcc17

四分之一大小就是量化模型,你用netron可视化看看吧 again,MNN训练框架现在不成熟,可能还有bug,建议直接使用python离线量化工具

可视化之后没问题,那用这个模型做forward的时候,也是int8计算是吧? 离线量化的话,我试了,注释掉了step(loss)那行代码,结果无法保存模型...所以就没用离线量化

12z34x avatar Jun 08 '21 03:06 12z34x

你好,请问调用python的QAT量化后,推理过程中,也是int8计算吗

YangLiji avatar Sep 15 '22 01:09 YangLiji

支持量化的算子是int8计算的,比如Conv, Pooling等

wangzhaode avatar Feb 15 '23 08:02 wangzhaode