PaddleClas
PaddleClas copied to clipboard
PaddleClas MultiLabels模型导出的onnx模型推理有BUG
MultiLabels模型导出的onnx模型推理 与 paddle模型相差非常大。
1 代码:PaddleClas develop分支 2 环境:docker images paddlepaddle/paddle:2.1.0-gpu-cuda11.2-cudnn8
下面是我操作的过程:
导出到paddle推理模型
python3 tools/export_model.py -c ./ppcls/configs/quick_start/professional/MobileNetV1_multilabel_intent_eval.yaml -o Arch.pretrained="./output/k1000_focal_2/MobileNetV2/latest"
安装必要的包
python -m pip install -i https://pypi.tuna.tsinghua.edu.cn/simple --upgrade pip
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install paddle2onnx onnx onnx-simplifier onnxruntime-gpu
导出到onnx
paddle2onnx --model_dir inference/ --model_filename inference.pdmodel --params_filename inference.pdiparams --save_file focal2.onnx --opset_version 10 --enable_dev_version True --enable_onnx_checker True
对于同一张图片输入,paddle的输出是:
但是onnx的输出是:
我做的是130类的多标签分类器,两者输出的数值相差很大,经过sigmod之后标签概率大小排序,最大的是同样的,但是数值上明显差别很大。
btw,官方的例子https://github.com/PaddlePaddle/PaddleClas/blob/release/2.4/docs/en/quick_start/quick_start_multilabel_classification_en.md里面,使用NUS-WIDE-SCENE做多标签任务,最后的模型导出到onnx依旧会遇到这个问题。
是我操作不对,还是有解决办法,希望尽快给一个答复。不行的话,我想我在下一周将转到使用pytorch来完成我的工作。
onnx推理代码:
import onnxruntime as ort
session = ort.InferenceSession(r'model/focal2.onnx', providers=['CUDAExecutionProvider']) # 加载模型
outputs = session.run(None, {'x': img}) # 调用模型
在paddle那里的图 贴错了,我再贴一些今天测试的结果:
对于同一张图输入,paddle模型输出后sigmod是(最大的两个数值是0.10090836, 0.96171629):
而onnx模型里面带了sigmod,输出就是想要的数值(最大的两个数值是0.00439452, 0.98361409):
想不出来是哪里出了问题,是paddle转onnx之后精度差这么多吗?
今天有了新的对比发现,把图片保存为bin后利用不同模型处理多标签任务,看输出的最大值判定模型推理是否相同,我发现: (1)运行onnx的结果最大数值是 0.96299744 (2)运行paddleclas自带的推理的功能(/deploy/python/predict_cls.py)的结果最大数值是 0.9629971。 万分位以上的差别都是可以接受的,所以我觉得paddle2onnx还是OK的。 (3)运行paddleclas自带的infer推理(tools/infer.py)的结果最大数值是0.94861。那么问题就出在paddle的动态模型转到paddle的推理模型上。
我在paddlecls的项目里也提一下这个问题,希望能得到解决。
您好,麻烦提供一下paddle的inference model和onnx的model,我们定位一下
你好,我把文件传百度云了,他们都是一一对应的: 链接:https://pan.baidu.com/s/1sscJwEJVflt06I-5fPNKBg?pwd=y9v3 提取码:y9v3
这个issues里还有一些其他描述,如有需要可以查看:https://github.com/PaddlePaddle/Paddle2ONNX/issues/832
是否有新进展呢?我提一下yaml配置:
# global configs
Global:
checkpoints: null
# pretrained_model: ./output/intent3/MobileNetV2/latest
pretrained_model: null
# output_dir: ./output/intent4/
output_dir: ./output/local/
device: cpu
save_interval: 1
eval_during_train: True
eval_interval: 1
epochs: 20
print_batch_step: 10
use_visualdl: False
# used for static mode and model export
image_shape: [ 3, 224, 224 ]
save_inference_dir: ./inference
use_multilabel: True
# model architecture
Arch:
name: MobileNetV2
class_num: 130
pretrained: True
# loss function config for traing/eval process
Loss:
Train:
- MultiLabelLoss:
weight: 1.0
Eval:
- MultiLabelLoss:
weight: 1.0
Optimizer:
name: Momentum
momentum: 0.9
lr:
name: Cosine
learning_rate: 0.001
regularizer:
name: 'L2'
coeff: 0.00004
# data loader for train and eval
DataLoader:
Train:
dataset:
name: MultiLabelDataset
image_root: /mnt/e/multilabels/
cls_label_path: /mnt/e/multilabels/train_labels.txt
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 4
drop_last: False
shuffle: True
loader:
num_workers: 20
use_shared_memory: True
Eval:
dataset:
name: MultiLabelDataset
image_root: /mnt/e/multilabels/
cls_label_path: /mnt/e/multilabels/val_labels.txt # 最小的,从训练集里面摘出来的
# cls_label_path: /ssd/xiedong/datasets/multilabel/eval_all.txt # 所有的
# cls_label_path: /ssd/xiedong/datasets/multilabel/eval_all2.txt # 除了训练集之外的
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
# - CropImage:
# size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 256
drop_last: False
shuffle: False
loader:
num_workers: 20
use_shared_memory: True
Infer:
infer_imgs: /mnt/c/Users/dong.xie/Desktop/workcode/workplace/PaddleClas/deploy/images/fixed/104cartoon_scene000009.jpg
batch_size: 10
transforms:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
# - CropImage:
# size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
- ToCHWImage:
PostProcess:
name: MultiLabelTopk
topk: 10
class_id_map_file: None
Metric:
Train:
- AccuracyScore:
- HammingDistance:
Eval:
- AccuracyScore:
- HammingDistance:
好的,我们会尽快查看
现在的问题是paddle的infer.py和paddle的inference推理没对上还是paddle的inference推理和onnx推理没对上呢?
是前者。 paddle的infer.py和paddle的inference推理没对上。
我这边是可以对上的,你需要检验一下你打印的位置是否正确,是否都是只经过了一个sigmoid函数。
我试了一下,还是不行,我详细写一下我操作过程,看看哪里有问题。
我的local.yaml文件:
# global configs
Global:
checkpoints: null
# pretrained_model: ./output/intent3/MobileNetV2/latest
pretrained_model: null
# output_dir: ./output/intent4/
output_dir: ./output/local/
device: cpu
save_interval: 1
eval_during_train: True
eval_interval: 1
epochs: 20
print_batch_step: 10
use_visualdl: False
# used for static mode and model export
image_shape: [ 3, 224, 224 ]
save_inference_dir: ./inference
use_multilabel: True
# model architecture
Arch:
name: MobileNetV2
class_num: 130
pretrained: True
# loss function config for traing/eval process
Loss:
Train:
- MultiLabelLoss:
weight: 1.0
Eval:
- MultiLabelLoss:
weight: 1.0
Optimizer:
name: Momentum
momentum: 0.9
lr:
name: Cosine
learning_rate: 0.001
regularizer:
name: 'L2'
coeff: 0.00004
# data loader for train and eval
DataLoader:
Train:
dataset:
name: MultiLabelDataset
image_root: /mnt/e/multilabels/
cls_label_path: /mnt/e/multilabels/train_labels.txt
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
- RandFlipImage:
flip_code: 1
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 4
drop_last: False
shuffle: True
loader:
num_workers: 20
use_shared_memory: True
Eval:
dataset:
name: MultiLabelDataset
image_root: /mnt/e/multilabels/
cls_label_path: /mnt/e/multilabels/val_labels.txt # 最小的,从训练集里面摘出来的
# cls_label_path: /ssd/xiedong/datasets/multilabel/eval_all.txt # 所有的
# cls_label_path: /ssd/xiedong/datasets/multilabel/eval_all2.txt # 除了训练集之外的
transform_ops:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
# - CropImage:
# size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
sampler:
name: DistributedBatchSampler
batch_size: 256
drop_last: False
shuffle: False
loader:
num_workers: 20
use_shared_memory: True
Infer:
infer_imgs: /mnt/c/Users/dong.xie/Desktop/workcode/workplace/PaddleClas/deploy/images/fixed/104cartoon_scene000009.jpg
batch_size: 10
transforms:
- DecodeImage:
to_rgb: True
channel_first: False
- ResizeImage:
size: 224
# - CropImage:
# size: 224
- NormalizeImage:
scale: 1.0/255.0
mean: [ 0.485, 0.456, 0.406 ]
std: [ 0.229, 0.224, 0.225 ]
order: ''
- ToCHWImage:
PostProcess:
name: MultiLabelTopk
topk: 10
class_id_map_file: None
Metric:
Train:
- AccuracyScore:
- HammingDistance:
Eval:
- AccuracyScore:
- HammingDistance:
我想进去infer.py的调试,这是给入的参数:
我在infer函数中加的断点:
此时batch_tensor就是那张图,装batch了,所以是(1,3,224,224).
out 变量就是模型输出的数值,此时还没经过sigmod,数值还是较大的:
此时我将执行这段代码:
import paddle.nn.functional as F
print("out的sigmod最大值", F.sigmoid(out).max()) # 0.96171629
import onnxruntime as ort
session = ort.InferenceSession(
r'inference/inference.onnx')
outputs = session.run(None, {'x': batch_tensor.numpy()})
print("onnx", outputs[0].max())
可以看到out经过sigmod之后的最大值是0.96171629,而onnx输出的数值好像是经过sigmod的,所以直接求最大值,是0.9836141。
onnx的输出:
而out变量经过sigmod的数值是:
确实是对不齐啊~~
PS. 我倒挺希望得到的回复是我的onnx模型转换错了,因为从这个结果来看真的让人不理解。
希望能像我这样操作一把试试,从而找到问题根源。
此外,还希望paddleclas在未来给出一些数据增强示例、训练在线可视化的一些东西。
群里加我微信语音讨论下吧~
好的呀,已添加,叫Kevin。
@cuicheng01 @xddun 你好,请问你的问题解决了吗?我在进行多标签分类任务的时候也遇到了这个bug,infer推理值和inference的推理值差异明显,如果解决了麻烦艾特我一下,需要知道该怎么解决这个bug
请问解决了吗,遇到同样的问题,infer正常,export_model进行推理就有问题,同样再转onnx也是有问题,问题出在export_model上,对输出作了归一化操作,实际是不能作这个归一化操作的。
@phoenixliu666 @chennankuan
已经在微信给百度负责这块的人 @cuicheng01 提供了详细的过程文件和描述,这的确是一个很大的BUG,如果各位有在端侧执行推理的需求,可能需要耐心等待bug修复或者换一个框架了,bug修复后 @cuicheng01 应该会第一时间回复此条issues。
问题的确出在export_model上,百度infer的模型导出到自身推理模型上出了问题。
好的,多谢解答
这里有一些支持其他特性的时候导致的一个bug,中间某一个版本修复过,最新的又暴露出来了,最新的PR已修复,同时支持解析label名字。https://github.com/PaddlePaddle/PaddleClas/pull/2219
@xddun @phoenixliu666 解决没有 你们