coremltools:如何正确使用 NeuralNetworkMultiArrayShapeRange?
Posted
技术标签:
【中文标题】coremltools:如何正确使用 NeuralNetworkMultiArrayShapeRange?【英文标题】:coremltools: how to properly use NeuralNetworkMultiArrayShapeRange? 【发布时间】:2020-04-26 23:10:43 【问题描述】:我有一个 PyTorch 网络,我想将它部署到 ios 设备。简而言之,我未能为 CoreML 中的输入张量形状增加灵活性。
该网络是一个卷积网络,它将 RGB 图像(存储为张量)作为输入并返回相同大小的 RGB 图像。使用 PyTorch,我可以输入我想要的任何尺寸的图像,例如 300x300 图像的尺寸为 (1, 3, 300, 300) 的张量。
为了将 PyTorch 模型转换为 CoreML 模型,我首先使用 torch.onnx.export
将其转换为 ONNX 模型。此函数需要传递一个虚拟输入,以便它可以执行图形。所以我确实使用了:
input = torch.rand(1, 3, 300, 300)
我的猜测是 ONNX 模型只接受大小为(1、3、300、300)的图像/张量。现在,我可以使用onnx_coreml.convert
函数将 ONNX 模型转换为 CoreML 模型。通过使用 Python 打印 CoreML 模型的规范描述,我得到如下信息:
input
name: "my_image"
type
multiArrayType
shape: 1
shape: 3
shape: 300
shape: 300
dataType: FLOAT32
output
name: "my_output"
type
multiArrayType
shape: 1
shape: 3
shape: 300
shape: 300
dataType: FLOAT32
metadata
userDefined
key: "coremltoolsVersion"
value: "3.1"
模型的输入必须是大小为 (1, 3, 300, 300) 的 multiArrayType
。通过将此模型复制到 XCode,我可以在检查模型时看到 my_name
列在“输入”部分下,并且预计是 MultiArray (Float32 1 x 3 x 300 x 300)
。到目前为止,一切都是一致的。
我的问题是增加输入形状的灵活性。我尝试使用 coremltools 没有运气。这是我的问题。这是我的代码:
import coremltools
from coremltools.models.neural_network import flexible_shape_utils
spec = coremltools.utils.load_spec('my_model.mlmodel')
shape_range = flexible_shape_utils.NeuralNetworkMultiArrayShapeRange()
shape_range.add_channel_range((3,3))
shape_range.add_height_range((64, 5000))
shape_range.add_width_range((64, 5000))
flexible_shape_utils.update_multiarray_shape_range(spec, feature_name='my_image', shape_range=shape_range)
coremltools.models.utils.save_spec(spec, 'my_flexible_model.mlmodel')
我使用 Python 得到以下规范描述:
input
name: "my_image"
type
multiArrayType
shape: 1
shape: 3
shape: 300
shape: 300
dataType: FLOAT32
shapeRange
sizeRanges
lowerBound: 3
upperBound: 3
sizeRanges
lowerBound: 64
upperBound: 5000
sizeRanges
lowerBound: 64
upperBound: 5000
只有指定的 3 个范围,这是有道理的,因为我只定义了通道、高度和宽度的范围,而不是批量大小。在 XCode 中,检查灵活的 CoreML 模型时出现以下错误:
There was a problem decoding this CoreML document
validator error: Description of multiarray feature 'my_image' has a default 4-d shape but a 3-d shape range
当我在 macOS X Mojave 上时,我很确定它正在开发另一个项目,但现在我什么都不确定。
我正在使用:
macOS X Catalina conda 4.7.12 python 3.7.5 pytorch 1.3.1 onnx 1.6.0 onnx-coreml 1.1 coremltools 3.1感谢您的帮助
【问题讨论】:
【参考方案1】:最简单的方法是删除shape:1
。像这样的:
del spec.description.input[0].shape[0]
现在默认形状也应该有 3 个维度。
但是,我建议将输入类型从多数组更改为实际图像。因为无论如何您都将使用它来处理图像。这将使您可以将图像作为CVPixelBuffer
或CGImage
对象而不是MLMultiArray
传递。
【讨论】:
使用del spec.description.input[0].type.multiArrayType.shape[0]
我能够按照您的建议摆脱第一个维度,然后我能够增加灵活性。但是,我无法使用 coremltools 调用预测函数(无法加载 CoreML.framework。无法进行预测。)并且 XCode 在模型描述窗口中显示错误(验证器错误:“卷积”类型的层“88”有输入排名 3,但预计排名至少为 4。)。问题可能来自非常规的极端层。我会尝试按照您的建议切换到图片。
可以在没有灵活输入的情况下将模型加载到 Xcode 中吗?奇怪的是,仅仅因为你增加了输入灵活性,你就会在卷积层上得到一个错误。
对不起,我的回答不清楚。 1) 我可以在 XCode 中加载初始 CoreML 模型,但我无法为其添加灵活性(因为输入是 4D 张量)。 2) 通过使用del (...)
删除第一个维度,我可以为模型增加灵活性,但是我无法在 XCode 中加载具有或不具有灵活性的模型 (validator error: Layer '88' of type 'Convolution' has input rank 3 but expects rank at least 4.
)
很难从远处调试它,但是当您将shape: 1
留在其中并添加带有lowerBound: 1
和upperBound: -1
的第4 个sizeRanges
事物时,它是否有效?我认为您不能为此使用 NeuralNetworkMultiArrayShapeRange,因此您必须直接使用 protobuf 对象修改shapeRange
。不确定 Core ML 是否会喜欢有 4 个维度而不是 3 个维度,但值得一试。
我认为手动添加sizeRanges
可以解决我的问题。我已经尝试过我的模型的一个子部分,它看起来很有希望。我现在必须在主模型上验证这一点。一旦我有新信息,将在这里发表评论。以上是关于coremltools:如何正确使用 NeuralNetworkMultiArrayShapeRange?的主要内容,如果未能解决你的问题,请参考以下文章
导入 coremltools 时出错 - 无法导入名称 ParametricSoftPlus
构建一个 sklearn 文本分类器并使用 coremltools 进行转换
尝试使用 coremltools 4.1 将模型转换为 coreml 不工作
使用 iOS 11 mlmodel 进行图像分类 - 使用 coremltools 和经过训练的 .caffemodel 转换问题