검증 및 지표

검증(validation)은 모델을 val()을 통해 나눈 데이터셋에 실행하고, 메트릭 키와 실수값(Float value)으로 이루어진 평면 딕셔너리를 반환합니다. 키는 문자열이며, 어떤 키를 얻는지는 모델 계열이 아니라 작업(task)에 따라 달라집니다.

검증을 실행

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입니다. 모든 키는 문자 그대로이므로 위치가 아니라 이름으로 읽으십시오. 탐지, 분할, 분류에서는 클래스별 결과를 속성으로 함께 담는 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가 포함됩니다. CUDA에서 half=True이면 검증은 amp_dtype의 오토캐스트 아래에서 실행되고, bfloat16 출력은 후처리 전에 float32로 변환됩니다. amp_dtype="bfloat16"으로 학습할 때도 검증은 같은 방식으로 실행됩니다.

agnostic_nms=True는 iou를 넘어 겹치는 박스 중 클래스와 관계없이 점수가 가장 높은 것 하나만 유지합니다. 이 단계는 계열이 끝낸 탐지 결과에 대해 classes= 뒤에 실행되므로, mAP, 혼동 행렬, 곡선, 이미지별 개수가 모두 같은 박스를 채점합니다. 탐지와 분할을 지원하며, 다른 작업은 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)로 나타나고, 두 쌍 모두 detect의 별칭 값과 동일합니다: (B) 쌍은 박스 mAP50-95와 박스 AR@100이며, (M) 쌍은 마스크 mAP50-95와 마스크 AR@100입니다.

작업열쇠
탐지하다metrics/mAP50-95, metrics/mAP50, metrics/mAP75, 위의 크기 및 리콜 분류와 함께
세그먼트위의 탐지 키의 마스크 버전(접미사가 없는 키는 마스크임); precision/recall는 (B)/(M)로만 존재하며, 둘 다 동일하게 별칭이 지정됨
자세metrics/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)가 접미사로 붙은 복사본
분류하다metrics/accuracy_top1, metrics/accuracy_top5
의미론의metrics/mIoU, metrics/pixel_accuracy
파노프틱metrics/PQ, metrics/SQ, metrics/RQ, metrics/PQ_things, metrics/PQ_stuff, metrics/categories
깊이metrics/abs_rel, metrics/rmse, metrics/delta1, metrics/delta2, metrics/delta3
보통metrics/mean_angular_error, metrics/median_angular_error, metrics/within_11_25, metrics/within_22_5, metrics/within_30
모서리metrics/ODS, metrics/OIS, metrics/best_threshold
복원하다metrics/PSNR, metrics/SSIM
매트metrics/MAE, metrics/Smeasure
광학 문자 인식metrics/det_precision, metrics/det_recall, metrics/det_hmean, metrics/e2e_precision, metrics/e2e_recall, metrics/e2e_f1, metrics/rec_1-NED
점metrics/precision, metrics/recall, metrics/f1, metrics/MLE, metrics/MAE, metrics/RMSE, 그리고 mAP 스윕 키

OBB의 metrics/precision와 metrics/recall는 별칭이 아닙니다: 이들은 실제 정밀도와 IoU 0.50에서의 재현율로, 가장 느슨한 작동 지점에서 취한 값입니다(모든 conf를 통과한 예측, 기본값 0.001). (OBB)로 끝나는 복사본들은 작업별 이름 아래 같은 네 가지 값을 반복하며, 위의 (B)와 (M)와 동일한 규칙을 따릅니다.

accuracy_top5는 실제로 top-min(5, num_classes)이므로, 세 가지 클래스 데이터셋에서는 top-3가 되며, 이는 모든 샘플이 만족하므로 1.0으로 읽습니다. 분류 결과는 이 두 값을 confusion_matrix 옆에 top1, top5 속성으로도 제공합니다.

점 작업의 스윕 키는 거리 임계값으로 작성되므로, 기본값으로는 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을 유지합니다. 탐지는 IoU 0.50에서 micro-F1을 최대화하는 임계값을 선택하여 metrics/best_conf, metrics/best_conf_f1도 반환하며, 클래스 이름을 키로 하는 임계값은 metrics.box.best_conf_per_class에 넣습니다. 점수가 같은 탐지는 함께 처리하며, 동률이면 더 높은 임계값을 선택합니다. 양수 F1이 없으면 0.0을 반환합니다. 분할은 이 임계값 키를 제공하지 않습니다.

혼동 행렬

탐지, 분할, 분류 결과는 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개와 backgroundprint(cm.class_accuracy())  # 클래스 이름: 찾아낸 객체 중 해당 클래스로 분류된 비율tp, fp = cm.tp_fp()

탐지와 분할에서는 신뢰도 0.25, 또는 conf가 더 높으면 conf 이상의 예측을 IoU 0.5에서 IoU가 높은 순서로 클래스에 관계없이 정답 박스와 일대일로 짝지웁니다. 짝은 예측 클래스와 실제 클래스 기준으로 집계되므로, 위치는 맞지만 클래스가 틀린 박스는 대각선 밖에 놓입니다. 행렬에는 background 행과 열이 추가로 있습니다. 짝이 없는 정답은 background 행에, 짝이 없는 예측은 background 열에 집계됩니다. 분할은 마스크가 아니라 박스를 짝지웁니다. classes=를 쓰면 다른 클래스의 정답은 제외됩니다.

COCO crowd 영역(iscrowd=1)은 mAP가 적용하는 규칙을 따릅니다. 같은 클래스의 정답과 짝이 되지 않았고 같은 클래스 crowd 영역 안에 절반 이상(예측 자신의 면적에 대한 교집합 기준) 놓인 예측은 집계되지 않고 무시됩니다. box.image_metrics와 visualize=True 이미지도 같은 임계값과 같은 crowd 규칙을 사용합니다. YOLO 형식 레이블에는 crowd 영역이 없습니다.

분류에서는 각 이미지를 top-1 클래스와 레이블 기준으로 한 번 집계하며 background는 없습니다.

메서드반환값
summary(normalize=False)예측 클래스마다 {"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

탐지와 분할 결과는 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의 항목마다 한 행입니다. box.ap_class_index는 분할에 정답이 있는 클래스 인덱스를 오름차순으로 나열한 것입니다. box.p, box.r, box.f1은 그 클래스들에 대한 평균 F1을 최대화하는 신뢰도에서의 클래스별 값입니다. 분할도 이 모두를 박스로 계산합니다. 실행에서 곡선이 만들어지지 않았다면 빈 배열입니다.

이미지별 바운딩 박스 지표

탐지 및 분할 결과는 딕셔너리 호환성을 유지하며 results.box.image_metrics도 제공합니다. 각 파일 이름은 시각화를 끈 경우에도 시각화 매칭 규칙으로 계산한 precision, recall, f1, tp, fp, fn에 매핑됩니다. 분할도 여기서는 바운딩 박스를 셉니다. 기본 파일 이름이 중복되면 첫 번째 이후부터 전체 경로를 사용합니다. 분모가 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++ 백엔드를 선택합니다. 설치되지 않은 경우, 실행은 프로세스당 하나의 경고와 함께 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 범위로 평가하며 값을 무시합니다.

검증 손실

기본적으로 검증은 정확도만 보고합니다. 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를 오버레이합니다.

구성 요소는 계열 자신의 것입니다:

작업계열들구성 요소
탐지하다yolo9, yolo9_p2, yolo9_e2ebox, cls, dfl
탐지하다yolonascls, iou, dfl
탐지하다rfdetrce, bbox, giou
탐지하다rtdetr, rtdetrv2vfl, bbox, giou
탐지하다dfinevfl, bbox, giou, fgl, ddf
탐지하다domedetrvfl, bbox, giou, fgl, ddf, defe_density, defe_reg
탐지하다deim, deimv2, rtdetrv4, ecmal, bbox, giou, fgl, ddf
탐지하다rtmdetcls, bbox
탐지하다picodetcls, bbox, dfl
탐지하다yoloxiou, obj, cls, l1
탐지하다yolo7iou, obj, cls
점fomoce
분류하다resnet, convnext, mobilenetv4, efficientnetv2ce
의미론의segformer, lingbotvision, dinov2sem
복원하다nafnetrestore

기본적으로 비활성화되어 있습니다. 목표 할당이 검증에 시간과 메모리를 추가하기 때문입니다. 검증기는 두 번째 순방향 계산을 수행하지 않고 정확도 지표를 위해 이미 생성된 모델 출력을 재사용하며, 평가 또는 EMA 모델에서는 no_grad 아래에서 실행되고, 다중 GPU 학습에서는 수집 작업 없이 rank 0에서 로컬로 계산됩니다. 최적 체크포인트 선택은 정확도 지표에 따라 유지됩니다.

의도적으로 하지 않는 세 가지가 있습니다. 첫째, 대비-디노이징(contrastive-denoising) 항목을 포함하지 않는데, 이는 전방 계산 시 실제 값이 필요하고 검증 전방 계산에서는 필요하지 않기 때문입니다. 둘째, 평가 모드 모델을 보고하기 때문에, 만약 어떤 계열의 학습 및 평가 전방 계산이 실제로 다르다면(BatchNorm 통계나 확률적 깊이(stochastic depth)에서), 그 수치는 평가 모드(eval mode)를 반영합니다; 이것이 의도된 비교입니다. 셋째, 계열가 구현하지 않은 작업(task)에 대해서는 조용히 건너뛰지 않고 설정(setup) 시 구성 오류(configuration error)를 발생시킵니다:

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를 자신의 저장 디렉토리에 작성하며, save_dir가 제공되지 않은 경우 기본적으로 runs/val/<model>_<size>_<timestamp>를 사용합니다. 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_conf_box.png의 클래스별 F1 곡선, 개수로 된 confusion_matrix.png와 각 실제 클래스의 비율로 된 confusion_matrix_normalized.png의 혼동 행렬, 그리고 OpenCV가 설치된 경우 주석이 달린 샘플 이미지를 가져옵니다. 분할(segmentation)은 지표 차트, 클래스별 차트, 정밀도-재현율 및 신뢰도 곡선의 마스크 측 사본을 추가하며, F1 곡선과 혼동 행렬은 박스 수준으로 유지됩니다. 포즈(pose)는 자체 메트릭 및 곡선 세트를 가져옵니다. 분류는 클래스가 2,000개를 넘는 경우를 제외하고 두 혼동 행렬 파일을 기록합니다. 다른 검증기는 플롯을 구현하지 않습니다. 의미론적, 파노라마, 깊이, 노멀, 엣지, 복원, 매트, OCR, OBB 및 포인트는 모두 해당 위치에 아무것도 작성하지 않습니다. 플로팅 실패는 경고만 하며 실행을 절대 중단하지 않습니다.

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은 모든 이미지를 유지합니다. 지표나 시각화 출력에는 영향을 주지 않습니다.

학습 중 검증

학습은 데이터셋의 val 분할에 대해 매 eval_interval 에폭마다, 그리고 마지막 에폭 뒤에는 항상 검증을 수행하며, 생성되는 지표는 best.pt 선택, patience 조기 종료, 그리고 모든 로거의 val/ 키를 결정하는 데 사용됩니다. EMA가 켜져 있을 때 검증은 EMA 가중치로 실행됩니다. 검증 파일은 실행 내부의 val/ 디렉토리에 저장됩니다. val=False는 마지막 에폭을 포함해 학습 중 검증을 끕니다.

eval_interval, patience 및 save_plots에 대해서는 하이퍼파라미터를 참조하고, 숫자가 어디에 들어가는지에 대해서는 실험 로거를 참조하십시오.

  • 데이터셋은 분할 키와 포맷 검증기를 읽습니다.

LibreYOLO v1.6.0에서 검증되었습니다.