Toybrick

标题: 同一个模型和代码,同一张图,两次运行结果不一致 [打印本页]

作者: 学校对面    时间: 2024-4-10 11:10
标题: 同一个模型和代码,同一张图,两次运行结果不一致
我有一个torch的原始模型a.pth,通过a->onnx->rknn得到的模型b.rknn,以及a->torch.jit.trace->rknn得到的模型c.rknn。对b和c进行量化以及准确性分析,发现无论是量化层结果(entire_qnt目录中的数据)还是各层的余弦距离(entire_qnt_error_analysis.txt中的数据)都完全一致,但通过python的API进行推理时,只有b是正确的,c始终不正确。

同时,我还发现,c每一次初次加载运行时,对同一张图像第一次运行和第二次运行结果会不一样(之后继续推理这张图象,结果就会和第二次运行保持一致)。更具体的描述:如果我先运行b,在运行c,此时c模型的第一帧会和后续帧结果不一样;重新切回b模型后,再运行c,第一帧和后续帧结果不一致的情况又会重新发生。
请问,这种情况有可能是什么原因导致的楠?我可以通过什么方式来进行检查和调试楠?

作者: jefferyzhang    时间: 2024-4-11 09:31
如果是rknn2建议转onnx再转rknn。
如果是rknn1建议用pt直接转rknn。
推理不正确可以尝试:
1. 用最新的rknntoolkit转换
2. 用netron查看转换后的rknn模型有什么区别
3, 逐层比对输出哪一层出问题
4. 关闭量化查看输出是否正确
作者: 学校对面    时间: 2024-4-11 13:52
jefferyzhang 发表于 2024-4-11 09:31
如果是rknn2建议转onnx再转rknn。
如果是rknn1建议用pt直接转rknn。
推理不正确可以尝试:

感谢回复!针对您的回复
1:我是用的1.7.5
2:两种方式转换后会有区别,区别在于pixelshuffle这个算子,静态图直接转rknn会被分解为reshape和permute等操作;转为onnx再转rknn会成为depth2space,前者速度会更快
3:通过rknn的准确性分析工具rknn.accuracy_analysis()发现两种转换方式的输出完全相同
4:关闭量化后,无论哪一种转换方式都可以正常推理

最后,我今早基本确定了出问题的算子是来自F.interpolate(x, scale_factor=self.upscale, mode='nearest'),我的模型结构是以这个上采样操作做为输入到输出的残差连接。然后,我在torch中,将这一个分支删掉,并在最终rknn量化结果后再加进去,基本上结果就正常了。不过仍然挺好奇为什么这个近邻插值会出现问题,是rknn对这一块的支持有什么bug吗?
作者: 学校对面    时间: 2024-4-11 15:17
jefferyzhang 发表于 2024-4-11 09:31
如果是rknn2建议转onnx再转rknn。
如果是rknn1建议用pt直接转rknn。
推理不正确可以尝试:

另外,虽然今早基本确定了是F.interpolate(x, scale_factor=self.upscale, mode='nearest')导致的原因,但是同样的量化图像和量化设置,torch静态图直接到rknn的效果还是没有torch到onnx再到rknn的效果好。
作者: jefferyzhang    时间: 2024-4-11 16:40
学校对面 发表于 2024-4-11 13:52
感谢回复!针对您的回复
1:我是用的1.7.5
2:两种方式转换后会有区别,区别在于pixelshuffle这个算子, ...

如果关闭量化结果完全相同说明模型转换两种是一致的,区别在于量化方式上。
转换成不同的算子他的数值范围会可能就会有很大变化,如果变化太大,uint8的量化是无法覆盖他所有情况,就会造成量化后的结果误差偏大。
例如 算子A参数范围在 [0, 10] 而concat了一个B参数范围在[100, 500] ,那这种算子量化后效果就会极差,一般做法就是拆算子,或者用混合量化方式将这层算子改为不量化。
作者: 学校对面    时间: 2024-4-11 17:49
jefferyzhang 发表于 2024-4-11 16:40
如果关闭量化结果完全相同说明模型转换两种是一致的,区别在于量化方式上。
转换成不同的算子他的数值范 ...

谢谢,我算子的变化只有depth2shuffle,trace之后被拆分为了reshape->permute->reshape这三步,按理说这些操作不会存在您说的这种情况吧。
作者: jefferyzhang    时间: 2024-4-12 08:55
学校对面 发表于 2024-4-11 17:49
谢谢,我算子的变化只有depth2shuffle,trace之后被拆分为了reshape->permute->reshape这三步,按理说这 ...

可以试着混合量化把这个算子不量化
作者: 学校对面    时间: 2024-4-15 10:48
jefferyzhang 发表于 2024-4-12 08:55
可以试着混合量化把这个算子不量化

您好,按文档执行混合量化时,目前是先根据step1中的建议对其中某一个卷积进行了i16的混合量化,并且在step2中加入了rknn.accuracy_analysis()分析结果,从准确性分析的结果来看目前余弦相似性都已达到0.99以上。但我将step2导出的模型在rknn.inference()中进行推理时,会提示下述错误:

E RKNNAPI: rknn_input_set,  inputs[0].buf wrong, buf = 0x7d91dc0, size = 32400 (min_size = 3240000)!
E Exception: Set inputs failed. error code: RKNN_ERR_PARAM_INVALID

我的模型输入是(1,3,120,90),输出是(1,3,480,360), 连板的设备是rv1126,目前在网上也没有遇到类似的问题,请问这种情况可能是什么原因导致的楠?
作者: jefferyzhang    时间: 2024-4-15 16:43
学校对面 发表于 2024-4-15 10:48
您好,按文档执行混合量化时,目前是先根据step1中的建议对其中某一个卷积进行了i16的混合量化,并且在st ...

set input failed 一般是输入和模型对不上,传入的buffer是你转换时候设置的格式,这里你的模型要3240000尺寸buffer,而你只有32400,这个很明显的问题,自己可以先算下输入尺寸是多少,先不要用0拷贝接口。
作者: 学校对面    时间: 2024-4-15 17:46
jefferyzhang 发表于 2024-4-15 16:43
set input failed 一般是输入和模型对不上,传入的buffer是你转换时候设置的格式,这里你的模型要3240000 ...

嗯嗯,是batch_size我没有设置,它默认100了。然后我现在做混合量化,我发现无论我将模型中哪一层设为i16或f32,整个模型的欧氏距离和余弦相似性任意层都很好,但是结果仍然对不上(可以说跟正常量化模型没啥区别)。。
甚至,我将整个量化模型中所有层都设置为了f16(除了类似reshape这种,设置为f16后我发现它好像还是u8),最终的结果仍然和没有做混合量化的结果一样。。。
请问这个可能的原因在哪里楠?
非常抱歉,一直打扰大哥您




欢迎光临 Toybrick (https://t.rock-chips.com/) Powered by Discuz! X3.3