Coremltools: нельзя использовать некоторые выходные данные из не максимального уровня подавления в последующих слоях

EDIT: похоже, что это ошибка в Coremltools. Смотрите здесь:https://github.com/apple/coremltools/issues/691


Резюме одним предложением: слой подавления без максимума выводит четыре значения, но я могу использовать только два из этих четырех значений в качестве входных данных для последующих уровней.

Я создаю модель нейронной сети, используя пакет Apple Core ML Tools, и добавляю слой не максимального подавления (NMS). Согласно документации, этот слой имеет четыре выхода:

  • выход 1: координаты ящика, соответствующие оставшимся ящикам.
  • результат 2: баллы по ячейкам, соответствующие оставшимся ячейкам.
  • вывод 3: индексы уцелевших ящиков. [это результат, который я хочу использовать в следующем слое]
  • выход 4: количество ящиков, выбранных после алгоритма NMS

Я создал тестовую модель с несколькими простыми входными данными, и уровень NMS правильно возвращает ожидаемые значения для каждого из четырех выходов, перечисленных выше. Если я затем использую либо выход №1, либо выход №2 в следующем слое, у меня не будет проблем с этим. Однако, если я пытаюсь использовать выход №3 или выход №4 в следующем слое, я получаю сообщение об ошибке, в котором говорится, что вход "не найден ни на одном из выходов предыдущих слоев".

Блокнот Jupyter

Самый простой способ воспроизвести проблему - загрузить и просмотреть этот блокнот Jupyter.

В качестве альтернативы приведенный ниже пример кода также помогает решить возникшую у меня проблему.

Образец кода

Я установил некоторые образцы входных данных следующим образом:

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_indices или box_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_indices а также 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_coords или nms_scoresвыходы в качестве входа в слой линейной активации, у меня нет никаких проблем. Он будет правильно выводить неизмененныйnms_coords или nms_scores значения из выходных данных уровня NMS.

Я сбит с толку, почему слой NMS правильно выводит то, что я хочу, но тогда я не могу использовать эти выводы в последующих слоях.

1 ответ

Проблема, кажется, была исправлена. Обновите с помощью

pip install coremltools>=5.0b3

Из этого комментария члена команды CoreMLTools:

У меня macOS 11.3, и я использую coremltools версии 5.0b3.

Убедитесь, что все исправлено. Пожалуйста, установите coremltools==5.0b3 в бета-версии Big Sur или Monterey, а затем убедитесь, что вы больше не видите эту ошибку.

Другие вопросы по тегам