しきい値とフィルタリング
どの予測を残すかはconf、iou、max_det、classesという4つの引数で決まります。集合予測器は固定されたクエリ集合をデコードしてNMSを実行しないため、すべてのファミリーに適用される引数はこのうち2つだけです。
4つの引数
| 引数 | デフォルト | 適用対象 |
|---|---|---|
conf | 0.25 | すべてのファミリー |
iou | 0.45 | Non-Maximum Suppressionを実行するファミリー |
max_det | 300 | すべてのファミリー |
classes | None | すべてのファミリー |
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") result = model( SAMPLE_IMAGE, conf=0.25, # このスコア以上の予測を残す iou=0.45, # NMSを実行する場合の重なりしきい値 max_det=300, # 画像ごとの上限 classes=None, # またはクラスIDのリスト)print(len(result.boxes))from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") for conf in (0.1, 0.25, 0.5, 0.75): result = model(SAMPLE_IMAGE, conf=conf) print(conf, len(result.boxes))libreyolo predict model=LibreYOLO9s.pt conf=0.4 iou=0.5 max_det=100 \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgこのうち2つはすべてに適用され、2つはそうではありません。パラメーター調整を始める前に知っておくべき最も重要な点です。
検証では意図的に異なるデフォルト値を使います。val()はconf=0.001とiou=0.6で実行されます。平均適合率は適合率と再現率の完全な曲線に対して計算され、0.25で打ち切ると曲線が途中で切れるためです。
conf
confは、それを下回るスコアの予測を破棄するしきい値です。NMSをまったく実行しないものも含め、すべてのファミリーに適用されます。検出数が多すぎる、または少なすぎる場合に最初に調整する項目です。
デフォルトの0.25は画像を目視する用途に適しています。下流システムへ渡す場合は通常より高い値が必要で、精度測定にははるかに低い値が必要です。
物体検出の検証は、IoU 0.50でのF1に基づくmetrics/best_confとクラス別のしきい値を公開します。デプロイ時のしきい値を決めるための、測定に基づく出発点として使ってください。検証を参照してください。セグメンテーションはこれらのキーを公開しません。
iou
iouは、同じクラスに属する2つのボックスが重なったときに、Non-Maximum Suppressionが低スコア側を削除する重なりのしきい値です。ファミリーが抑制処理を実行する場合だけ意味があります。
集合予測器は固定数のクエリをデコードし、スコア上位のものを選びます。重複は後処理ではなくアーキテクチャ内部で学習時に抑えられるため、調整できるしきい値はありません。次のファミリーはAPI互換性のためiouを受け付けますが無視します。
CenterNet、DEIM、DETR、Deformable DETR、D-FINE、DINO-DETR、EdgeCrafter、Faster R-CNN、LW-DETR、Mask R-CNN、RF-DETR、RT-DETR、エンドツーエンドYOLOv9ヘッドです。これらのデコーダーを基にしたバリアントも同じ動作を継承します。
from libreyolo import LibreYOLO, SAMPLE_IMAGE # RF-DETRは固定クエリ集合をデコードするためここではiouを変えても効果がないmodel = LibreYOLO("LibreRFDETRs.pt") loose = model(SAMPLE_IMAGE, iou=0.9)tight = model(SAMPLE_IMAGE, iou=0.1) # どちらも同じ件数となる 有効な制御はconfとmax_detprint(len(loose.boxes), len(tight.boxes))多くのファミリーでは後処理のdocstringにこの点が記載されていますが、実行時には警告が出ません。そのため、RF-DETRでiouを変えて測定してもエラーではなく平坦な結果になります。Faster R-CNNとMask R-CNNは少し異なり、どちらもモデル内部ですでにNMSを実行しています。その固定されたアップストリームのしきい値をiouで変更する方法には対応していません。
YOLOv1からYOLOv4、YOLOv7、YOLOv9、YOLOX、YOLO-NAS、RTMDet、PicoDet、EfficientDet、FCOS、RetinaNet、SSDではiouが使用されます。
推論時の次の3つのオプションは、いずれもモデル処理後のボックスに作用するため、集合予測器でもiouが影響します。
tiling=Trueは、重なり合うタイルをiouでクラス別NMSにより調整します。augment=Trueは、反転したビューをiouでクラス別NMSにより統合します。agnostic_nms=Trueは、後述するとおり、重なり合うボックスをiouでクラスをまたいで抑制します。
最初の2つは推論パフォーマンスで解説しています。
オープンボキャブラリー検出器には独自の規則があります。プロセッサーがNMSを実行するファミリーは固有のデフォルトしきい値を宣言し、iouを適用します。OMDet-Turboがこれに該当します。抑制をまったく行わないGrounding DINO、OWLv2、OV-DEIMは、iouを渡すと警告します。この警告を出すのはライブラリ内でこれらだけです。
max_det
max_detは1枚の画像に対して返す予測数の上限です。すべてに適用されますが、その仕組みは異なります。NMSを使うファミリーは抑制後に切り詰め、集合予測器はtop-k選択のサイズとして使用します。
アップストリームの参照設定に従い、指定値より低い上限を適用するファミリーもあります。SSDは200、FCOSは固有の画像ごとの検出上限に制限されます。それ以上にmax_detを増やしても効果はありません。
max_detがファミリーごとではなく中央で適用されるのは、タイルを調整した後に統合済みリストを切り詰めるタイル推論と、フィルタリングまたは抑制の後に切り詰めるclassesまたはagnostic_nms=True付きの呼び出しの2つの場合です。
クラスのフィルタリング
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") # クラスIDはmodel.namesのインデックス COCOでは0がpersonresult = model(SAMPLE_IMAGE, classes=[0]) print({result.names[int(c)] for c in result.boxes.cls.tolist()})from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt")result = model(SAMPLE_IMAGE) wanted = {"person", "backpack"}ids = [i for i, name in result.names.items() if name in wanted]print(ids) filtered = model(SAMPLE_IMAGE, classes=ids)print(len(filtered.boxes))classesはクラスIDのリストを受け取り、そのいずれかに属する予測だけを残します。IDはresult.namesのインデックスです。データセットの順序を仮定せず、結果のnamesを読み取る方法が最も確実です。
フィルタリングは各ファミリーの後処理後に、すべての推論経路が通る共通処理で行われます。これにより2つの重要な効果があります。NMSを使わないファミリーを含め、すべてのファミリーで機能します。また、ボックスに対応するペイロードも同時に絞り込むため、マスク、キーポイント、回転ボックスが対応しない状態で残ることもありません。
コマンドラインのclassesには、単独の整数、リスト、カンマ区切り文字列を指定できます。
libreyolo predict model=LibreYOLO9s.pt classes=0 source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpglibreyolo predict model=LibreYOLO9s.pt classes="[0,2,5]" source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgフィルタリングだけで精度が得られるわけではありません。後で破棄するクラスの予測にもモデルは計算量を使います。classesを指定すると、ファミリーは300個(max_detの方が大きい場合はmax_det個)の候補ボックスを確保し、max_detへの切り詰めはフィルタリングの後に行われるため、max_detが小さくても目的のクラスが押し出されることはありません。エクスポートしたバックエンドも、バッチ処理のTensorRTエンジンを含めて同じ候補数を使います。不要なクラスのスコアの高いボックスが300個を超える画像では、目的のクラスに到達する前に候補が埋まる可能性があります。その場合はmax_detを300より大きくしてください。
agnostic_nms
各ファミリー独自のNMSはクラス別なので、デフォルトでは、異なるクラスの2つのボックスは重なっていても、どのiouでも両方残ります。agnostic_nms=Trueはクラス非依存のステップを1つ追加します:iouを超えて重なるボックスのうち、クラスに関係なく最もスコアの高いボックスだけが残ります。
from libreyolo import LibreYOLO, SAMPLE_IMAGE model = LibreYOLO("LibreYOLO9s.pt") per_class = model(SAMPLE_IMAGE)agnostic = model(SAMPLE_IMAGE, agnostic_nms=True) # 重なり合う異なるクラスのボックスは最もスコアの高い1つにまとまるprint(len(per_class.boxes), len(agnostic.boxes))libreyolo predict model=LibreYOLO9s.pt agnostic_nms=true \ source=https://raw.githubusercontent.com/LibreYOLO/libreyolo/release/libreyolo/assets/parkour.jpgこのステップは、ファミリーの完成した検出結果に対して、classesのフィルタリングの後、max_detへの切り詰めの前に実行されます。そのため、独自のNMSを実行しない集合予測器、エクスポートしたバックエンド、augment=Trueとtiling=Trueの場合でも同じように動作します。マスクとキーポイントは対応するボックスとともに削除され、回転ボックスは回転IoUで比較されます。対象はボックスを返すタスク、つまりdetect、segment、pose、obbです。
ファミリーはこのステップの処理対象として、300個(max_detの方が大きい場合はmax_det個)の候補ボックスを確保します。max_detが300未満の場合、抑制で空いた枠はスコアの低い候補で埋められます。デフォルトを含む300以上の場合、その枠は空のままです。
適用されない場合は次のとおりです。
- 標準の推論経路では、ボックスを持たないタスクは
ValueErrorを送出します。 LibreEnsembleとHRNetはNotImplementedErrorを送出します。LibreSAMモデルと3D検出器(WildDet3D、3D-MOOD、FCOS3D、DetAny3D)はこの引数を受け付けず、TypeErrorを送出します。- L2CS-Net、PP-OCRv5、SAM 3D Body、LibreFaceRecは独自の推論経路を実行し、この引数を無視します。
val(agnostic_nms=True)はdetectとsegmentの検証に同じステップを適用します。検証と指標を参照してください。
predictが拒否するもの
警告ではなく例外を送出する引数が2つあります。visualizeとembedはどちらもNotImplementedErrorを送出します。埋め込みにはtask="embed"を指定してモデルを読み込み、通常どおりpredictまたはembedを呼び出してください。agnostic_nms=Trueは、上記のとおり適用されない場合に例外を送出します。
認識されない引数は、対応するオプションを示すTypeErrorを送出します。そのため、入力ミスが暗黙に無視されることはありません。
次の引数は受け付けられますが、警告して破棄されます。boxes、dnn、half、line_width、retina_masks、show_conf、show_labels、verboseです。