Ultralytics YOLO27: ウェイトリストに登録する。
Get Started
レッスン初級

デプロイ用にエクスポートする

best.ptをONNX、OpenVINO、TensorRT、CoreML、LiteRT、またはQNNにエクスポートし、出荷前にエクスポートモデルがPyTorchモデルと一致することを確認してください。

best.ptの実行にはPythonとPyTorchが必要ですが、スマートフォン、ブラウザー、Jetson、実運用サーバーには通常インストールされていません。Exportモードを使うと、1回の呼び出しで、これらのランタイム向けの自己完結型ファイルにモデルを変換できます。注意点として、ファイルを読み込めるからといって、エクスポートが正しいとは限りません。また、不注意な比較によって、正しいエクスポートが壊れているように見えたり、壊れたエクスポートを見逃したりすることがあります。

このレッスンでは、錠剤モデルをONNXにエクスポートし、同じYOLO APIで実行します。また、条件を揃えてボックスと検証mAPを比較し、モデルが一致することを確認したうえで、対象環境に適した形式を選択します: ONNX、OpenVINO、TensorRT、CoreML、LiteRT、またはQNN。

成果

学習済みモデルをデプロイ先に適した形式にエクスポートし、条件を揃えたパリティチェックと検証によって、エクスポートモデルがbest.ptと一致することを確認できます。

短期集中コース
すでに使い方をご存じの方は、こちらをご覧ください。
  1. yolo export model=runs/detect/pills_v1/weights/best.pt format=onnx — まずはこちらから始めてください。

  2. Intel CPU向けのOpenVINO、NVIDIA GPUとJetson向けのTensorRT、Apple向けのCoreML、Android向けのLiteRT、Snapdragon NPU向けのQNNです。

  3. .pt側でrect=Falseを使い、同じ画像に対する.ptとエクスポートモデルの結果を比較してください。

  4. 学習時のimgszで両方を検証してください。mAP50-95は一致するはずです。

実践的

実践例: ONNXへのエクスポート#

Ultralytics Platformのモデルエクスポートタブ。ONNX、TensorRT、CoreML、OpenVINOなどのデプロイ形式が一覧表示されています

yolo export model=runs/detect/pills_v1/weights/best.pt format=onnx
PyTorch: starting from 'runs/detect/pills_v1/weights/best.pt' with input shape (1, 3, 320, 320) BCHW and output shape(s) (1, 5, 2100) (5.2 MB)
ONNX: export success ✅ 0.9s, saved as 'runs/detect/pills_v1/weights/best.onnx' (9.3 MB)
Predict:         yolo predict task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320
Validate:        yolo val task=detect model=runs/detect/pills_v1/weights/best.onnx imgsz=320 data=my_dataset/data.yaml

各行の説明:

  • input shape (1, 3, 320, 320): 1枚の画像、3つのカラーチャネル、固定された320×320の正方形です。ファイルに組み込まれた学習時のimgszを使用します。
  • output shape(s) (1, 5, 2100): 2,100個の候補ボックスそれぞれに、4つのボックス値と1つのクラススコアがあります。デフォルトでは、NMSはグラフの外部で実行されます。
  • 9.3 MB: ONNXファイルにはFP32の重みが保存されるため、FP16の.ptより大きくなります。
  • Predict: / Validate:: エクスポート済みファイル向けのコマンドが用意されており、適切なimgszがすでに指定されています。

ほとんどの用途では、いくつかの引数を指定すれば十分です。その他の引数については、ONNX統合ガイドを参照してください。

引数デフォルト用途
imgsz学習時のサイズ異なる固定入力サイズでエクスポートします(例: imgsz=640)
dynamicFalse固定形状ではなく、可変の入力サイズを受け入れます
quantizeなし(FP32)FP16の重みには16を使用します(yolo26n.onnxは9.5 MBから4.8 MBに縮小します)。形式が対応している場合、INT8には8を使用します
nmsなしnms=TrueはNMSをグラフに埋め込むため、ランタイムは最終ボックスを返します

実践例: エクスポートモデルの一致を確認する#

YOLOクラスはエクスポート済みファイルも読み込めるため、先ほどのPredictコードを変更せずに使えます。同じ検証画像で両方のファイルを比較してください:

from ultralytics import YOLO

image = "my_dataset/images/val/Frame_144.jpg"
pt = YOLO("runs/detect/pills_v1/weights/best.pt")(image, rect=False, verbose=False)[0]  # square input, like ONNX
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx")(image, verbose=False)[0]

print(f"pt:   {len(pt.boxes)} pills, mean conf {pt.boxes.conf.mean():.3f}")
print(f"onnx: {len(onnx.boxes)} pills, mean conf {onnx.boxes.conf.mean():.3f}")
print(f"max box difference: {(pt.boxes.xyxy - onnx.boxes.xyxy).abs().max():.4f} px")
pt:   25 pills, mean conf 0.870
onnx: 25 pills, mean conf 0.870
max box difference: 0.0002 px

検出数と信頼度は同じで、ボックスはピクセルのわずかな端数まで一致しています。次に、データ分割全体で検証を行い、さらに厳密に確認します:

from ultralytics import YOLO

pt = YOLO("runs/detect/pills_v1/weights/best.pt").val(data="my_dataset/data.yaml", rect=False, verbose=False)
onnx = YOLO("runs/detect/pills_v1/weights/best.onnx").val(data="my_dataset/data.yaml", verbose=False)
print(f".pt   mAP50-95 {pt.box.map:.4f}")
print(f".onnx mAP50-95 {onnx.box.map:.4f}")
.pt   mAP50-95 0.6570
.onnx mAP50-95 0.6570

一致しています。(.ptファイルのデフォルトの矩形検証では0.659となりました。これは入力のパディングによるわずかな差であり、エクスポートが原因ではありません。)

一致を確認したら、出荷前に対象デバイス上でyolo benchmarkを使って速度を測定し、実際の処理速度を確認してください。

対象環境に適した形式を選ぶ#

Ultralytics Platformのライフサイクル: SAMのスマートアノテーションで注釈を付け、クラウドGPUで学習し、統合パートナーのロゴとともに世界各地のリージョンへデプロイします

目標形式説明
汎用性の高いデフォルト: Linux、Windows、Mac上のサーバーとデスクトップonnxCPUまたはGPU上のONNX Runtime。検証に最も手早く使えるエクスポート形式です
NVIDIA GPUとJetsonengine (TensorRT)NVIDIAで最速です。デバイス上でエクスポートしてください。TensorRTで最適化するをご覧ください
Intel CPUとiGPUopenvinoIntelカーネルによる実際のCPU高速化です。CPUでのOpenVINOをご覧ください
iPhone、iPad、Macのアプリcoremlネイティブ対応で、Apple Neural Engineを使用します
Androidおよびその他のモバイル・組み込みデバイスlitertモバイルではINT8を推奨します
Snapdragon NPUqnnHexagon HTPアクセラレーション。デフォルトではINT8の重みと16ビットのアクティベーションを使用します。nameでHTPアーキテクチャを選択してください
WebブラウザーONNX Runtime Webでonnxを使用します小型モデルが現実的な選択肢です: nとs
from ultralytics import YOLO

model = YOLO("runs/detect/pills_v1/weights/best.pt")

model.export(format="onnx")  # クロスプラットフォーム: ONNX Runtime
model.export(format="openvino")  # Intel CPU / iGPU
model.export(format="engine", quantize=16)  # NVIDIA TensorRT、FP16(対象GPUで実行)
model.export(format="coreml")  # Apple iOS / macOS
model.export(format="litert", quantize=8, data="my_dataset/data.yaml")  # Android / エッジ、INT8
model.export(format="qnn", name="73", data="my_dataset/data.yaml")  # Qualcomm Snapdragon NPU(HTP v73)。独自のデータでキャリブレーションしてください

各エクスポートは重みファイルと同じ場所にbest.onnx、best_openvino_model/、best.engineなどを書き込みます。最終的に別の形式を使う場合でも、まずはONNXを試してください。検証が最も手早く、他のいくつかのツールチェーンへの入力にもなるためです。デプロイオプションガイドでは各形式を比較し、デプロイ先の選択では選択の手順を説明します。

モデルの量子化では、精度と引き換えにサイズと速度を改善します。FP16(quantize=16)では、精度をほぼ維持したままファイルサイズを半分にできます。INT8(quantize=8)はさらに小さく高速になりますが、キャリブレーション画像が必要です。これは、エクスポート時に値の範囲を決めるために処理する代表的なフレームです。Ultralyticsでは少なくとも300枚を推奨しています。INT8モデルは、デプロイ前に必ず検証してください。精度の低下は、モデルやキャリブレーションセットによって、ごくわずかな場合も大きい場合もあります。

次の間違いに注意する#

異なる入力を比較する

症状: .pt モデルは Frame_144.jpg 上で錠剤を35個検出する一方、ONNXファイルでは25個しか検出されず、エクスポートに問題があるように見えます。原因: PyTorchの推論では、各画像をストライドに合わせた最小の長方形(この16:9フレームでは192×320)にパディングします。一方、静的ONNXモデルは常に320×320の正方形を入力として受け取ります。入力が異なれば、信頼度の低い検出結果も異なります。対処: parity.py の例のように、比較時は .pt モデルに rect=False を渡してください。

静的エクスポートでは指定したimgszが反映されない

症状: best.onnx に imgsz=640 を渡しても、ログには依然として 320x320 と表示されます。原因: 静的エクスポートでは、エクスポート時に設定した入力サイズが1つだけ使われます。対処: 実行時のサイズ(imgsz=640)でエクスポートするか、dynamic=True を指定してエクスポートしてください。

TensorRTエンジンはデバイス固有

A100でビルドした .engine はJetson Orinでは動作せず、TensorRTをアップグレードすると使えなくなる場合もあります。実行先のデバイスで、実際に使用するTensorRTバージョンを使ってエクスポートしてください。ONNXには移植性がありますが、エンジンにはありません。

指定しない場合、INT8のキャリブレーションにはCOCO8が使われる

INT8エクスポート時に data を省略すると、Ultralyticsは警告を出してから、デフォルトのCOCO8サンプルでキャリブレーションします。錠剤とはまったく似ていない8枚の画像が使われます。独自のデータを渡してください: model.export(format="litert", quantize=8, data="my_dataset/data.yaml")。

出荷準備が整いました#

学習済みのbest.pt、ベースラインと比較できる検証結果、実行環境向けにエクスポートしたファイル、そしてエクスポート結果が元のモデルと一致することを示す証拠が揃いました。これで、データ、学習、検証、エクスポート、デプロイという一連の流れが完了です。プロダクションチームはこの流れを定期的に実行します。Ultralytics YOLO in Productionでは、検証済みのエクスポート結果を起点に、最適化されたランタイム、トラッキングパイプライン、マルチストリーム配信、モニタリングについて学びます。

試してみる

pills_v1/weights/best.ptをONNXにエクスポートし、parity.pyとval_export.pyを実行してください。rect=Falseを指定せずにparity.pyを再実行し、.ptの件数がどう変わるか記録してください。次の4項目を提出してください。一致した検出数、ボックスの最大差、2つのmAP50-95値、実際のデプロイ先で必要な形式とその理由を述べた1行。

コミット
git add -A && git commit -m "feat(deploy): exported best.pt to onnx for production runtime"
完了条件
以下のすべてを満たすと、レッスンは完了です。
  • runs/detect/pills_v1/weights/best.onnxが存在し、YOLO()を通じて推論を実行できます。

  • rect=Falseでは検出数が一致し、ボックスの最大差は1 px未満です。

  • 条件を揃えた場合、ONNXと.ptの検証mAP50-95は一致し、対象形式とその理由も説明できています。

解答を表示
from ultralytics import YOLO

# Train
model = YOLO("yolo26n.pt")
model.train(data="my_dataset/data.yaml", epochs=10, imgsz=320, name="pills_e2e")

# Validate
metrics = model.val()
print(f"mAP50-95 = {metrics.box.map:.3f}")  # 0.659

# Export
model.export(format="onnx")
parity.py:      pt 25 pills, onnx 25 pills, max box difference 0.0002 px
without rect:   pt 35 pills (192x320 input) vs onnx 25 (320x320): input mismatch, not an export bug
val_export.py:  .pt 0.6570, .onnx 0.6570
Target:         Intel laptop CPU -> openvino, for faster CPU inference than ONNX Runtime
次のステップ

コースを修了しました。最終クイズに回答してTrain your first YOLO modelの修了証を取得し、続けてUltralytics YOLO in Productionに進んでください。