coremltools:如何正确使用 NeuralNetworkMultiArrayShapeRange?

coremltools: how to properly use NeuralNetworkMultiArrayShapeRange?

我有一个 PyTorch 网络,我想将它部署到 iOS 台设备。简而言之,我未能在 CoreML 中为输入张量形状增加灵活性。

该网络是一个卷积神经网络,它将 RGB 图像(存储为张量)作为输入,returns 一个相同大小的 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"
  }
}

模型的输入必须是 multiArrayType 大小 (1, 3, 300, 300)。通过将此模型复制到 XCode,我可以在检查模型时看到 my_name 列在 "Inputs" 部分下,它应该是 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 时,我很确定它正在处理另一个项目,但此时我什么都不确定。

我正在使用:

感谢您的帮助

最简单的方法就是删除 shape:1。像这样:

del spec.description.input[0].shape[0]

现在默认形状也应该有 3 个维度。

但是,我建议将输入类型从多数组更改为实际图像。因为无论如何你都会将它与图像一起使用。这将使您将图像作为 CVPixelBufferCGImage 对象而不是 MLMultiArray.

传递