从pytorch模型转换的coreML模型提供了错误的预测概率

问题描述

我有一个pytorch二进制分类模型,我将其转换为coreML。我分别使用以下教程/文档通过onnx直接和间接转换了我的模型 https://coremltools.readme.io/docs/pytorch-conversion,以及 https://github.com/onnx/onnx-docker/blob/master/onnx-ecosystem/inference_demos/resnet50_modelzoo_onnxruntime_inference.ipynb

对于原始pytorch和从PyTorch转换的onnx模型,softmax函数之前的输出和概率相似。但是,通过教程文档从PyTorch转换的coreML模型的输出是完全错误的。从任何一种方法编译coreML方法都没有错误

检查coreML和Pytorch的最后一层的权重似乎是相同的。 softmax之前coreML模型的输出给了我 {'classLabel':'_xx','classLabelProbs':{'_xx':29.15625,'xx':-22.53125}}

pytorch模型的输出给了我[-3.2185674 3.4477997]

从onnx到coreML的转换输出看起来像...

58/69: Converting Node Type Add
59/69: Converting Node Type Relu
60/69: Converting Node Type Conv
61/69: Converting Node Type Batchnormalization
62/69: Converting Node Type Relu
63/69: Converting Node Type Conv
64/69: Converting Node Type Batchnormalization
65/69: Converting Node Type Add
66/69: Converting Node Type Relu
67/69: Converting Node Type GlobalAveragePool
68/69: Converting Node Type Flatten
69/69: Converting Node Type Gemm
Translation to CoreML spec completed. Now compiling the CoreML model.
Model Compilation done.

当我打印时,pytorch模型的输出在最后一层看起来像这样。

(layer4): Sequential(
(0): BasicBlock(
(conv1): Conv2d(256,512,kernel_size=(3,3),stride=(2,2),padding=(1,1),bias=False)
(bn1): Batchnorm2d(512,eps=1e-05,momentum=0.1,affine=True,track_running_stats=True)
(relu): ReLU(inplace=True)
(conv2): Conv2d(512,stride=(1,bias=False)
(bn2): Batchnorm2d(512,track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256,kernel_size=(1,bias=False)
(1): Batchnorm2d(512,track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(512,track_running_stats=True)
)
)
(avgpool): AdaptiveAvgPool2d(output_size=(1,1))
(fc): Linear(in_features=512,out_features=2,bias=True).

我该如何解决从PyTorch转换而来的coreML模型产生的定量误差?

解决方法

您的图像预处理选项可能有问题:https://machinethink.net/blog/help-core-ml-gives-wrong-output/

,

更新:

使用coreml统一api,我添加了一个可缩放的层。我的输出没有给出分类器的任何概率。

![转换后的pytorch模型的最后几层] [1] [1]:https://i.stack.imgur.com/9bzd2.png

最后一层打印出张量而不是概率。所以我通过network.builder添加了softmax函数

builder.add_softmax(name="softmax",input_name="305",output_name="307:labelProbabilityLayerName")

上一个最后一个节点的输出名称等于“ 307:labelProbabilityLayerName”,在添加softmax()之前,我将其更改为“ 305”。这样,前一个最后一个节点的输出就是我的softmax的输入。而且,现在可以将输出传递给我的softmax了,现在可以将其连接到原始字符串类,以打印出预期的概率。 我仍然收到错误消息说...

“ RuntimeError:错误编译模型:”读取protobuf规范时出错。验证程序错误:“ softmax”层消耗了此网络中不存在的名为“ 307”的输入。”。

这没有任何意义,因为我将softmax定义为消耗'305',并且还更新了最后一层,它是内部乘积层,以输出305。

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...