PyTorch YOLACT モデルの変換¶
危険
ここで説明されているコードは非推奨になりました。従来のソリューションの適用を避けるため使用しないでください。下位互換性を確保するためにしばらく保持されますが、最新のアプリケーションでは使用してはなりません。
このガイドでは、非推奨となった変換方法について説明します。新しい推奨方法に関するガイドは、Python チュートリアルに記載されています。
You Only Look At Coefficients (YOLACT) は、リアルタイム・インスタンス・ セグメント化のシンプルな完全畳み込みモデルです。PyTorch 実装は、こちらの GitHub リポジトリーで公開されています。YOLACT++ モデルは、ONNX 形式で表現できない変形可能な畳み込みレイヤーを使用するため、サポートされていません。
パッチファイルの作成¶
モデルを変換する前に、リポジトリー用のパッチファイルを作成します。このパッチは、コマンドライン引数をフレームワーク・オプションに追加してフレームワーク・コードを変更します。この引数により、推論グラフのダンプが有効になります。
書き込み可能なディレクトリーに移動し、
YOLACT_onnx_export.patch
ファイルを作成します。-
次の差分コードをファイルにコピーします。
From 76deb67d4f09f29feda1a633358caa18335d9e9f Mon Sep 17 00:00:00 2001 From: "OpenVINO" <openvino@intel.com> Date: Fri, 12 Mar 2021 00:27:35 +0300 Subject: [PATCH] Add export to ONNX --- eval.py | 5 ++++- utils/augmentations.py | 7 +++++-- yolact.py | 29 +++++++++++++++++++---------- 3 files changed, 28 insertions(+), 13 deletions(-) diff --git a/eval.py b/eval.py index 547bc0a..bde0680 100644 --- a/eval.py +++ b/eval.py @@ -593,9 +593,12 @@ def badhash(x): return x def evalimage(net:Yolact, path:str, save_path:str=None): - frame = torch.from_numpy(cv2.imread(path)).cuda().float() + frame = torch.from_numpy(cv2.imread(path)).float() + if torch.cuda.is_available(): + frame = frame.cuda() batch = FastBaseTransform()(frame.unsqueeze(0)) preds = net(batch) + torch.onnx.export(net, batch, "yolact.onnx", opset_version=11) img_numpy = prep_display(preds, frame, None, None, undo_transform=False) diff --git a/utils/augmentations.py b/utils/augmentations.py index cc7a73a..2420603 100644 --- a/utils/augmentations.py +++ b/utils/augmentations.py @@ -623,8 +623,11 @@ class FastBaseTransform(torch.nn.Module): def __init__(self): super().__init__() - self.mean = torch.Tensor(MEANS).float().cuda()[None, :, None, None] - self.std = torch.Tensor( STD ).float().cuda()[None, :, None, None] + self.mean = torch.Tensor(MEANS).float()[None, :, None, None] + self.std = torch.Tensor( STD ).float()[None, :, None, None] + if torch.cuda.is_available(): + self.mean.cuda() + self.std.cuda() self.transform = cfg.backbone.transform def forward(self, img): diff --git a/yolact.py b/yolact.py index d83703b..f8c787c 100644 --- a/yolact.py +++ b/yolact.py @@ -17,19 +17,22 @@ import torch.backends.cudnn as cudnn from utils import timer from utils.functions import MovingAverage, make_net -# This is required for Pytorch 1.0.1 on Windows to initialize Cuda on some driver versions. -# See the bug report here: https://github.com/pytorch/pytorch/issues/17108 -torch.cuda.current_device() - -# As of March 10, 2019, Pytorch DataParallel still doesn't support JIT Script Modules -use_jit = torch.cuda.device_count() <= 1 -if not use_jit: - print('Multiple GPUs detected! Turning off JIT.') +use_jit = False ScriptModuleWrapper = torch.jit.ScriptModule if use_jit else nn.Module script_method_wrapper = torch.jit.script_method if use_jit else lambda fn, _rcn=None: fn +def decode(loc, priors): + variances = [0.1, 0.2] + boxes = torch.cat((priors[:, :2] + loc[:, :, :2] * variances[0] * priors[:, 2:], priors[:, 2:] * torch.exp(loc[:, :, 2:] * variances[1])), 2) + + boxes_result1 = boxes[:, :, :2] - boxes[:, :, 2:] / 2 + boxes_result2 = boxes[:, :, 2:] + boxes_result1 + boxes_result = torch.cat((boxes_result1, boxes_result2), 2) + + return boxes_result + class Concat(nn.Module): def __init__(self, nets, extra_params): @@ -476,7 +479,10 @@ class Yolact(nn.Module): def load_weights(self, path): """ Loads weights from a compressed save file. """ - state_dict = torch.load(path) + if torch.cuda.is_available(): + state_dict = torch.load(path) + else: + state_dict = torch.load(path, map_location=torch.device('cpu')) # For backward compatibility, remove these (the new variable is called layers) for key in list(state_dict.keys()): @@ -673,8 +679,11 @@ class Yolact(nn.Module): else: pred_outs['conf'] = F.softmax(pred_outs['conf'], -1) - return self.detect(pred_outs, self) + pred_outs['boxes'] = decode(pred_outs['loc'], pred_outs['priors']) # decode output boxes + pred_outs.pop('priors') # remove unused in postprocessing layers + pred_outs.pop('loc') # remove unused in postprocessing layers + return pred_outs --
ファイルを保存して閉じます。
YOLACT モデルを OpenVINO IR 形式に変換¶
ステップ 1. この GitHub リポジトリーのクローンを作成し、コミットをチェックアウトします。
-
YOLACT リポジトリーのクローンを作成します。
git clone https://github.com/dbolya/yolact
-
必要なコミットをチェックアウトしてください。
git checkout 57b8f2d95e62e2e649b382f516ab41f949b57239
README.md
の説明に従って環境をセットアップします。
ステップ 2. README.md
ドキュメントの Evaluation
セクションに添付されているリストから、事前トレーニング済みモデル (yolact_base_54_800000.pth
など) をダウンロードします。
ステップ 3. モデルを ONNX 形式に変換します。
-
YOLACT_onnx_export.patch パッチをリポジトリーに適用します。パッチファイルがない場合は、パッチファイルの作成の手順を参照してください。
git apply /path/to/patch/YOLACT_onnx_export.patch
-
YOLACT モデルを評価して ONNX 形式にエクスポートします。
python3 eval.py \ --trained_model=/path/to/yolact_base_54_800000.pth \ --score_threshold=0.3 \ --top_k=10 \ --image=/path/to/image.jpg \ --cuda=False
スクリプトは失敗する可能性がありますが、
yolact.onnx
ファイルを取得する必要があります。
ステップ 4. モデルを IR に変換します。
mo --input_model /path/to/yolact.onnx
ステップ 5. 入力前処理を IR に埋め込みます。
平均値/スケール値と RGB->BGR 変換を OpenVINO アプリケーションにオフロードしてパフォーマンスを向上させるには、次のモデル変換 API パラメーターを使用します。
-
モデルのバックボーンが Resnet50-FPN または Resnet101-FPN の場合は、次の MO コマンドラインを使用します。
mo \ --input_model /path/to/yolact.onnx \ --reverse_input_channels \ --mean_values "[123.68, 116.78, 103.94]" \ --scale_values "[58.40, 57.12, 57.38]"
-
モデルのバックボーンが Darknet53-FPN の場合は、次の MO コマンドラインを使用します。
mo \ --input_model /path/to/yolact.onnx \ --reverse_input_channels \ --scale 255