首页 > 解决方案 > Coremltools:不能在后续层中使用来自非最大抑制层的一些输出

问题描述

编辑:似乎这是 Coremltools 中的一个错误。见这里: https ://github.com/apple/coremltools/issues/691#event-3295066804


一句话总结:非最大抑制层输出四个值,但我只能使用这四个值中的两个作为后续层的输入。

我正在使用 Apple 的 Core ML Tools 包构建神经网络模型,并且添加了一个非最大抑制 (NMS) 层。根据文档,该层有四个输出:

我用一些简单的输入建立了一个测试模型,NMS 层正确地返回了上面列出的四个输出中的每一个的预期值。如果我随后在后续层中使用 output#1 或 output#2,那么我这样做没有问题。但是,如果我尝试在后续层中使用 output#3 或 output#4,我会收到一条错误消息,指出输入“在前面层的任何输出中都找不到”。

Jupyter 笔记本

复制此问题的最简单方法是下载并浏览此Jupyter Notebook

或者,下面的示例代码也解决了我遇到的问题。

示例代码

我设置了一些示例输入数据,如下所示:

boxes = np.array(
    [[[0.00842474, 0.83051298, 0.91371644, 0.55096077],
      [0.34679857, 0.31710117, 0.62449838, 0.70386912],
      [0.08059154, 0.74079195, 0.61650205, 0.28471152]]], np.float32)

scores = np.array(
    [[[0.87390688],
      [0.2797731 ],
      [0.72611251]]], np.float32)

input_features = [('boxes', datatypes.Array(*boxes.shape)),
                  ('scores', datatypes.Array(*scores.shape))]
output_features = [('output', None)]

data = {'boxes': boxes,
        'scores': scores }

我已经建立了如下测试模型:

builder = neural_network.NeuralNetworkBuilder(input_features, output_features, disable_rank5_shape_mapping=True)

# delete the original output, which was just a placeholder while initializing the model
del builder.spec.description.output[0]

# add the NMS layer
builder.add_nms(
    name="nms",
    input_names=["boxes","scores"],
    output_names=["nms_coords", "nms_scores", "surviving_indices", "box_count"],
    iou_threshold=0.5,
    score_threshold=0.5,
    max_boxes=3,
    per_class_suppression=False)

# make the model output all four of the NMS layer's outputs
for name in ["nms_coords", "nms_scores", "surviving_indices", "box_count"]:
    builder.spec.description.output.add()
    builder.spec.description.output[-1].name = name
    builder.spec.description.output[-1].type.multiArrayType.dataType = ft.ArrayFeatureType.FLOAT32

# # add a linear activation layer (intentionally commented out)
# builder.add_activation(
#     name="identity",
#     non_linearity="LINEAR",
#     input_name="surviving_indices",
#     output_name="activation_output",
#     params=[1.0,0.0])

# initialize the model
model = coremltools.models.MLModel(builder.spec)

此时,当我调用

output = model.predict(data, useCPUOnly=True)
print(output)

一切都按预期工作。

例如,如果我调用print(output['surviving_indices'],结果是[[ 0. 2. -1.]](如预期的那样)。

但是,我无法使用surviving_indicesbox_count输出作为后续层的输入。例如,如果我添加一个线性激活层(通过取消注释上面的块),我会得到以下错误:

Input 'surviving_indices' of layer 'identity' not found in any of the outputs of the preceding layers.

如果我使用box_count输出(即通过input_name="box_count"add_activation图层中设置),我也会遇到同样的问题。

我知道 NMS 层正确返回了名为surviving_indicesand的输出box_count,因为当我调用时,print(builder.spec.neuralNetwork.layers[0])我得到以下结果:

name: "nms"
input: "boxes"
input: "scores"
output: "nms_coords"
output: "nms_scores"
output: "surviving_indices"
output: "box_count"
NonMaximumSuppression {
  iouThreshold: 0.5
  scoreThreshold: 0.5
  maxBoxes: 3
}

此外,如果我使用nms_coordsnms_scores输出作为线性激活层的输入,我没有任何问题。它将正确输出 NMS 层输出中未修改的nms_coordsnms_scores值。

我对为什么 NMS 层正确输出我想要的内容感到困惑,但是我无法在后续层中使用这些输出。

标签: iosswiftcoremlcoremltoolsnon-maximum-suppression

解决方案


推荐阅读