Различные результаты после преобразования pytorch в torchscript? Преобразование NSnumber в Float приведет к потерям?

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

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

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

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

Я использовал следующие коды для преобразования. 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 ответ

Решение

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

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

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

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, а затем, после преобразования в float, по сравнению с двумя одинаковыми срезами в выходы модели pytorch и torchscript-pytorch?

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