Модель coreML, преобразованная из модели pytorch, дает неверные вероятности прогноза

У меня есть модель двоичной классификации pytorch, которую я преобразовал в coreML. Я преобразовал свою модель прямо или косвенно через onnx, используя следующие руководства / документацию соответственно https://coremltools.readme.io/docs/pytorch-conversion и https://github.com/onnx/onnx-docker/blob/master/onnx-ecosystem/inference_demos/resnet50_modelzoo_onnxruntime_inference.ipynb.

Выходные данные до функции softmax и вероятности аналогичны как для исходного pytorch, так и для модели onnx, преобразованной из PyTorch. Но результат для модели coreML, преобразованной из PyTorch с помощью учебной документации, полностью неверен. У меня не было ошибок при компиляции метода coreML из любого метода.

Проверка веса последнего слоя для coreML и Pytorch кажется одинаковой. вывод модели coreML до softmax дает мне {'classLabel': '_xx', 'classLabelProbs': {'_xx': 29.15625, 'xx': -22.53125}}

в то время как результат модели pytorch дает мне [-3,2185674 3,4477997]

Результат преобразования из onnx в coreML выглядит так ...

58/69: Converting Node Type Add
59/69: Converting Node Type Relu
60/69: Converting Node Type Conv
61/69: Converting Node Type BatchNormalization
62/69: Converting Node Type Relu
63/69: Converting Node Type Conv
64/69: Converting Node Type BatchNormalization
65/69: Converting Node Type Add
66/69: Converting Node Type Relu
67/69: Converting Node Type GlobalAveragePool
68/69: Converting Node Type Flatten
69/69: Converting Node Type Gemm
Translation to CoreML spec completed. Now compiling the CoreML model.
Model Compilation done.

В то время как вывод модели pytorch, когда я печатаю, выглядит следующим образом для последнего слоя ....

(layer4): Sequential(
(0): BasicBlock(
(conv1): Conv2d(256, 512, kernel_size=(3, 3), stride=(2, 2), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(downsample): Sequential(
(0): Conv2d(256, 512, kernel_size=(1, 1), stride=(2, 2), bias=False)
(1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(1): BasicBlock(
(conv1): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn1): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
(relu): ReLU(inplace=True)
(conv2): Conv2d(512, 512, kernel_size=(3, 3), stride=(1, 1), padding=(1, 1), bias=False)
(bn2): BatchNorm2d(512, eps=1e-05, momentum=0.1, affine=True, track_running_stats=True)
)
)
(avgpool): AdaptiveAvgPool2d(output_size=(1, 1))
(fc): Linear(in_features=512, out_features=2, bias=True).

Как мне исправить количественные ошибки, вызванные моей моделью coreML, преобразованной из PyTorch?


person Jonathan Brown    schedule 25.10.2020    source источник


Ответы (2)


Вероятно, это проблема с параметрами предварительной обработки изображений: https://machinethink.net/blog/help-core-ml-gives-wrong-output/

person Matthijs Hollemans    schedule 25.10.2020
comment
Я начал свою модель с предварительно обученной модели resnet18 и обучил ее на своих данных. Я использовал ту же предварительную обработку изображения, прежде чем передать его модели как для моей модели pytorch, так и для моей преобразованной модели coreml. Это должно было позаботиться о том, о чем говорится в статье. Верно? - person Jonathan Brown; 26.10.2020
comment
Да, если вы использовали те же параметры предварительной обработки для модели Core ML, то это не должно быть проблемой. Но обратите внимание, что ваш вывод примерно в 10 раз больше, чем вывод PyTorch, что обычно означает, что масштаб ввода уже неправильный. Попробуйте преобразовать модель всего с одним слоем, чтобы убедиться, что это работает. - person Matthijs Hollemans; 26.10.2020

Обновить:

используя унифицированный api coreml, я добавил масштабированный слой. Мои результаты не дают никаких вероятностей для моего классификатора.

! [последние несколько слоев преобразованной модели pytorch] [1] [1]: https://i.stack.imgur.com/9bzd2.png

последний слой печатает тензор вместо вероятностей. Поэтому я добавил функцию softmax через network.builder

builder.add_softmax(name="softmax", input_name="305", output_name="307:labelProbabilityLayerName")

предыдущий последний узел имел выходное имя, равное 307: labelProbabilityLayerName, и я изменил его на 305 до того, как добавил softmax (). таким образом, вывод предыдущего последнего узла является входом в мой softmax. Кроме того, теперь вывод может быть передан в мой softmax, теперь он может подключиться к исходному строковому классу, распечатывая предполагаемые вероятности. Я все еще получаю сообщение об ошибке ...

RuntimeError: Ошибка компиляции модели: Ошибка чтения спецификации protobuf. Ошибка валидатора: уровень softmax использует вход с именем 307, которого нет в этой сети.

Это не имеет смысла, потому что я определил свой softmax для потребления '305', а также обновил этот последний слой, который является слоем внутреннего продукта, для вывода 305.

person Jonathan Brown    schedule 30.10.2020