Ultralytics YOLO26におけるエンドツーエンド検出の理解#
YOLOv8 や YOLO11 などの以前のモデルから YOLO26 にアップグレードする場合、気付く最大の違いの 1 つは、Non-Maximum Suppression (NMS) の削除です。従来の YOLO モデルは、最終的な検出に絞り込むために独立した NMS 後処理ステップを必要とする数千の重なり合う予測を生成します。これにより、レイテンシが増加し、エクスポートグラフが複雑になり、さまざまなハードウェアプラットフォーム間で一貫性のない動作をする可能性があります。
YOLO26は異なるアプローチを採用しています。外部のフィルタリングを必要とせず、モデルから直接最終的な検出結果を出力します。これは エンドツーエンドの物体検出 として知られており、すべてのYOLO26モデルでデフォルトで有効になっています。その結果、よりシンプルなデプロイメントパイプライン、低レイテンシー、および CPUでの推論が最大43%高速化 されます。
本ガイドでは、何が変更されたのか、コードの更新が必要かどうか、エンドツーエンド推論をサポートするエクスポートフォーマット、および古いYOLOモデルからスムーズに移行する方法について解説します。
このアーキテクチャの変更の背景にある動機の詳細については、YOLO26がNMSを削除する理由に関するUltralyticsブログ記事をご覧ください。
- Ultralytics APIまたはCLIを使用していますか? 変更は不要です。モデル名を
yolo26n.ptに変更するだけです。 - カスタム推論コード(ONNX Runtime、TensorRT など)を使用していますか? 後処理を更新してください。検出出力は、NMS なしで
xyxy形式の(N, 300, 6)になりました。その他のタスクでは、追加データ(マスク係数、キーポイント、または角度)が追加されます。 - エクスポートしていますか? ほとんどのフォーマットはエンドツーエンドの出力をネイティブでサポートしています。ただし、一部のフォーマット(NCNN、RKNN、PaddlePaddle、ExecuTorch、IMX、Edge TPU、QNN)は、サポートされていないオペレーターの制約(例:
torch.topk)のため、自動的に従来の出力にフォールバックします。Hailo HEFワークフローは、Hailo固有のスクリプトを使用してONNXからコンパイルされるため、モデルの検出ヘッドとNMS設定を確認してください。
エンドツーエンド検出の仕組み#
YOLO26は、トレーニング時に デュアルヘッドアーキテクチャ を使用します。両方のヘッドは同じバックボーンとネックを共有しますが、異なる方法で出力を生成します。
| ヘッド | 目的 | 検出出力 | 後処理 |
|---|---|---|---|
| One-to-One(デフォルト) | エンドツーエンド推論 | (N, 300, 6) | 信頼度しきい値のみ |
| One-to-Many | 従来のYOLO出力 | (N, nc + 4, 8400) | NMSが必要 |
上記の形状は検出用です。その他のタスクでは、1対1の出力に検出ごとの追加データが拡張されます。
| タスク | エンドツーエンド出力 | 追加データ |
|---|---|---|
| Detection | (N, 300, 6) | — |
| Instance Segmentation | (N, 300, 6 + nm) + プロト (N, nm, H, W) | nm マスク係数(デフォルト32) |
| ポーズ | (N, 300, 57) | 17 キーポイント × 3 (x, y, 可視性) |
| OBB | (N, 300, 7) | 回転角度 |
トレーニング中、両方のヘッドが同時に実行されます。1対多のヘッドはより豊富な学習シグナルを提供し、1対1のヘッドはクリーンで重複のない予測を生成することを学びます。推論およびエクスポート中、デフォルトでは 1対1のヘッド のみがアクティブになり、画像ごとに最大300個の検出を [x1, y1, x2, y2, confidence, class_id] 形式で生成します。
model.fuse() を呼び出すと、推論を高速化するために Conv + BatchNorm レイヤーが折り畳まれ、エンドツーエンドモデルでは1対多のヘッドも削除されるため、モデルサイズとFLOPsが削減されます。デュアルヘッドアーキテクチャの詳細については、YOLO26モデルページをご覧ください。
コードを変更する必要はありますか?#
Ultralytics Python APIまたはCLIを使用する場合#
変更は必要ありません。 標準の Ultralytics Python API または CLI を使用している場合、すべてが自動的に機能します。予測、検証、およびエクスポートはすべて、エンドツーエンドモデルをそのまま処理します。
from ultralytics import YOLO
# Load a YOLO26 model
model = YOLO("yolo26n.pt")
# Predict — no NMS step, no code changes
results = model.predict("image.jpg")カスタム推論コードを使用する場合#
はい、出力形式が異なります。 YOLOv8 または YOLO11 用のカスタム後処理ロジックを書いた場合(例えば、ONNX Runtime または TensorRT で推論を実行する場合など)、新しい出力形状を処理するように更新する必要があります:
| YOLOv8 / YOLO11 | YOLO26(エンドツーエンド) | |
|---|---|---|
| 検出出力 | (N, nc + 4, 8400) | (N, 300, 6) |
| ボックス形式 | xywh (中心x、中心y、幅、高さ) | xyxy (左上x、左上y、右下x、右下y) |
| レイアウト | アンカーごとのボックス座標 + クラススコア | [x1, y1, x2, y2, conf, class_id] |
| NMSが必要 | はい | いいえ |
| 後処理 | NMS + 信頼度フィルタ | 信頼度フィルタのみ |
セグメンテーション、ポーズ、および OBB タスクの場合、YOLO26は各検出にタスク固有のデータを追加します。出力形状の表をご覧ください。
ここで N はバッチサイズ、nc はクラスの数です(例:COCOの場合は80)。
エンドツーエンドモデルを使用すると、後処理がはるかに簡単になります(例:ONNX Runtimeを使用する場合):
import onnxruntime as ort
# Load and run the exported end-to-end model
session = ort.InferenceSession("yolo26n.onnx")
output = session.run(None, {session.get_inputs()[0].name: input_tensor})
# End-to-end output: (batch, 300, 6) → [x1, y1, x2, y2, confidence, class_id]
detections = output[0][0] # first image in batch
detections = detections[detections[:, 4] > conf_threshold] # confidence filter — that's it!One-to-Manyヘッドへの切り替え#
従来のYOLO出力形式が必要な場合(既存のNMSベースの後処理コードを再利用するためなど)、利用可能な場合は end2end=False を設定することで1対多のヘッドに切り替えることができます:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
# Prediction with NMS (traditional behavior)
results = model.predict("image.jpg", end2end=False)
# Validation with NMS
metrics = model.val(data="coco.yaml", end2end=False)
# Export without end-to-end
model.export(format="onnx", end2end=False)エクスポートフォーマットの互換性#
ほとんどのエクスポートフォーマットは、ONNX、TensorRT、CoreML、OpenVINO、LiteRT、およびMNNを含め、エンドツーエンド推論をそのままサポートしています。
以下のフォーマットはエンドツーエンドを サポートしておらず、自動的に1対多のヘッドにフォールバックします:NCNN、RKNN、PaddlePaddle、ExecuTorch、IMX、Edge TPU、およびQualcomm QNN。
Hailo HEFの場合、コンパイルステップはONNXエクスポートの後に model.export(format=...) の外側で行われます。正確な検出モデルに一致するHailo DFCログ、.alls モデルスクリプト、およびNMS JSONを使用してください。エンドツーエンドのYOLO26グラフがHailoツールチェーンでサポートされていない場合は、end2end=False を指定してONNXモデルをエクスポートし、従来の検出ヘッドをコンパイルしてください。
TensorRTはエンドツーエンドをサポートしていますが、JetPack 6上のTensorRT 10.3.0で quantize=8 を指定してエクスポートする場合、自動的に無効になります。
精度と速度のトレードオフ#
エンドツーエンド検出は、精度への影響を最小限に抑えながら、デプロイメントにおいて大きなメリットをもたらします:
| メトリクス | エンドツーエンド (デフォルト) | 1対多 + NMS(end2end=False) |
|---|---|---|
| CPU推論速度 | 最大43%高速化 | ベースライン |
| mAPへの影響 | ~0.5 mAP低下 | YOLO11と同等または上回る |
| 後処理 | 信頼度フィルタのみ | フルNMSパイプライン |
| デプロイメントの複雑さ | 最小限 | NMSの実装が必要 |
ほとんどの現実世界のアプリケーションにおいて、~0.5の mAP の差は、速度と簡便性の向上を考慮するとごくわずかです。最大の精度が最優先事項である場合は、いつでも end2end=False を使用して1対多のヘッドにフォールバックできます。
すべてのモデルサイズ(n、s、m、l、x)の詳細なベンチマークについては、YOLO26のパフォーマンス指標をご覧ください。
YOLOv8またはYOLO11からの移行#
既存のプロジェクトをYOLO26にアップグレードする場合、スムーズな移行のために以下のチェックリストを確認してください。
- Ultralytics API / CLI ユーザー: 変更は不要です。モデル名を
yolo26n.pt(またはyolo26n-seg.pt、yolo26n-pose.pt、yolo26n-obb.pt)に更新するだけです。 - カスタム後処理コード: 新しい出力形状(検出用の
(N, 300, 6)、およびセグメンテーション、ポーズ、OBBのタスク固有データ)を処理するように更新してください。また、ボックスの形式がxywhからxyxyに変更されていることにも注意してください。 - エクスポートパイプライン: ターゲットフォーマットのフォーマット互換性セクションを確認してください。
- TensorRT + INT8: JetPack 6では、TensorRT 10.3.0は
quantize=8でエンドツーエンドを自動的に無効にします。エンドツーエンドを維持するには、別のTensorRTバージョンを使用してください。 - FP16エクスポート: すべての出力をFP16にする必要がある場合は、
end2end=Falseでエクスポートしてください。output0がFP32のままになる理由をご覧ください。 - iOS / CoreML: エンドツーエンドが完全にサポートされています。Xcode プレビューのサポートが必要な場合は、
end2end=Falseとnms=Trueを使用してください。 - エッジデバイス(NCNN, RKNN): これらのフォーマットは自動的にOne-to-Manyへフォールバックするため、デバイス上のパイプラインにNMSを含めてください。
結論#
エンドツーエンド検出はYOLO26のデフォルトであり、Ultralytics Python API または CLI を使用している場合はコードの変更は必要ありません。カスタム後処理パイプラインのみが、新しい (N, 300, 6) の出力を読み取り、NMSステップを削除するように更新する必要があります(1対多の出力にフォールバックするNCNNやRKNNなどのエクスポートフォーマットを除き、これらは引き続きデバイス上でNMSが必要です)。すべてのモデルサイズにわたる詳細な速度と精度のベンチマークについてはYOLO26モデルページを、エクスポートオプションとフォーマットの完全なセットについてはエクスポートモードのドキュメントをご覧ください。
よくある質問 (FAQ)#
end2end=Trueとnms=Trueを同時に使用できますか?#
いいえ。これらのオプションは排他的です。export 時にエンドツーエンドモデルで nms=True を設定した場合、警告とともに自動的に nms=False に強制されます。エンドツーエンドのヘッドは重複フィルタリングを内部ですでに処理するため、外部の NMS は不要です。
ただし、end2end=False と nms=True を組み合わせることは有効な設定です。これにより、従来のNMSがエクスポートグラフに組み込まれます。これは、検出モデルで直接Xcodeのプレビュー機能を使用できるため、CoreMLのエクスポートに役立ちます。
エンドツーエンドモデルにおいて、max_detパラメータは何を制御しますか?#
max_det パラメータ(デフォルト: 300)は、画像ごとに返される検出の最大数を設定します。推論時またはエクスポート時に調整できます:
model.predict("image.jpg", max_det=100) # fewer detections
model.export(format="onnx", max_det=500) # more detections for dense scenesデフォルトのYOLO26チェックポイントは max_det=300 でトレーニングされていることに注意してください。この値を増やすことは可能ですが、1対のヘッドは最大300個のクリーンな検出を生成するようにトレーニング中に最適化されているため、その制限を超える検出は品質が低下する可能性があります。画像ごとに300個以上の検出が必要な場合は、より高い max_det の値で再トレーニングすることを検討してください。
エクスポートしたONNXモデルの出力が (1, 300, 6) ですが、これは正しいですか?#
はい、それが検出の期待されるエンドツーエンドの出力形式です:バッチサイズが1のバッチサイズ、最大300個の検出し、それぞれが [x1, y1, x2, y2, confidence, class_id] の6つの値を持ちます。信頼度閾値でフィルタリングするだけで完了です。NMSは必要ありません。
その他のタスクでは、出力形状が異なります。
| タスク | 出力形状 | 説明 |
|---|---|---|
| 検出 | (1, 300, 6) | [x1, y1, x2, y2, conf, class_id] |
| セグメンテーション | (1, 300, 38) + (1, 32, 160, 160) | 6つのボックス値 + 32個のマスク係数、およびプロトタイプマスクテンソル |
| Pose(姿勢推定) | (1, 300, 57) | 6つのボックス値 + 17個のキーポイント × 3 (x, y, 可視性) |
| OBB(指向性バウンディングボックス) | (1, 300, 7) | 6つのボックス値 + 1つの回転角度 |
エクスポートしたモデルがエンドツーエンドかどうかを確認するにはどうすればよいですか?#
Ultralytics Python APIを使用するか、エクスポートされたONNXモデルのメタデータを直接確認することで調べることができます。
from ultralytics import YOLO
model = YOLO("yolo26n.onnx")
model.predict(verbose=False) # run predict to setup predictor first
print(model.predictor.model.end2end) # True if end-to-end is enabledまたは、出力形状を確認します。エンドツーエンドの検出モデルは (1, 300, 6) を出力し、従来のモデルは (1, nc + 4, 8400) を出力します。その他のタスクの形状については、出力形状のFAQをご覧ください。
インスタンスセグメンテーション、ポーズ推定、OBBタスクでエンドツーエンドはサポートされていますか?#
はい。YOLO26の検出スタイルのタスクバリアント(検出、インスタンスセグメンテーション、姿勢推定、および指向性物体検出(OBB))は、デフォルトでエンドツーエンド推論をサポートしています。end2end=False のフォールバックも、これらのタスク全体で利用できます。
各タスクは、ベースとなる検出出力にタスク固有のデータを拡張します。
| タスク | モデル | エンドツーエンド出力 |
|---|---|---|
| 検出 | yolo26n.pt | (N, 300, 6) |
| インスタンスセグメンテーション | yolo26n-seg.pt | (N, 300, 38) + プロト (N, 32, 160, 160) |
| Pose(姿勢推定) | yolo26n-pose.pt | (N, 300, 57) |
| OBB(指向性バウンディングボックス) | yolo26n-obb.pt | (N, 300, 7) |