从 pytorch 模型转换而来的 coreML 模型给出了错误的预测概率
Posted
技术标签:
【中文标题】从 pytorch 模型转换而来的 coreML 模型给出了错误的预测概率【英文标题】:coreML model converted from pytorch model giving the wrong prediction probabilities 【发布时间】:2021-02-07 15:38:02 【问题描述】:我有一个转换为 coreML 的 pytorch 二进制分类模型。我分别使用以下教程/文档通过 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, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), 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, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Linear(in_features=512, out_features=2, bias=True).
如何解决从 PyTorch 转换的 coreML 模型产生的定量错误?
【问题讨论】:
【参考方案1】:这可能是您的图像预处理选项的问题:https://machinethink.net/blog/help-core-ml-gives-wrong-output/
【讨论】:
我从一个预训练的 resnet18 模型开始我的模型,并用我的数据对其进行了训练。在将图像传递给我的 pytorch 模型和转换后的 coreml 模型之前,我对图像使用了相同的预处理。那应该照顾文章所谈论的内容。对吗? 是的,如果您对 Core ML 模型使用相同的预处理选项,那么这应该不是问题。但请注意,您的输出比 PyTorch 输出大约 10 倍,这通常意味着输入的比例已经错误。尝试转换只有一层的模型,看看是否可以正常工作。【参考方案2】:更新:
使用 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: Error compile model: "Error reading protobuf spec.验证器错误:“softmax”层使用了一个名为“307”的输入,该输入在此网络中不存在。”。”
这没有意义,因为我将我的 softmax 定义为消耗“305”,并且还将作为内积层的最后一层更新为输出 305。
【讨论】:
以上是关于从 pytorch 模型转换而来的 coreML 模型给出了错误的预测概率的主要内容,如果未能解决你的问题,请参考以下文章
将 PyTorch 模型与 CoreML 一起使用时输入尺寸重塑
如何在 TensorFlow、Keras 或 PyTorch 中部署 CoreML 模型?
将 pytorch 转换为 coreml 以实现逐元素最大操作