Xác thực và metric

Xác thực chạy mô hình trên một split của dataset qua val() và trả về dictionary phẳng gồm các key metric và giá trị float. Các key là chuỗi literal, và tập key nhận được phụ thuộc vào tác vụ chứ không phải family.

Chạy xác thực

val() nhận dataset và trả về các metric.

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
Trên split khác
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml", split="train", batch=4) print(metrics)

Giá trị trả về là một dict phẳng ánh xạ các key metric tới số. Mọi key đều là literal, vì vậy hãy đọc theo tên thay vì vị trí. Với detect, segment và classify nó là một lớp con của dict có thêm kết quả theo từng lớp đối tượng dưới dạng thuộc tính, được mô tả bên dưới.

Các đối số chính là data, split, batch, imgsz, conf, iou, workers, device, augment, save_json và verbose. conf mặc định là 0.001 và iou là 0.6, đều lỏng hơn nhiều so với giá trị mặc định khi dự đoán vì một lượt quét mAP cần phần đuôi có độ tin cậy thấp. imgsz mặc định theo kích thước đầu vào riêng của mô hình thay vì một số cố định. split nhận val, test hoặc train và không nhận giá trị nào khác. Khi không có data, một checkpoint đã huấn luyện được xác thực trên dataset mà nó đã được huấn luyện; trọng số đã phát hành không mang dataset nào và cần data=.

Mọi trường khác của cấu hình xác thực được truyền qua dưới dạng đối số keyword, gồm save_dir, max_det, eval_max_det, half, amp_dtype, cache, save_plots, single_cls và agnostic_nms. Với half=True trên CUDA, việc xác thực chạy dưới autocast ở amp_dtype, và đầu ra bfloat16 được ép sang float32 trước khi hậu xử lý; huấn luyện với amp_dtype="bfloat16" cũng xác thực theo cách đó.

agnostic_nms=True chỉ giữ box có điểm cao nhất trong các box chồng lấn vượt iou, bất kể lớp của chúng. Nó chạy trên các phát hiện đã hoàn tất của family, sau classes=, nên mAP, confusion matrix, các đường cong và số đếm theo từng ảnh đều chấm điểm cùng các box. Nó bao phủ detect và segment, và mọi tác vụ khác phát sinh ValueError. Phía predict nằm ở Ngưỡng và lọc.

single_cls=True chấm điểm phát hiện như một lớp đối tượng duy nhất. Ground truth được gộp về lớp 0, và các phát hiện của mô hình được giữ theo classes= trong không gian nhãn của chính mô hình, rồi gán lại nhãn 0, nên một checkpoint được huấn luyện trên nhiều lớp đối tượng được chấm điểm như một detector một lớp.

Key metric theo từng tác vụ

Phát hiện trả về nhóm số liệu 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)

Hai key trong đó dễ gây nhầm lẫn. metrics/precision và metrics/recall là các alias được giữ để tương thích ngược: chúng mang giá trị mAP 50-95 và AR@100, không phải một cặp precision và recall. Hãy dùng các key có tên cụ thể.

Phân đoạn thực thể trả về các số liệu mAP và AR ở trên dưới dạng số liệu mặt nạ trong các key không có hậu tố, với phiên bản hộp dưới hậu tố (B) và phiên bản mặt nạ được lặp lại dưới (M). Với tác vụ này, precision và recall chỉ tồn tại ở dạng có hậu tố metrics/precision(B)/metrics/recall(B) và metrics/precision(M)/metrics/recall(M), cả hai cặp mang cùng giá trị alias như detect: cặp (B) là mAP50-95 và AR@100 của hộp, cặp (M) là mAP50-95 và AR@100 của mặt nạ.

Tác vụKey
detectmetrics/mAP50-95, metrics/mAP50, metrics/mAP75, cùng phân tích theo kích thước và recall ở trên
segmentphiên bản mặt nạ của các key detect ở trên (key không hậu tố là mặt nạ); precision/recall chỉ có dạng (B)/(M), cả hai được alias theo cùng cách
posemetrics/keypoints_mAP50-95, metrics/keypoints_mAP50, metrics/keypoints_mAP75, metrics/keypoints_mAP_M, metrics/keypoints_mAP_L, và các key keypoints_AR tương ứng
obbmetrics/mAP50-95, metrics/mAP50, metrics/mAP75, metrics/precision, metrics/recall, cùng các bản sao có hậu tố (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, cùng một key quét mAP

metrics/precision và metrics/recall của OBB không phải alias: chúng là precision và recall thực ở IoU 0.50, lấy tại operating point lỏng nhất (mọi dự đoán vượt qua conf, mặc định 0.001). Các bản sao có hậu tố (OBB) lặp lại cùng bốn giá trị dưới tên theo tác vụ, cùng quy ước với (B) và (M) ở trên.

accuracy_top5 thực ra là top-min(5, num_classes), vì vậy trên dataset ba lớp, nó là top-3 mà mọi sample đều thỏa mãn, nên giá trị là 1.0. Kết quả phân loại cũng cung cấp hai giá trị này dưới dạng các thuộc tính top1 và top5, bên cạnh confusion_matrix.

Key quét của tác vụ point được dựng từ các ngưỡng khoảng cách, vì vậy với giá trị mặc định, nó là metrics/mAP@[0.01:0.10] và key một ngưỡng là metrics/mAP@0.01. Truyền dist_thresholds sẽ thay đổi cả hai chuỗi.

Phần lớn tác vụ còn trả về key fitness, là số đơn mà cơ chế chọn checkpoint tốt nhất sử dụng theo mặc định. Phát hiện, phân đoạn và OBB không có key này; family của chúng được chọn theo metrics/mAP50-95, vốn có trong dictionary trả về. Tư thế không trả về fitness lẫn metrics/mAP50-95; thay vào đó, trainer của tác vụ đặt best_metric_key thành metrics/keypoints_mAP50-95.

Phân loại ImageFolder bổ sung macro metrics/precision, metrics/recall và metrics/f1, lấy trung bình trên các lớp đối tượng có trong nhãn đích đánh giá. Top-1 vẫn là fitness mặc định. Phát hiện còn trả về metrics/best_conf và metrics/best_conf_f1, chọn ngưỡng tối ưu micro-F1 tại IoU 0.50, và đặt các ngưỡng với khóa là tên lớp đối tượng trên metrics.box.best_conf_per_class. Các phát hiện cùng điểm vẫn được nhóm chung; khi hòa chọn ngưỡng cao hơn. Không có F1 dương sẽ cho 0.0. Phân đoạn không cung cấp các khóa ngưỡng này.

Confusion matrix

Kết quả detect, segment và classify mang results.confusion_matrix. Nó được tính ở mọi lần xác thực, dù có ghi biểu đồ hay không, và matrix của nó là một mảng số nguyên lập chỉ mục matrix[predicted, true].

Confusion matrix
from libreyolo import LibreYOLO model = LibreYOLO("LibreYOLO9s.pt")metrics = model.val(data="coco8.yaml") cm = metrics.confusion_matrixprint(cm.matrix.shape)      # (81, 81): 80 lớp đối tượng cộng backgroundprint(cm.class_accuracy())  # tên lớp: tỉ lệ đối tượng tìm thấy được gán lớp đótp, fp = cm.tp_fp()

Với detect và segment, các dự đoán ở độ tin cậy 0.25, hoặc conf nếu cao hơn, được ghép một-một với các box ground truth thuộc bất kỳ lớp nào ở IoU 0.5, theo thứ tự IoU cao nhất trước. Một cặp được đếm ở lớp dự đoán và lớp thật của nó, nên một box đặt đúng chỗ nhưng sai lớp rơi ra ngoài đường chéo. Ma trận có thêm một hàng và cột background: một ground truth không được ghép cặp được đếm ở hàng background, một dự đoán không được ghép cặp ở cột background. Segmentation ghép cặp box, không phải mặt nạ. Với classes=, ground truth của các lớp khác bị bỏ ra.

Các vùng crowd của COCO (iscrowd=1) theo quy tắc mà mAP áp dụng. Một dự đoán mà không ground truth nào cùng lớp khớp, nằm ít nhất một nửa bên trong một vùng crowd cùng lớp (phần giao chia cho diện tích của chính dự đoán), bị bỏ qua thay vì được đếm. box.image_metrics và các ảnh visualize=True dùng cùng ngưỡng và cùng quy tắc crowd. Nhãn định dạng YOLO không có vùng crowd.

Với classify, mỗi ảnh được đếm một lần, ở lớp top-1 của nó so với nhãn, và không có background.

Phương thứcTrả về
summary(normalize=False)Một dict cho mỗi lớp dự đoán, {"Predicted": name, <true class>: value}; với normalize, tỉ lệ của mỗi lớp thật
to_csv(), to_json()Phần tóm tắt dưới dạng văn bản CSV hoặc JSON
to_df()Phần tóm tắt dưới dạng Polars DataFrame; cần pip install polars
tp_fp()True positive theo từng lớp (đường chéo) và false positive (phần còn lại của hàng dự đoán)
nonzero()Các ô có giá trị dưới dạng các mảng (predicted, true, count) thẳng hàng
class_accuracy()Theo từng lớp, tỉ lệ các instance của nó được gán lớp đó; với detection, chỉ tính các đối tượng tìm thấy
plot(normalize=True, save_dir="")Ghi confusion_matrix_normalized.png, hoặc confusion_matrix.png với normalize=False, và trả về đường dẫn

Trên 2,000 lớp đối tượng, ma trận phân loại dày đặc không được dựng: matrix, summary(), các hàm xuất to_*() và plot() phát sinh lỗi, trong khi tp_fp(), nonzero() và class_accuracy() vẫn hoạt động.

Lớp này là libreyolo.validation.ConfusionMatrix, được dựng bằng ConfusionMatrix(nc, iou_thres=0.5, conf_thres=0.25, *, names=None, task="detect"), trong đó task là "detect" hoặc "classify".

Precision, recall và F1 theo từng lớp đối tượng

Kết quả detect và segment mang precision, recall và F1 của từng lớp đối tượng qua các ngưỡng độ tin cậy, ghép cặp ở IoU 0.5.

Đường cong theo từng lớp đối tượng
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,) và (classes, 1000)for index, f1 in zip(box.ap_class_index, box.f1):    print(model.names[int(index)], round(float(f1), 3))

box.px giữ 1000 độ tin cậy, cách đều nhau trên [0, 1]. box.p_curve, box.r_curve và box.f1_curve là các mảng (classes, 1000), mỗi hàng ứng với một phần tử của box.ap_class_index, là các chỉ số lớp đối tượng có ground truth trong split, theo thứ tự tăng dần. box.p, box.r và box.f1 là các giá trị theo từng lớp ở độ tin cậy làm cực đại F1 trung bình trên các lớp đó. Segmentation tính tất cả từ box. Chúng là các mảng rỗng khi lượt chạy không tạo ra đường cong nào.

Chỉ số bounding box theo ảnh

Kết quả phát hiện và phân đoạn vẫn tương thích dictionary và còn cung cấp results.box.image_metrics. Mỗi tên tệp ánh xạ đến precision, recall, f1, tp, fp và fn theo quy tắc ghép cặp của trực quan hóa, kể cả khi tắt trực quan hóa. Phân đoạn đếm bounding box ở đây. Tên tệp trùng dùng đường dẫn đầy đủ sau lần xuất hiện đầu. Mẫu số bằng 0 cho kết quả 0.0. Các bản ghi này không được tổng hợp qua các rank phân tán.

Key tốc độ

Mọi validator đều thêm thời gian:

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

Đây là số mili giây trên mỗi ảnh, lấy trung bình trong lượt chạy. Chúng mô tả máy và cài đặt bạn đã chạy, vì vậy một số liệu lấy từ đây chỉ có ý nghĩa khi được báo cáo cùng phần cứng, kích thước batch và precision.

Backend đánh giá

Metric phát hiện và phân đoạn được tính qua COCO evaluator, còn faster_coco_eval=True, giá trị mặc định, chọn backend C++ khi đã cài package faster-coco-eval. Nếu chưa cài, lượt chạy quay về pycocotools với một cảnh báo cho mỗi process:

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

Backend thực sự chạy được ghi lại trên mô hình dưới dạng last_eval_backend, và CLI báo cáo nó trong đầu ra cho các tác vụ kiểu phát hiện. Đặt LIBREYOLO_FASTER_COCO_EVAL để ghi đè giá trị cấu hình từ môi trường.

iou_thresholds chỉ được áp dụng trên đường dẫn OBB. Đường dẫn COCO đánh giá theo lượt quét cố định riêng từ 0.50 đến 0.95 và bỏ qua giá trị này.

Validation loss

Theo mặc định, xác thực chỉ báo cáo độ chính xác. val_loss=True còn tính objective huấn luyện của family trên các batch xác thực.

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

Nó phát ra metrics/loss cùng một metrics/loss/<component> cho mỗi thành phần, được gán trọng số chính xác như khi huấn luyện, vì vậy các thành phần cộng lại thành tổng. Qua logger, chúng xuất hiện dưới dạng val/loss và val/loss/<component>, còn libreyolo monitor đặt metrics/loss chồng lên train/loss.

Các thành phần là thành phần riêng của family:

Tác vụFamilyThành phần
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

Tùy chọn này mặc định tắt vì việc gán target làm tăng thời gian và bộ nhớ xác thực. Validator dùng lại đầu ra mô hình đã tạo cho metric độ chính xác thay vì chạy forward pass thứ hai, chạy trong no_grad trên mô hình đánh giá hoặc EMA, và trong huấn luyện multi-GPU, nó được tính cục bộ trên rank 0 mà không có collective. Việc chọn checkpoint tốt nhất vẫn dựa trên metric độ chính xác.

Có ba điều được chủ ý không thực hiện. Thứ nhất, nó không bao giờ gồm các thành phần khử nhiễu tương phản vì chúng cần ground truth tại thời điểm forward, còn forward xác thực không nhận dữ liệu đó. Thứ hai, nó báo cáo mô hình ở evaluation mode, vì vậy khi forward train và eval của một family thực sự khác nhau ở statistic BatchNorm hoặc stochastic depth, con số phản ánh eval mode; đây là phép so sánh có chủ ý. Thứ ba, tác vụ chưa được family triển khai sẽ phát sinh lỗi cấu hình khi thiết lập thay vì âm thầm bỏ qua:

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

FOMO là ngoại lệ không thay đổi gì: validator của family này luôn tính loss đó, và val_loss=True chỉ ảnh hưởng tới các key dùng để công bố.

Không thể kết hợp xác thực có augmentation với validation loss; yêu cầu cả hai sẽ phát sinh lỗi.

Các tệp được ghi khi xác thực

val() luôn ghi config.yaml vào thư mục lưu, mặc định là runs/val/<model>_<size>_<timestamp> khi không cung cấp save_dir. project, name và exist_ok chọn thư mục này theo cách huấn luyện vẫn làm: project/name, với hậu tố tăng dần trừ khi exist_ok=True.

Ghi dự đoán theo định dạng 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 ghi predictions.json cho phát hiện, còn phân đoạn ghi predictions_bbox.json cùng predictions_masks.json. OBB không hỗ trợ và sẽ báo rõ.

save_plots=True, hoặc alias plots=True của nó, ghi vào thư mục con plots/ và cần matplotlib, được cài bằng pip install "libreyolo[plots]". Phát hiện tạo box_metrics.png, biểu đồ AP và recall theo từng lớp, đường cong precision-recall và confidence, các đường cong F1 theo từng lớp trong f1_conf_box.png, confusion matrix dưới dạng số đếm trong confusion_matrix.png và dưới dạng tỉ lệ của mỗi lớp thật trong confusion_matrix_normalized.png, cùng ảnh sample đã chú thích khi cài OpenCV. Phân đoạn thêm bản sao phía mặt nạ của biểu đồ metric, các biểu đồ theo từng lớp và các đường cong precision-recall và confidence; các đường cong F1 và confusion matrix vẫn ở mức box. Tư thế có bộ metric và đường cong riêng. Phân loại ghi hai tệp confusion matrix, trừ khi trên 2,000 lớp đối tượng. Các validator khác không triển khai biểu đồ; ngữ nghĩa, toàn cảnh, độ sâu, pháp tuyến, cạnh, phục hồi, matting, OCR, OBB và point đều không ghi gì ở đó. Lỗi vẽ biểu đồ sẽ cảnh báo và không bao giờ dừng lượt chạy.

visualize=True ghi ảnh TP/FP/FN của bounding box có xét lớp đối tượng cho phát hiện và phân đoạn, hoặc ảnh so sánh nhãn với top-1 cho phân loại ImageFolder, vào visualize/errors/ và visualize/correct/. Ghép cặp dùng IoU 0.5 và độ tin cậy max(0.25, conf). Mặc định là visualize=False, show_labels=True và show_conf=True. Các tác vụ không hỗ trợ và đánh giá clip V-JEPA 2 từ chối trực quan hóa.

plot_samples=8 giới hạn biểu đồ ảnh mẫu riêng; 0 tắt nó và -1 giữ mọi ảnh. Điều này không thay đổi chỉ số hay đầu ra trực quan hóa.

Xác thực trong khi huấn luyện

Quá trình huấn luyện xác thực mỗi eval_interval epoch, và luôn xác thực sau epoch cuối cùng, trên split val của dataset, và các metric tạo ra điều khiển việc chọn best.pt, early stop theo patience và các key val/ trong mọi logger. Việc xác thực chạy trên trọng số EMA khi bật EMA. Các tệp của nó được ghi vào thư mục val/ bên trong lượt chạy. val=False tắt xác thực trong khi huấn luyện, kể cả ở epoch cuối.

Xem Siêu tham số để biết eval_interval, patience và save_plots, và Logger thí nghiệm để biết các con số được đưa tới đâu.

  • Xem Dataset để biết các key split và định dạng mà validator đọc.

Đã kiểm chứng với LibreYOLO v1.6.0.