Ultralytics YOLO27: ウェイトリストに登録する。
Get Started
検出の先へ: セグメンテーション、Pose、OBB、分類·分類、組み合わせ、出荷·レッスン 10/10
レッスン中級

すべてのタスクを評価してデプロイする

デプロイ時の画像サイズで、各タスク固有の指標を合否判定に使います。1つのループですべてのタスクを検証し、予測結果を確認したうえで、すべてのタスクをONNXにエクスポートします。

正解の定義はタスクごとに異なります。ピクセルの重なり、キーポイントの類似度、回転ボックスのIoU、top-1の正解、深度比率などです。検出用のチェックリストを使い回すチームは、ボックスのmAPを基準にセグメンテーションモデルを判定したり、製品の対象ではないボックスを基準に姿勢推定モデルを判定したりして、リリースしてしまいます。また、合格基準を満たしたモデルでも、エクスポート後に問題が起きることがあります。このレッスンでは、同じ姿勢推定の重みでも入力サイズによって検出人数が5人から3人に変わり、深度モデルの距離はほぼ2倍になります。

成果

各タスクモデルについて、合否判定に使う指標と imgsz を記載したリリース表を作成します。さらに、それぞれをONNXにエクスポートして検証し、適切なタスクとして再読み込みでき、対象ドメインの画像で正しく予測できることを確認します。

短期集中コース
すでに使い方をご存じの方は、こちらをご覧ください。
  1. セグメンテーションはマスクmAP50-95、セマンティックセグメンテーションはmIoU、姿勢推定はpose mAP50-95、OBBはOBB mAP50-95、分類はtop-1、深度推定はδ1を基準にします。

  2. タスクのキーを指定して metrics.results_dict から主要な数値を読み取り、各数値の横に imgsz を記録します。

  3. 検証時と同じサイズで model.export(format="onnx", imgsz=...) を使ってエクスポートします。

  4. YOLO("model.onnx") を使ってエクスポートしたモデルを再読み込みし、リリース前にモデルの対象ドメインの画像で1回予測します。

実践的

タスクごとに1つの合否基準#

タスク判定基準results_dict のキーPython属性評価指標
セグメンテーションマスクmAP50-95metrics/mAP50-95(M)metrics.seg.mapインスタンスごとのピクセルIoU
セマンティックセグメンテーションmIoU(クラスごとのIoUを含む)metrics/mIoUmetrics.miouクラスごとのピクセルIoU
姿勢推定pose mAP50-95metrics/mAP50-95(P)metrics.pose.mapOKS
OBBOBB mAP50-95metrics/mAP50-95(B)metrics.box.map回転ボックスのIoU
分類top-1精度metrics/accuracy_top1metrics.top1top-1クラスの正解
深度推定δ1(AbsRelを含む)metrics/delta1metrics.delta1真の深度の1.25倍以内に収まるピクセルの割合

パフォーマンス指標ガイドでは、各スコアについて説明しています。セグメンテーションと姿勢推定の実行では、ボックスの指標も出力されます。ボックスとマスクの差から輪郭の品質を診断できるため、診断用として確認しますが、製品の指標ではありません。しきい値のスイープや混同行列など、検出に特化した読み解き方については、検証と診断の内容を応用できます。

1つのループですべてのタスクを検証する#

Valモードでは、タスクに合ったデータセットと組み合わせて、あらゆるタスクの重みを使用できます。そのため、1つのループでリリース表の数値をまとめて取得できます。

from ultralytics import YOLO

runs = {
    "yolo26n-seg.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)"),
    "yolo26n-sem.pt": ("cityscapes8.yaml", "metrics/mIoU"),
    "yolo26n-pose.pt": ("coco8-pose.yaml", "metrics/mAP50-95(P)"),
    "yolo26n-obb.pt": ("dota8.yaml", "metrics/mAP50-95(B)"),
    "yolo26n-depth.pt": ("depth8.yaml", "metrics/delta1"),
}
for weights, (data, key) in runs.items():
    metrics = YOLO(weights).val(data=data, device="cpu", plots=False, verbose=False)
    print(f"{weights:17s} {key:22s} {metrics.results_dict[key]:.3f}")
yolo26n-seg.pt    metrics/mAP50-95(M)    0.538
yolo26n-sem.pt    metrics/mIoU           0.610
yolo26n-pose.pt   metrics/mAP50-95(P)    0.419
yolo26n-obb.pt    metrics/mAP50-95(B)    0.857
yolo26n-depth.pt  metrics/delta1         0.377

imgsz を明示的に指定しない場合、各モデルは学習時のサイズで検証されます。セグメンテーションと姿勢推定は640、深度推定は768、セマンティックセグメンテーションとOBBは1024です。これらの事前学習済みモデルの数値は、コース前半で学習した320ピクセルのモデルより高くなっています。これは学習による差と解像度による差の両方が影響しています。検証画像は4枚だけなので、ここでの数値はすべてスモークテストです。たとえば、深度推定タスクのページでは、NYUベンチマーク全体に対するδ1が報告されています。分類は意図的に対象外としています。分類器のレッスンと同様に、ファインチューニングした分類器は専用フォルダーを使って検証してください。

解像度も評価指標の一部です

同じ重みでも、異なるimgszではスコアが変わります。すべての数値と合わせてimgszを記録し、デプロイ時に使用するサイズで検証してください。異なるサイズで測定した数値を比較しないでください。

すべてのタスクをエクスポートする#

各タスクは、同じエクスポートモードの呼び出しでONNXにエクスポートできます。タスクはモデルのメタデータに保存されるため、YOLO("model.onnx") が適切な後処理を適用します。実行環境の選択、同等性チェック、TensorRTやOpenVINOのチューニングについては、ONNXにエクスポートして同等性を検証するで説明しています。このループでは、すべてのタスクでエクスポートと再読み込みが問題なく完了することを確認します。

from ultralytics import YOLO

for weights in ["yolo26n-seg.pt", "yolo26n-sem.pt", "yolo26n-pose.pt", "yolo26n-obb.pt", "yolo26n-cls.pt", "yolo26n-depth.pt"]:
    onnx_path = YOLO(weights).export(format="onnx", imgsz=320)
    onnx_model = YOLO(onnx_path)  # task comes from the ONNX metadata
    result = onnx_model("https://ultralytics.com/images/bus.jpg", imgsz=320, verbose=False)[0]
    print(f"{onnx_model.task:9s} {result.verbose()}")
segment   4 persons, 1 bus,
semantic
pose      3 persons,
obb       (no detections),
classify  minibus 0.38, police_van 0.21, trolleybus 0.05, amphibian 0.05, bullet_train 0.03,
depth     depth 4.67-26.91m,

すべてのエクスポートを適切なタスクとして再読み込みできました。特に次の3つの結果は、詳しく確認する必要があります。

  • 320ピクセルでは姿勢推定モデルが3人を検出しました。640ピクセルのPyTorch実行では5人を検出しました。
  • 深度推定モデルはシーンの距離を4.7~26.9 mと判定しました。同じ重みをネイティブサイズの768ピクセルで使った場合は2.1~14.9 mと判定しました。
  • OBBモデルは街路の写真で何も検出しませんでした。空撮画像向けモデルとして正しい動作であり、エクスポートの不具合ではありません。

imgsz=320 で実行したPyTorchの姿勢推定と深度推定の数値はONNXと一致しているため、どちらもエクスポートの不具合ではありません。入力サイズによって結果が変わりました。検証した imgsz でエクスポートしてください。セマンティックセグメンテーションにはオブジェクトごとの要約行がないため、代わりに result.semantic_mask を確認します。

各エクスポートを適切なドメインでスモークテストする

エクスポートが壊れていると判断したり、出荷したりする前に、学習時と同様の画像を使って各エクスポート済みモデルで1回推論します。COCOモデルには道路シーン、OBBには航空画像タイル、深度推定には適切なスケールの屋内または道路シーンを使用します。

独自の後処理を実装する場合は、エクスポートログにある imgsz=320 でのONNXの生出力は次のとおりです。

タスクONNXの出力形状内容
セグメンテーション(1, 116, 2100) と (1, 32, 80, 80)ボックス + 80個のクラススコア + 32個のマスク係数、マスクプロトタイプ
セマンティックセグメンテーション(1, 320, 320)クラスマップ。argmaxはすでに計算グラフに含まれています
姿勢推定(1, 56, 2100)ボックス + 1個のスコア + 17 × 3個のキーポイント値
OBB(1, 20, 2100)ボックス + 15個のクラススコア + 1個の角度
分類(1, 1000)クラス確率
深度推定(1, 1, 320, 320)ピクセルごとの深度(メートル単位)

Ultralytics Platformでは、モデルページにタスク固有の指標(セグメンテーションモデルの場合はマスクmAP)が表示され、その下のエクスポートタブから同じ形式でエクスポートできます。

セグメンテーションモデルのUltralytics Platformモデルページ。マスクmAP50、mAP50-95、適合率、再現率のカードの下に、TorchScript、ONNX、OpenVINO、TensorRT、CoreMLを一覧表示するエクスポートタブがあります

ONNXは中間形式として機能します。エクスポートした1つのファイルをONNX Runtimeで実行したり、ほかのランタイム向けに変換したりできます。

中間形式としてのONNX:PyTorch、TensorFlow、KerasなどのフレームワークのモデルをONNXにエクスポートし、ONNX Runtimeまたは別のフレームワークで読み込めます

リリースチェックリスト#

  • 上の表に記載した合否判定用の指標が、ホールドアウトセットでデプロイ時の imgsz において目標を満たしています。
  • エクスポートしたモデルを、想定される task として再読み込みでき、固定した画像セットでPyTorchの予測結果と一致します。
  • タスクごとのコードパスが空の結果を処理します。masks is None、キーポイントが0個、OBBが0個の場合も対象です。
  • 可観測性とドリフトで説明しているように、下流の数値(面積、角度、距離、クラス確率)を記録し、変化を監視できるようにします。

合否基準を満たさない場合、「データに戻る」とは通常、次の3つの調整手段のいずれかを指します。

mAPを改善する3つの方法:データ品質、モデルの最適化、アノテーションプロセス

まずデータ品質とアノテーションプロセスを改善します。レッスン2と6のラベルチェックから始めるのが最も手軽です。データがクリーンな場合にのみ、モデルを変更します。

試してみる

このコースで学習したタスクから2つ選びます。それぞれについて、デプロイ時の imgsz における合否判定指標を記載したリリース表の行を作成します。学習済みの best.pt をそのサイズでONNXにエクスポートして再読み込みし、対象ドメインの画像1枚で妥当な予測をすることを確認します。

完了条件
以下のすべてを満たすと、レッスンは完了です。
  • リリース表には、両モデルについて、適切な合否判定指標、その値、imgsz が記載されています。

  • 両モデルがONNXにエクスポートされ、想定される task として再読み込みできました。

  • それぞれのエクスポートモデルが、対象ドメインの画像で妥当な予測をしました。

解答を表示
from ultralytics import YOLO

checks = {
    "runs/segment/train/weights/best.pt": ("coco8-seg.yaml", "metrics/mAP50-95(M)", "https://ultralytics.com/images/bus.jpg"),
    "runs/obb/train/weights/best.pt": ("dota8.yaml", "metrics/mAP50-95(B)", "https://ultralytics.com/images/boats.jpg"),
}
for weights, (data, key, image) in checks.items():
    model = YOLO(weights)
    gate = model.val(data=data, imgsz=320, plots=False, verbose=False).results_dict[key]
    onnx_model = YOLO(model.export(format="onnx", imgsz=320))
    result = onnx_model(image, imgsz=320, verbose=False)[0]
    print(f"{onnx_model.task:8s} {key} @320 = {gate:.3f} | ONNX: {result.verbose()}")

runs/... のパスを、学習実行時に表示されたフォルダー(Results saved to ...)に合わせて変更します。レッスン2と7の1エポックの学習では、次のようになります。

segment  metrics/mAP50-95(M) @320 = 0.377 | ONNX: 4 persons, 1 bus,
obb      metrics/mAP50-95(B) @320 = 0.832 | ONNX: 185 ships, 3 harbors,
モデルゲート指標値画像サイズONNX
セグメンテーションマスクmAP50-950.377320segment として再読み込みされ、バス1台と人物4人を検出します
OBBOBB mAP50-950.832320obb として再読み込みされ、船185隻と港3か所を検出します

各チェックには、モデルの対象ドメインの画像を使います。OBBモデルには街路の画像ではなく、空撮した港の写真を使います。どちらもエクスポートチェックには合格していますが、どちらのモデルもリリースできる状態ではありません。検証画像4枚での1エポックの学習はスモークテストであり、合否判定ではないためです。

次のステップ

コースの試験を受けて修了証を取得し、続いて Ultralytics YOLO in Production に進みましょう。最適化されたランタイム、トラッキング、モニタリングを使って、これらのモデルをデプロイします。