Переглянути як Markdown

Валідація та метрики

Валідація запускає модель на частині датасету через val() і повертає плоский словник ключів метрик та чисел із рухомою крапкою. Ключі є буквальними рядками, а їхній набір залежить від задачі, а не від сімейства.

Запуск валідації

val() приймає датасет і повертає метрики.

Python
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"])
CLI
libreyolo val model=LibreYOLO9s.pt data=coco8.yaml
На іншій частині
from 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 потрібен хвіст низької впевненості. imgsz типово дорівнює власному розміру вхідних даних моделі, а не фіксованому числу. split приймає лише val, test або train. Без data навчена контрольна точка валідується на датасеті, на якому її навчено; опубліковані ваги його не містять і потребують data=.

Будь-яке інше поле конфігурації валідації передається як іменований аргумент, зокрема save_dir, max_det, eval_max_det, half, amp_dtype, cache, save_plots, single_cls і agnostic_nms. За half=True на CUDA валідація виконується під autocast з amp_dtype, а виходи bfloat16 перед постобробленням приводяться до float32; навчання з amp_dtype="bfloat16" валідується так само.

agnostic_nms=True лишає тільки рамку з найвищою оцінкою серед рамок, що перекриваються понад iou, незалежно від їхніх класів. Він працює на готових виявленнях сімейства, після classes=, тому mAP, матриця плутанини, криві та підрахунки для кожного зображення оцінюють одні й ті самі рамки. Він охоплює detect і segment, а будь-яке інше завдання спричиняє ValueError. Сторону передбачення описано в розділі Пороги та фільтрування.

single_cls=True оцінює виявлення як один клас. Еталонна розмітка згортається до класу 0, а виявлення моделі обмежуються classes= у власному просторі міток моделі й перемічуються на 0, тому контрольна точка, навчена на кількох класах, оцінюється як одноокласовий детектор.

Ключі метрик для кожної задачі

Виявлення повертає сімейство показників 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)

Два з них можуть ввести в оману. metrics/precision і metrics/recall є псевдонімами, збереженими для зворотної сумісності: вони містять значення mAP 50-95 і AR@100, а не пару точності й повноти. Використовуйте іменовані ключі.

Сегментація екземплярів повертає наведені вище значення mAP і AR для масок під ключами без суфікса, версії рамок під суфіксом (B) і повторені версії масок під суфіксом (M). Для цієї задачі точність і повнота існують лише у формах із суфіксом, metrics/precision(B)/metrics/recall(B) і metrics/precision(M)/metrics/recall(M), а обидві пари містять ті самі типи псевдонімів, що й для виявлення: пара (B) є mAP50-95 рамок і AR@100 рамок, а пара (M) є mAP50-95 масок і AR@100 масок.

ЗадачаКлючі
detectmetrics/mAP50-95, metrics/mAP50, metrics/mAP75, а також наведені вище розподіли за розміром і повнотою
segmentверсії наведених вище ключів detect для масок (ключі без суфікса стосуються масок); precision/recall існують лише як (B)/(M), обидві пари мають ті самі типи псевдонімів
posemetrics/keypoints_mAP50-95, metrics/keypoints_mAP50, metrics/keypoints_mAP75, metrics/keypoints_mAP_M, metrics/keypoints_mAP_L і відповідні ключі keypoints_AR
obbmetrics/mAP50-95, metrics/mAP50, metrics/mAP75, metrics/precision, metrics/recall, а також копії із суфіксом (OBB)
classifymetrics/accuracy_top1, metrics/accuracy_top5
semanticmetrics/mIoU, metrics/pixel_accuracy
panopticmetrics/PQ, metrics/SQ, metrics/RQ, metrics/PQ_things, metrics/PQ_stuff, metrics/categories
depthmetrics/abs_rel, metrics/rmse, metrics/delta1, metrics/delta2, metrics/delta3
normalmetrics/mean_angular_error, metrics/median_angular_error, metrics/within_11_25, metrics/within_22_5, metrics/within_30
edgemetrics/ODS, metrics/OIS, metrics/best_threshold
restoremetrics/PSNR, metrics/SSIM
mattemetrics/MAE, metrics/Smeasure
ocrmetrics/det_precision, metrics/det_recall, metrics/det_hmean, metrics/e2e_precision, metrics/e2e_recall, metrics/e2e_f1, metrics/rec_1-NED
pointmetrics/precision, metrics/recall, metrics/f1, metrics/MLE, metrics/MAE, metrics/RMSE, а також ключ перебору mAP

metrics/precision і metrics/recall для OBB не є псевдонімами: це справжні точність і повнота за IoU 0.50, узяті в найслабшій робочій точці (кожне передбачення, що пройшло conf, типово 0.001). Копії із суфіксом (OBB) повторюють ті самі чотири значення під назвою конкретної задачі за тією самою домовленістю, що й (B) та (M) вище.

accuracy_top5 насправді означає top-min(5, num_classes), тому в датасеті з трьома класами це top-3, якому відповідає кожен зразок, а отже значення дорівнює 1.0. Результати класифікації також надають ці два значення як атрибути top1 і top5 поряд із confusion_matrix.

Ключ перебору задачі point формується з порогів відстані, тому за типових значень він має назву 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, вибираючи оптимальний за мікро-F1 поріг при IoU 0.50, і розміщує пороги з ключами за назвами класів у 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, якщо він вищий, зіставляються один до одного з еталонними рамками будь-якого класу за IoU 0.5, починаючи з найвищого IoU. Пара рахується за її передбаченим і справжнім класом, тож добре розміщена рамка з хибним класом потрапляє поза діагональ. Матриця має додатковий рядок і стовпець background: еталонна рамка без пари рахується в рядку background, а передбачення без пари в стовпці background. Сегментація зіставляє рамки, а не маски. З classes= еталонні дані інших класів виключаються.

Області натовпу COCO (iscrowd=1) підпорядковуються правилу, яке застосовує mAP. Передбачення, якому не відповідала жодна еталонна рамка його класу й яке лежить принаймні наполовину всередині області натовпу того самого класу (перетин, поділений на власну площу передбачення), ігнорується, а не рахується. box.image_metrics і зображення visualize=True використовують ті самі пороги й те саме правило натовпу. Мітки у форматі YOLO не мають областей натовпу.

Для classify кожне зображення рахується один раз, за його класом top-1 щодо його мітки, і background немає.

МетодПовертає
summary(normalize=False)Один словник на кожен передбачений клас, {"Predicted": name, <справжній клас>: 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, або confusion_matrix.png з normalize=False, і повертає шлях

Понад 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 несуть точність, повноту й F1 кожного класу за різних порогів впевненості, зіставлені за IoU 0.5.

Криві для кожного класу
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,) і (класи, 1000)for index, f1 in zip(box.ap_class_index, box.f1):    print(model.names[int(index)], round(float(f1), 3))

box.px містить 1000 значень впевненості, рівномірно розподілених на [0, 1]. box.p_curve, box.r_curve і box.f1_curve є масивами (класи, 1000), по одному рядку на кожен елемент box.ap_class_index, тобто індекси класів, що мають еталонні дані в частині датасету, у зростальному порядку. box.p, box.r і box.f1 є значеннями для кожного класу за впевненості, що максимізує середній F1 за цими класами. Сегментація обчислює всі з них за рамками. Вони є порожніми масивами, коли запуск не створив кривих.

Метрики рамок для кожного зображення

Результати виявлення й сегментації зберігають сумісність зі словниками та також надають results.box.image_metrics. Кожній назві файлу відповідають precision, recall, f1, tp, fp і fn за правилом зіставлення візуалізації, навіть коли візуалізацію вимкнено. Сегментація тут рахує рамки. Повторювані базові назви після першого входження використовують повні шляхи. Нульові знаменники дають 0.0. Ці записи не збираються між розподіленими рангами.

Ключі швидкості

Кожен валідатор додає часові показники:

speed/preprocess_ms   speed/inference_ms   speed/postprocess_msspeed/total_ms        speed/total_s        speed/images_seen

Це мілісекунди на зображення, усереднені за запуском. Вони описують машину й використані налаштування, тому значення має сенс лише разом з обладнанням, розміром батча й точністю.

Backend оцінювання

Метрики виявлення й сегментації обчислюються через оцінювач COCO, а типове значення faster_coco_eval=True вибирає backend C++, коли встановлено пакет faster-coco-eval. Якщо його немає, запуск переходить до pycocotools з одним попередженням на процес:

faster_coco_eval requested but not installed; falling back to pycocotools.Install with: pip install faster-coco-eval

Фактично використаний backend записується в модель як last_eval_backend, а CLI повідомляє його у виводі для задач у стилі виявлення. Установіть LIBREYOLO_FASTER_COCO_EVAL, щоб перевизначити значення конфігурації із середовища.

iou_thresholds враховується лише на шляху OBB. Шлях COCO оцінює за власним фіксованим набором від 0.50 до 0.95 та ігнорує це значення.

Функція втрат валідації

Типово валідація повідомляє лише правильність. val_loss=True також обчислює навчальну цільову функцію сімейства на батчах валідації.

Python
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")model.train(data="coco8.yaml", epochs=10, val_loss=True)

Вона породжує metrics/loss і один ключ metrics/loss/<component> для кожного доданка, зваженого так само, як під час навчання, тому сума компонентів дорівнює загальному значенню. Через логер вони відображаються як val/loss і val/loss/<component>, а libreyolo monitor накладає metrics/loss на train/loss.

Компоненти належать самим сімействам:

ЗадачаСімействаКомпоненти
detectyolo9, yolo9_p2, yolo9_e2ebox, cls, dfl
detectyolonascls, iou, dfl
detectrfdetrce, bbox, giou
detectrtdetr, rtdetrv2vfl, bbox, giou
detectdfinevfl, bbox, giou, fgl, ddf
detectdomedetrvfl, bbox, giou, fgl, ddf, defe_density, defe_reg
detectdeim, deimv2, rtdetrv4, ecmal, bbox, giou, fgl, ddf
detectrtmdetcls, bbox
detectpicodetcls, bbox, dfl
detectyoloxiou, obj, cls, l1
detectyolo7iou, obj, cls
pointfomoce
classifyresnet, convnext, mobilenetv4, efficientnetv2ce
semanticsegformer, lingbotvision, dinov2sem
restorenafnetrestore

Вона типово вимкнена, оскільки призначення цілей додає до валідації витрати часу й пам'яті. Валідатор повторно використовує результат моделі, уже створений для метрики правильності, замість другого прямого проходу, працює в контексті no_grad на моделі оцінювання або EMA, а під час навчання на кількох GPU обчислюється локально на ранзі 0 без колективних операцій. Вибір найкращої контрольної точки й далі використовує метрику правильності.

Три дії навмисно не виконуються. Функція ніколи не містить доданків контрастного шумопригнічення, бо їм потрібна еталонна розмітка під час прямого проходу, а прямий прохід валідації виконується без неї. Вона повідомляє результат моделі в режимі оцінювання, тому там, де прямі проходи навчання й оцінювання сімейства справді відрізняються статистикою BatchNorm або стохастичною глибиною, число відображає режим оцінювання; саме таке порівняння й передбачено. Якщо сімейство не реалізувало цю можливість для задачі, під час налаштування породжується помилка конфігурації замість непомітного пропуску:

val_loss=True currently supports RF-DETR detection only; segment, pose, OBB,classify, and semantic tasks are not supported

FOMO є винятком, для якого нічого не змінюється: його валідатор завжди обчислював цю функцію втрат, а val_loss=True впливає лише на ключі, під якими її опубліковано.

Аугментовану валідацію не можна поєднувати з функцією втрат валідації; одночасний запит обох можливостей породжує помилку.

Файли, які записує валідація

Метод val() завжди записує config.yaml до каталогу результатів, який типово має назву runs/val/<model>_<size>_<timestamp>, якщо save_dir не задано. project, name і exist_ok вибирають його так само, як під час навчання: project/name із суфіксом зі збільшуваним номером, якщо не задано exist_ok=True.

Записати передбачення у форматі COCO
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/, і потрібен matplotlib, який встановлює pip install "libreyolo[plots]". Для виявлення створюються box_metrics.png, графіки AP і повноти для кожного класу, криві точність-повнота й залежності від упевненості, криві F1 для кожного класу в f1_conf_box.png, матриця плутанини як кількості в confusion_matrix.png і як частки кожного справжнього класу в confusion_matrix_normalized.png, а також анотовані зображення-зразки, якщо встановлено OpenCV. Сегментація додає копії графіка метрик, графіків для кожного класу та кривих точність-повнота й залежностей від упевненості для масок; криві F1 і матриця плутанини залишаються на рівні рамок. Поза отримує власний набір метрик і кривих. Класифікація записує два файли матриці плутанини, окрім випадку понад 2,000 класів. Інші валідатори не реалізують графіки; семантична й паноптична сегментація, глибина, нормалі, краї, відновлення, matting, OCR, OBB і point нічого туди не записують. Помилка побудови графіка породжує попередження й ніколи не перериває запуск.

visualize=True записує зображення TP/FP/FN рамок із урахуванням класів для виявлення й сегментації або порівняння мітки з top-1 для класифікації ImageFolder у 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 наведено в розділі Гіперпараметри, а місця надсилання чисел описано в розділі Логери експериментів.

  • Датасети описують ключі частин і формати, які читають валідатори.

Перевірено з LibreYOLO v1.6.0.