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, а затем убедитесь, что вы больше не видите эту ошибку.