検証と指標
検証はval()を通じてデータセット分割上でモデルを実行し、指標キーと浮動小数点値のフラットな辞書を返します。キーはリテラル文字列で、取得できるものはファミリーではなくタスクによって決まります。
検証の実行
val()はデータセットを受け取り、指標を返します。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml") print(metrics["metrics/mAP50-95"])print(metrics["metrics/mAP50"])print(metrics["speed/total_ms"])libreyolo val model=LibreYOLO9s.pt data=coco8.yamlfrom libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml", split="train", batch=4) print(metrics)戻り値は指標キーを数値に対応付けるフラットなdictです。すべてのキーはリテラルなので、位置ではなく名前で読み取ってください。detect、segment、classifyでは、後述するクラスごとの結果も属性として持つdictのサブクラスです。
主な引数はdata、split、batch、imgsz、conf、iou、workers、device、augment、save_json、verboseです。confのデフォルトは0.001、iouは0.6で、どちらも予測時のデフォルトより大幅に緩くなっています。mAPのsweepには信頼度の低い末尾まで必要なためです。imgszは固定値ではなくモデル自身の入力サイズがデフォルトです。splitはval、test、trainだけを受け付けます。dataを指定しない場合、学習で得たチェックポイントは学習に使ったデータセットで検証し、公開済みの重みはデータセットを持たないためdata=が必要です。
検証構成のその他のフィールドはキーワード引数として渡せます。save_dir、max_det、eval_max_det、half、amp_dtype、cache、save_plots、single_cls、agnostic_nmsも含まれます。CUDAでhalf=Trueを指定すると、検証はamp_dtypeのautocast下で実行され、bfloat16の出力は後処理の前にfloat32へキャストされます。amp_dtype="bfloat16"で学習した場合も同じ方法で検証します。
agnostic_nms=Trueは、iouを超えて重なるボックスのうち、クラスに関係なく最もスコアの高いボックスだけを残します。これはファミリーの完成した検出結果に対してclasses=の後に実行されるため、mAP、混同行列、曲線、画像ごとのカウントはすべて同じボックスを評価します。対象はdetectとsegmentで、それ以外のタスクではValueErrorが発生します。推論側についてはしきい値とフィルタリングを参照してください。
single_cls=Trueは物体検出を1クラスとして評価します。正解データはクラス0にまとめられ、モデルの検出結果はモデル自身のラベル空間でclasses=に絞り込まれた後に0へ付け替えられるため、複数クラスで学習したチェックポイントも1クラスの検出器として評価されます。
タスク別の指標キー
物体検出はCOCO系の数値を返します。
metrics/mAP50-95 metrics/mAP50 metrics/mAP75metrics/mAP_small metrics/mAP_medium metrics/mAP_largemetrics/AR1 metrics/AR10 metrics/AR100 metrics/AR_max_detmetrics/AR_small metrics/AR_medium metrics/AR_largemetrics/precision metrics/recallmetrics/precision(B) metrics/recall(B) metrics/mAP50(B) metrics/mAP50-95(B)このうち2つは注意が必要です。metrics/precisionとmetrics/recallは後方互換性のため維持されるエイリアスで、precisionとrecallの組ではなく、mAP 50-95とAR@100の値を保持します。名前が明確なキーを使用してください。
インスタンスセグメンテーションでは、上記のmAPとARをサフィックスなしのキーでマスク指標として返し、ボックス版を(B)サフィックス、マスク版のコピーを(M)サフィックスで返します。このタスクのprecisionとrecallはサフィックス付きだけで、metrics/precision(B)とmetrics/recall(B)、metrics/precision(M)とmetrics/recall(M)になります。どちらの組も物体検出と同じエイリアス値を保持します。(B)の組はボックスのmAP50-95とAR@100、(M)の組はマスクのmAP50-95とAR@100です。
| タスク | キー |
|---|---|
| detect | metrics/mAP50-95、metrics/mAP50、metrics/mAP75と、上記のサイズ別およびrecall内訳 |
| segment | 上記のdetectキーのマスク版(サフィックスなしはマスク)。precisionとrecallは(B)と(M)だけで、どちらも同じ規則のエイリアス |
| pose | metrics/keypoints_mAP50-95、metrics/keypoints_mAP50、metrics/keypoints_mAP75、metrics/keypoints_mAP_M、metrics/keypoints_mAP_Lと、対応するkeypoints_ARキー |
| obb | metrics/mAP50-95、metrics/mAP50、metrics/mAP75、metrics/precision、metrics/recallと、(OBB)サフィックス付きのコピー |
| classify | metrics/accuracy_top1、metrics/accuracy_top5 |
| semantic | metrics/mIoU、metrics/pixel_accuracy |
| panoptic | metrics/PQ、metrics/SQ、metrics/RQ、metrics/PQ_things、metrics/PQ_stuff、metrics/categories |
| depth | metrics/abs_rel、metrics/rmse、metrics/delta1、metrics/delta2、metrics/delta3 |
| normal | metrics/mean_angular_error、metrics/median_angular_error、metrics/within_11_25、metrics/within_22_5、metrics/within_30 |
| edge | metrics/ODS、metrics/OIS、metrics/best_threshold |
| restore | metrics/PSNR、metrics/SSIM |
| matte | metrics/MAE、metrics/Smeasure |
| ocr | metrics/det_precision、metrics/det_recall、metrics/det_hmean、metrics/e2e_precision、metrics/e2e_recall、metrics/e2e_f1、metrics/rec_1-NED |
| point | metrics/precision、metrics/recall、metrics/f1、metrics/MLE、metrics/MAE、metrics/RMSEと、mAP sweepキー |
OBBのmetrics/precisionとmetrics/recallはエイリアスではありません。IoU 0.50における実際のprecisionとrecallで、最も緩い動作点、つまりconf(デフォルト0.001)を通過したすべての予測から取得します。(OBB)サフィックス付きのコピーは、上記の(B)や(M)と同じ規則で、同じ4つの値をタスク固有名の下に繰り返します。
accuracy_top5は実際にはtop-min(5, num_classes)です。3クラスのデータセットではtop-3となり、すべてのサンプルが条件を満たすため1.0になります。分類の結果は、この2つの値をconfusion_matrixと並ぶ属性top1とtop5としても公開します。
pointタスクのsweepキーは距離しきい値から構築されます。デフォルトではmetrics/mAP@[0.01:0.10]となり、単一しきい値のキーはmetrics/mAP@0.01です。dist_thresholdsを渡すと両方の文字列が変わります。
ほとんどのタスクは、最良チェックポイント選択でデフォルト使用する単一値のfitnessキーも返します。物体検出、セグメンテーション、OBBはこのキーを持ちません。それらのファミリーでは辞書が返すmetrics/mAP50-95を使って選択します。姿勢推定はfitnessもmetrics/mAP50-95も返さず、代わりにトレーナーがbest_metric_keyをmetrics/keypoints_mAP50-95へ設定します。
ImageFolder分類は、検証対象に存在するクラスで平均したマクロ平均のmetrics/precision、metrics/recall、metrics/f1を追加します。デフォルトの適合度は引き続きtop-1です。物体検出はmetrics/best_confとmetrics/best_conf_f1も返してIoU 0.50でマイクロF1が最良となるしきい値を選択し、クラス名をキーとするしきい値をmetrics.box.best_conf_per_classに格納します。同じスコアの検出はまとめて扱い、同点の場合は高いしきい値を選びます。正のF1がない場合は0.0を返します。セグメンテーションはこれらのしきい値キーを公開しません。
混同行列
detect、segment、classifyの結果はresults.confusion_matrixを持ちます。プロットを書き出すかどうかに関係なく毎回の検証で計算され、そのmatrixはmatrix[predicted, true]でインデックス付けされる整数配列です。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml") cm = metrics.confusion_matrixprint(cm.matrix.shape) # (81, 81) 80クラスと背景print(cm.class_accuracy()) # クラス名ごとに 検出された物体のうちそのクラスが付いた割合tp, fp = cm.tp_fp()detectとsegmentでは、信頼度0.25(confの方が高ければconf)以上の予測を、クラスを問わず正解ボックスとIoU 0.5で、IoUの高い順に1対1で組み合わせます。組は予測クラスと正解クラスの位置に数えられるため、位置は正しくてもクラスが誤っているボックスは対角線の外に入ります。行列には追加のbackground行と列があります:組にならなかった正解データはbackground行に、組にならなかった予測はbackground列に数えられます。セグメンテーションはマスクではなくボックスで組み合わせます。classes=を指定すると、それ以外のクラスの正解データは除外されます。
COCOのcrowd領域(iscrowd=1)は、mAPが適用する規則に従います。同じクラスのどの正解データとも一致しなかった予測が、同じクラスのcrowd領域の内側に半分以上(予測自身の面積に対する交差部分の割合)入っている場合、その予測は数えずに無視します。box.image_metricsとvisualize=Trueの画像も、同じしきい値と同じcrowd規則を使います。YOLO形式のラベルにはcrowd領域がありません。
classifyでは、各画像はtop-1クラスとラベルの組として1回だけ数えられ、backgroundはありません。
| メソッド | 戻り値 |
|---|---|
summary(normalize=False) | 予測クラスごとに1つの辞書{"Predicted": name, <true class>: value}。normalizeを指定すると各正解クラスに対する割合 |
to_csv()、to_json() | CSVまたはJSONテキストとしてのサマリー |
to_df() | Polars DataFrameとしてのサマリー。pip install polarsが必要 |
tp_fp() | クラスごとの真陽性(対角成分)と偽陽性(予測行の残り) |
nonzero() | 値の入ったセルを位置を揃えた(predicted, true, count)配列として |
class_accuracy() | クラスごとに、そのインスタンスのうちそのクラスが付いた割合。物体検出では検出された物体だけが対象 |
plot(normalize=True, save_dir="") | confusion_matrix_normalized.png(normalize=Falseではconfusion_matrix.png)を書き出し、そのパスを返す |
クラス数が2,000を超えると、分類用の密な行列は構築されません:matrix、summary()、to_*()によるエクスポート、plot()は例外を発生させますが、tp_fp()、nonzero()、class_accuracy()は引き続き動作します。
クラスはlibreyolo.validation.ConfusionMatrixで、ConfusionMatrix(nc, iou_thres=0.5, conf_thres=0.25, *, names=None, task="detect")として構築し、taskには"detect"または"classify"を指定します。
クラスごとの適合率、再現率、F1
detectとsegmentの結果は、IoU 0.5で照合した各クラスの適合率、再現率、F1を、信頼度しきい値全体にわたって持ちます。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml") box = metrics.boxprint(box.px.shape, box.f1_curve.shape) # (1000,) と (classes, 1000)for index, f1 in zip(box.ap_class_index, box.f1): print(model.names[int(index)], round(float(f1), 3))box.pxは[0, 1]を等間隔に区切った1000個の信頼度を保持します。box.p_curve、box.r_curve、box.f1_curveは(classes, 1000)の配列で、分割内に正解データを持つクラスのインデックスを昇順に並べたbox.ap_class_indexの各要素に1行ずつ対応します。box.p、box.r、box.f1は、それらのクラスにわたる平均F1が最大となる信頼度での、クラスごとの値です。セグメンテーションはこれらすべてをボックスから計算します。実行で曲線が生成されなかった場合は空の配列になります。
画像ごとのボックス指標
物体検出とセグメンテーションの結果は辞書との互換性を維持し、results.box.image_metricsも公開します。可視化が無効でも、可視化の照合規則を使って、各ファイル名にprecision、recall、f1、tp、fp、fnを対応付けます。セグメンテーションでも、ここではボックスを数えます。同じベース名が重複する場合、2つ目以降は完全なパスを使います。分母が0の場合は0.0を返します。これらの記録は分散ランク間では集約しません。
速度キー
すべてのバリデーターが処理時間を追加します。
speed/preprocess_ms speed/inference_ms speed/postprocess_msspeed/total_ms speed/total_s speed/images_seenこれらは実行全体で平均した画像あたりのミリ秒です。実行したマシンと設定を表すため、この値を報告するときはハードウェア、バッチサイズ、精度も併記しなければ意味がありません。
評価バックエンド
物体検出とセグメンテーションの指標はCOCO評価器で計算され、デフォルトのfaster_coco_eval=Trueはfaster-coco-evalパッケージがインストールされている場合にC++バックエンドを選択します。ない場合はプロセスごとに1回警告し、pycocotoolsへフォールバックします。
faster_coco_eval requested but not installed; falling back to pycocotools.Install with: pip install faster-coco-eval実際に使用したバックエンドはモデルのlast_eval_backendに記録され、物体検出系タスクではCLIも出力に含めます。環境から構成値を上書きするにはLIBREYOLO_FASTER_COCO_EVALを設定します。
iou_thresholdsが使われるのはOBB経路だけです。COCO経路は独自の固定0.50から0.95のsweepで評価し、この値を無視します。
検証loss
デフォルトの検証は精度だけを報告します。val_loss=Trueを指定すると、検証バッチに対してファミリーの学習目的関数も計算します。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train(data="coco8.yaml", epochs=10, val_loss=True)metrics/lossと項ごとのmetrics/loss/<component>を出力します。各成分には学習とまったく同じ重みが付くため、合計するとtotalになります。ロガーではval/lossとval/loss/<component>として表示され、libreyolo monitorはmetrics/lossをtrain/lossへ重ねて表示します。
成分はファミリー固有です。
| タスク | ファミリー | 成分 |
|---|---|---|
| detect | yolo9、yolo9_p2、yolo9_e2e | box、cls、dfl |
| detect | yolonas | cls、iou、dfl |
| detect | rfdetr | ce、bbox、giou |
| detect | rtdetr、rtdetrv2 | vfl、bbox、giou |
| detect | dfine | vfl、bbox、giou、fgl、ddf |
| detect | domedetr | vfl、bbox、giou、fgl、ddf、defe_density、defe_reg |
| detect | deim、deimv2、rtdetrv4、ec | mal、bbox、giou、fgl、ddf |
| detect | rtmdet | cls、bbox |
| detect | picodet | cls、bbox、dfl |
| detect | yolox | iou、obj、cls、l1 |
| detect | yolo7 | iou、obj、cls |
| point | fomo | ce |
| classify | resnet、convnext、mobilenetv4、efficientnetv2 | ce |
| semantic | segformer、lingbotvision、dinov2 | sem |
| restore | nafnet | restore |
ターゲット割り当てによって検証の時間とメモリが増えるため、デフォルトでは無効です。精度指標用にすでに生成したモデル出力を再利用し、2回目の順伝播は実行しません。評価モデルまたはEMAモデルに対してno_grad下で実行し、マルチGPU学習ではcollectiveを使わずrank 0上でローカル計算します。最良チェックポイントの選択は引き続き精度指標に基づきます。
意図的に行わないことが3つあります。1つ目は対照的ノイズ除去の項を含めないことです。これには順伝播時の正解データが必要ですが、検証の順伝播では渡さないためです。2つ目は評価モードのモデルを報告することです。BatchNorm統計やStochastic Depthなど、ファミリーの学習時と評価時の順伝播が実際に異なる箇所では、数値は評価モードを反映します。これが意図する比較です。3つ目は、ファミリーで未実装のタスクを通知なくスキップしないことです。セットアップ時に構成エラーを発生させます。
val_loss=True currently supports RF-DETR detection only; segment, pose, OBB,classify, and semantic tasks are not supportedFOMOは動作が変わらない例外です。バリデーターが常にこのlossを計算しており、val_loss=Trueは公開するキーだけに影響します。
拡張付き検証と検証lossは併用できず、両方を指定すると例外が発生します。
検証が書き込むファイル
val()は必ず保存ディレクトリにconfig.yamlを書き込みます。save_dirを指定しない場合、デフォルトはruns/val/<model>_<size>_<timestamp>です。project、name、exist_okは学習と同じ方法でこれを選択します:project/nameに、exist_ok=Trueでない限り連番の接尾辞を付けます。
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.val(data="coco8.yaml", save_json=True, save_dir="runs/val/exp")save_json=Trueは、物体検出ではpredictions.json、セグメンテーションではpredictions_bbox.jsonとpredictions_masks.jsonを書き込みます。OBBは対応しておらず、その旨を報告します。
save_plots=True(またはエイリアスのplots=True)はplots/サブディレクトリへ書き込み、pip install "libreyolo[plots]"でインストールされるmatplotlibを必要とします。物体検出では、box_metrics.png、クラスごとのAPと再現率のチャート、適合率・再現率曲線と信頼度曲線、f1_conf_box.pngのクラスごとのF1曲線、件数で表したconfusion_matrix.pngと各正解クラスに対する割合で表したconfusion_matrix_normalized.pngの混同行列、さらにOpenCVがインストールされている場合はアノテーション付きのサンプル画像を生成します。セグメンテーションは、指標チャート、クラスごとのチャート、適合率・再現率曲線と信頼度曲線のマスク版を追加します。F1曲線と混同行列はボックス単位のままです。姿勢推定には独自の指標と曲線一式があります。画像分類は、クラス数が2,000を超える場合を除き、2つの混同行列ファイルを書き込みます。その他のバリデーターはプロットを実装していません。セマンティック、panoptic、深度、法線、エッジ、復元、matte、OCR、OBB、pointはいずれも何も書き込みません。プロットの失敗は警告され、実行を中止しません。
visualize=Trueは、物体検出とセグメンテーションではクラスを考慮したボックスのTP/FP/FN画像を、ImageFolder分類ではラベルとtop-1の比較画像を、visualize/errors/とvisualize/correct/に書き出します。照合にはIoU 0.5と信頼度max(0.25, conf)を使います。デフォルトはvisualize=False、show_labels=True、show_conf=Trueです。未対応タスクとV-JEPA 2のクリップ検証は可視化を拒否します。
plot_samples=8は、別のサンプル描画の上限です。0で無効にし、-1ですべての画像を残します。指標や可視化の出力には影響しません。
学習中の検証
学習はeval_intervalエポックごと、および最終エポックの後には必ず、データセットのval分割で検証し、生成された指標がbest.ptの選択、patienceによる早期停止、すべてのロガーのval/キーを駆動します。EMAが有効な場合、検証はEMA重み上で実行されます。そのファイルは実行ディレクトリ内のval/ディレクトリに書き込まれます。val=Falseは最終エポックも含めて学習中の検証を無効にします。
eval_interval、patience、save_plotsについてはハイパーパラメーターを、数値の送信先については実験ロガーを参照してください。
関連項目
- バリデーターが読み取る分割キーと形式についてはデータセットを参照してください。