推論を行ったとき結果がnullとなるケースが多々ある. 今回PreTrainedのresnetをonnx exportし,onnx runtimeで推論すると結果が返るが, pytorchで学習を進めたモデルをexportした場合,推論結果がnullとなった際の備忘録.
結論
画像を配列にしたとき正規化を行えば推論結果が返るようになった.
input_image = cv2.imread(file_path)/255
序論
推論時はモデルの入出力の型に注意しなくてはいけない. 今回画像をTensorFloat配列に変換しモデルに入力する.
UWPにonnxモデルを取り込むとcode generatorが自動でラッパーファイルをonnx_model_name.csで生成する.
その際にInputの方をImageFeatureValueまたはTensorFloatにすると思うが,
入力配列の中身の値が0~255で構成されているならばImageFeatureValue,0~1ならTensorFloatを用いれば良い(と思う).
余談だが配列の中身の値が-1~1の範囲を求めるならば,onnxexportの際にtorch.randnを用いる.
modelのexportと推論
学習後のモデルをonnx exportする.
(BatchNorm層のあるモデルでもtorchの最新版であれば対応しています)
import torch import torchvision model = torchvision.models.detection.maskrcnn_resnet50_fpn(pretrained=True) x = torch.rand(1,3,2048, 1084,device=torch.device("cpu")) torch.onnx.export(model.cpu(), x, "detection_resnet_op11.onnx", export_params=True,#モデルに訓練した重みも保存するか否か verbose=False, #変換の途中経過を見るかどうか opset_version = 11)
上記のように学習済みのResnet50であれば,onnx sessionで推論した画像をcv2で読み込んでInputに指定すれば結果が返る.
今回はtrain_one_epoch(model, optimizer, data_loader, device, epoch, print_freq=100)後のmodelだと推論結果がnullになった.
そこでevaluate(model.cpu(), data_loader_test, device=device)の際にモデルに入力される画像の中身を確認した.
model(images)で推論されているのだが,そのimagesをprint
・Resnet
・自前データセットでの学習後の推論
ここで自分の愚に気付く!!
画像を正規化すれば解決しました.
以下推論コード
# Writer : Yu Yamaoka import onnxruntime import numpy as np import torch import cv2 #モデルの読み込み onnx_session = onnxruntime.InferenceSession(model_path)# ex:) model_path = "model.onnx" #入力画像の用意 input_image = cv2.imread(file_name) # file_name = "picture.png" input_image = input_image/255 #正規化(笑) input_image = input_image.transpose(2, 1, 0).astype('float32') #モデルのInputの型と合うように転置すればいいです input_image = input_image.reshape(1,3,2048, 1084)#Ajust model input shape #モデルへのInputとOutputを規定 input_name = onnx_session.get_inputs()[0].name#NetronでInputの名前を確認してもいい. output_name = onnx_session.get_outputs()[1].name#欲しい出力を決める,Netronで確認するのが楽. #推論 result = onnx_session.run([output_name], {input_name: input_image}) #推論結果整形 result = np.array(result).squeeze() print(result)
本日はここまでです.お疲れ様でした.