Различные результаты после преобразования pytorch в torchscript? Преобразование NSnumber в Float вызывает какие-либо потери? - PullRequest
3 голосов
/ 08 февраля 2020

Я преобразовал предварительно обученную модель pytorch (.pt) в модель torchscript (.pt) для использования в Swift 5 (ios -iphone6s, xcode 11). В Swift функция «предсказания» модели дала мне свои значения вложения (Тензор). Поскольку в результате прогнозирования он возвратил массив NSNumber, я использовал приведение типов [NSNumber] к обоим [Double] или [Float], чтобы вычислить расстояние между двумя значениями внедрения. Нормализация L2, скалярное произведение и т. Д. c.

Однако в то время как версия Pytorch получила правильные ответы, модель torchscript получила так много неправильных ответов. Не только ответы разные, Расчеты расстояний двух пар внедрения в torchscript также отличаются от результатов модели Pytorch на P C (CPU, Pycharm). Фактически, перед использованием приведения типов для вычислений расстояния значения встраивания в NSNumber (Swift) настолько отличаются от значений в float32 (pytorch). Я использовал те же входные изображения.

Я пытался найти причину. Однажды я скопировал значения вложения ([NSNumber]) из swift-torchscript и вычислил расстояние между двумя встраиваниями в pytorch, чтобы проверить если была проблема с моей реализацией расчета расстояния в Swift. Я использовал torch.FloatTensor, чтобы использовать приведение типов [NSNumber] -> [Float]. Я также попробовал [Double]. В результате этого я нашел много бесконечных чисел. Связаны ли эти бесконечные числа с неправильным ответом?

Что означает этот «инф»? Это ошибка расчета или приведения типа? Я потерял информацию во время трансляции из NSNumber во Float или Double? Как я могу получить правильное значение из модели torchscript в Swift? Что я должен проверить?

Я использовал следующие коды для преобразования. pytorch -> torchscript.

import torch

from models.inception_resnet_v1 import InceptionResnetV1

device = torch.device('cuda:0' if torch.cuda.is_available() else 'cpu')

resnet = InceptionResnetV1(pretrained='vggface2').eval().to(device)

example = torch.rand(1, 3, 160, 160)
traced_script_module = torch.jit.trace(resnet, example)
traced_script_module.save("mobile_model.pt")

1 Ответ

1 голос
/ 10 февраля 2020

Используете ли вы InceptionResnetV1 из: https://github.com/timesler/facenet-pytorch? Когда вы ссылаетесь на модель pytorch при сравнении выходных данных, вы имеете в виду модель torchscript при запуске в pytorch или re snet как есть?

Если это последняя, ​​вы уже проверяете что-то похожее, как показано ниже?

Что вы получаете, когда запускаете следующее:

print('Original:')
orig_res = resnet(example)
print(orig_res.shape)
print(orig_res[0, 0:10])
print('min abs value:{}'.format(torch.min(torch.abs(orig_res))))
print('Torchscript:')
ts_res = traced_script_module(example)
print(ts_res.shape)
print(ts_res[0, 0:10])
print('min abs value:{}'.format(torch.min(torch.abs(ts_res))))
print('Dif sum:')
abs_diff = torch.abs(orig_res-ts_res)
print(torch.sum(abs_diff))
print('max dif:{}'.format(torch.max(abs_diff)))

после определения 'traced_script_module'. Я получаю следующее:

Original:
torch.Size([1, 512])
tensor([ 0.0347,  0.0145, -0.0124,  0.0723, -0.0102,  0.0653, -0.0574,  0.0004,
        -0.0686,  0.0695], device='cuda:0', grad_fn=<SliceBackward>)
min abs value:0.00034740756382234395
Torchscript:
torch.Size([1, 512])
tensor([ 0.0347,  0.0145, -0.0124,  0.0723, -0.0102,  0.0653, -0.0574,  0.0004,
        -0.0686,  0.0695], device='cuda:0', grad_fn=<SliceBackward>)
min abs value:0.0003474018594715744
Dif sum:
tensor(8.1539e-06, device='cuda:0', grad_fn=<SumBackward0>)
max dif:5.960464477539063e-08

, что не идеально, но учитывая, что выходы имеют порядок не менее 10 ^ -4, и что число перед последним является суммой абсолютной разности 512 элементов, не значит, это кажется не слишком далеко для меня. Максимальная разница составляет около 10 ^ -8.

Кстати, вы можете изменить на:

example = torch.rand(1, 3, 160, 160).to(device)

Если вы получите что-то похожее для тестов выше, каковы какого типа значения вы получаете для первых 10 выходных значений, которые вы получаете из swift-torchscript как NSNumber, а затем, будучи приведенными в плавающем порядке, сравниваются с обоими одинаковыми срезами в выходных данных модели pytorch и torchscript-pytorch?

...