Model Validation with Ultralytics YOLO#
Introduction#
Validation is a critical step in the machine learning pipeline, allowing you to assess the quality of your trained models. Val mode in Ultralytics YOLO26 provides tools and metrics for evaluating object detection models and every other supported task. This guide explains how to use Val mode to confirm that your models are accurate and reliable.
See the unreleased YOLO27 preview for preliminary validation results.
Watch: Ultralytics Modes Tutorial: Validation
Why Validate with Ultralytics YOLO?#
Reasons to use YOLO26's Val mode:
- Precision: Get accurate metrics like mAP50, mAP75, and mAP50-95 to evaluate your model comprehensively.
- Convenience: Use built-in features that remember training settings, simplifying the validation process.
- Flexibility: Validate your model with the same or different datasets and image sizes.
- Hyperparameter Tuning: Use validation metrics to fine-tune your model for better performance.
Key Features of Val Mode#
Notable features of YOLO26's Val mode:
- Automated Settings: Models remember their training configurations for straightforward validation.
- Multi-Metric Support: Evaluate your model with a range of accuracy metrics.
- CLI and Python API: Validate from the command-line interface or the Python API, whichever you prefer.
- Data Compatibility: Works with the datasets used during training as well as custom datasets.
- YOLO26 models automatically remember their training settings, so
yolo val model=path/to/best.ptorYOLO("path/to/best.pt").val()validates at the training image size on the original dataset. Official weights fall back to the task default dataset; passdatato override.
Usage Examples#
Validate the accuracy of a trained YOLO26n model. No arguments are needed, as the model retains its training data and arguments as model attributes: path/to/best.pt validates on the dataset it was trained on. Official weights record a training dataset path that doesn't exist on your machine, so they fall back to the task default coco8.yaml with a warning. Pass data to validate on another dataset.
On Windows, you may receive a RuntimeError when launching the validation as a script. Add an if __name__ == "__main__": block before your validation code to resolve it.
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n.pt") # load an official model
model = YOLO("path/to/best.pt") # load a custom model
# Validate the model
metrics = model.val() # no arguments needed, dataset and settings remembered
metrics.box.map # map50-95
metrics.box.map50 # map50
metrics.box.map75 # map75
metrics.box.maps # mAP50-95 per class; classes absent from the val set hold the overall mAP
metrics.box.ap_class_index # class indices that were actually evaluated
metrics.box.image_metrics # per-image metrics dictionary with precision, recall, F1, TP, FP, and FNArguments for YOLO Model Validation#
When validating YOLO models, several arguments can be adjusted to tailor the evaluation process. These arguments control aspects such as input image size, batch processing, and performance thresholds. Each argument is described below.
| Argument | Type | Default | Description |
|---|---|---|---|
data | str | None | Specifies the path to the dataset YAML (e.g., coco8.yaml), which should include the path to the validation data. Classification instead takes a dataset directory or a built-in dataset name (e.g., imagenet10). |
imgsz | int | 640 | Defines the size of input images. All images are resized to this dimension before processing. Larger sizes may improve accuracy for small objects but increase computation time. |
batch | int | 16 | Sets the number of images per batch. Higher values utilize GPU memory more efficiently but require more VRAM. Adjust based on available hardware resources. |
save_json | bool | False | If True, saves the results to a JSON file for further analysis, integration with other tools, or submission to evaluation servers like COCO. On detection datasets it also evaluates the predictions with faster-coco-eval and reports small-, medium-, and large-object mAP, logged during training as metrics/mAP_small(B), metrics/mAP_medium(B), and metrics/mAP_large(B) in results.csv. For semantic segmentation it instead saves PNG class masks under results/, keeping image subdirectories. |
conf | float | 0.001 | Sets the minimum confidence threshold for detections. Lower values increase recall but may introduce more false positives. Precision-recall curves, mAP, and detection confusion matrices all use this value; a higher conf, such as 0.25, gives a matrix closer to prediction output but can lower mAP. Summary precision and recall use the max-F1 confidence, so they may differ from values derived from confusion_matrix.png. Defaults to 0.01 for OBB validation to reduce memory usage. |
iou | float | 0.7 | Sets the Intersection Over Union threshold for Non-Maximum Suppression. Controls duplicate detection elimination. |
max_det | int | 300 | Limits the maximum number of detections per image. For detect, segment, pose, and OBB, left at 300 it is raised to the largest labeled-object count in the validated split when an image exceeds it, with a warning; any other value is kept, with a warning that recall may be capped when an image exceeds it. |
quantize | int or str | None | Validation precision: 16/"fp16" and 32/"fp32"/unset select FP16 or FP32 compute for PyTorch and TorchScript models (FP32 on CPU); other formats use the precision their artifact and runtime select. At 16 OpenVINO still FP16-rounds the input on the client and widens it back to FP32, without changing the runtime precision. INT8/PTQ quantization is configured during export, then used by validating the exported model. Replaces the deprecated half flag. |
device | str | None | Specifies the device for validation (cpu, cuda:0, npu, npu:0, etc.). When None, automatically selects the best available device. Multiple CUDA devices can be specified with comma separation. |
dnn | bool | False | If True, uses the OpenCV DNN module for ONNX model inference, offering an alternative to PyTorch inference methods. |
plots | bool | True | When set to True, generates and saves plots of predictions versus ground truth, confusion matrices, and PR curves for visual evaluation of model performance. |
classes | list[int] | None | Specifies a list of class IDs to evaluate. Useful for filtering out and focusing only on certain classes during evaluation. |
rect | bool | True | If True, batches similar aspect ratios into rectangular shapes. Adds half a stride before rounding each dimension up to a stride multiple (no extra half-stride for semantic). With stride 32, a 640×640 image at imgsz=640 becomes 672×672 with a 16 px offset, while predict uses 640×640, so metrics can differ. rect=False matches predict for square images. Ignored for depth and RT-DETR, which stretch images to an imgsz square. |
split | str | 'val' | Determines the dataset split to use for validation (val, test, or train). Allows flexibility in choosing the data segment for performance evaluation. |
fraction | float, int, or list | 1.0 | Subset of the validated split. With a [train, val, test] list, the entry matching split applies (1 = full split, integers above 1 = image counts; omitted entries are full). A scalar applies only with split=train; val and test then use the full split. |
project | str | None | Name of the project directory where validation outputs are saved. A relative path is placed under runs_dir/<task>, while an absolute path is used as-is. |
name | str | None | Name of the validation run. Used for creating a subdirectory within the project folder, where validation logs and outputs are stored. |
verbose | bool | True | If True, displays detailed information during the validation process, including per-class metrics, batch progress, and additional debugging information. |
save_txt | bool | False | If True, saves detection results in text files, with one file per image, useful for further analysis, custom post-processing, or integration with other systems. |
save_conf | bool | False | If True, includes confidence values in the saved text files when save_txt is enabled, providing more detailed output for analysis and filtering. |
workers | int | 8 | Number of worker threads for data loading. Higher values can speed up data preprocessing but may increase CPU usage. Setting to 0 uses main thread, which can be more stable in some environments. |
augment | bool | False | Enables test-time augmentation (TTA) during validation, potentially improving detection accuracy at the cost of inference speed by running inference on transformed versions of the input. Only available for Ultralytics PyTorch models. |
agnostic_nms | bool | False | Enables class-agnostic Non-Maximum Suppression, suppressing lower-scoring overlapping boxes regardless of their predicted class. Useful for instance-focused applications. With NMS-free inference (nms=False on YOLO26 or YOLOv10), this only prevents the same detection from appearing with multiple class labels (IoU=1.0 duplicates) and does not perform IoU-threshold-based suppression between distinct boxes. |
single_cls | bool | False | Treats all classes as a single class during validation. Useful for evaluating model performance on binary detection tasks or when class distinctions aren't important. |
visualize | bool | False | Visualizes the ground truths, true positives, false positives, and false negatives for each image. Useful for debugging and model interpretation. |
show_labels | bool | True | Displays class labels in validation visualizations when visualize=True. Set to False for a cleaner view of matches and errors. |
show_conf | bool | True | Displays confidence scores in validation visualizations when visualize=True. Set to False for a cleaner view of matches and errors. |
compile | bool or str | False | Enables PyTorch 2.x torch.compile graph compilation with backend='inductor'. Accepts True → "default", False → disables, or a string mode such as "default", "reduce-overhead", "max-autotune-no-cudagraphs". Falls back to eager with a warning if unsupported. |
channels_last | bool | None | Uses the channels_last (NHWC) memory format for native PyTorch validation. None automatically enables it on oneDNN-enabled Linux and Windows x86 CPUs with PyTorch 1.13 or newer, False disables it, and True requests it on supported x86 CPU or CUDA devices. ARM64, MPS, older PyTorch versions, CPUs without oneDNN, and exported formats remain unchanged; validation during training keeps the training model layout. |
nms | bool, optional | None | Runs one-to-many inference with NMS by default (None or True). Set False to use the NMS-free one-to-one head when available. See the End-to-End Detection guide for details. |
Adjusting these settings to your specific needs and resources helps you strike the right balance between evaluation accuracy and speed.
Rectangular validation geometry (rect)#
Static exports use their recorded (height, width) input shape, including non-square exports, for validation. For example,
YOLO("yolo26n.onnx").val(data="coco8.yaml") uses a 384×640 input if the model was exported with imgsz=(384, 640).
For detection, instance segmentation, pose, and OBB, rectangular validation (rect=True) rounds each batch dimension up using ceil(shape * imgsz / stride + 0.5) * stride, where shape is the batch's normalized height or width. The resulting padding is split between opposite sides. For example, a square 640×640 image validated at imgsz=640 with stride 32 uses a 672×672 input with 16 px of padding on each side, while predict() uses 640×640 without padding.
This difference can affect validation metrics. For square, stride-aligned inputs, model.val(rect=False) matches the geometry of predict() and square fixed-shape exports. During training, these YOLO tasks use rectangular validation batches regardless of the training rect setting, so model.train(rect=False) still selects best.pt using rectangular validation. Other tasks differ: semantic segmentation adds no extra validation padding, depth disables rectangular validation, classification ignores rect, and RT-DETR uses its own dataset builder with rect=False.
Example Validation with Arguments#
Watch: How to Export Model Validation Results in CSV, JSON, SQL, Polars DataFrame & More
The examples below run YOLO model validation with custom arguments in Python and the CLI.
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n.pt")
# Customize validation settings
metrics = model.val(data="coco8.yaml", imgsz=640, batch=16, conf=0.25, iou=0.7, device="0")You can also export confusion matrix results in different formats, for example as a DataFrame:
from ultralytics import YOLO
model = YOLO("yolo26n.pt")
results = model.val(data="coco8.yaml", plots=True)
print(results.confusion_matrix.to_df())Validation stores per-image precision, recall, F1, TP, FP, and FN metrics (at IoU threshold 0.5) for all tasks
except classification. Access them through results.box.image_metrics for detection and OBB, results.seg.image_metrics
for segmentation, and results.pose.image_metrics for pose after validation completes.
from ultralytics import YOLO
# Load a model
model = YOLO("yolo26n.pt")
# Validate and access per-image metrics
results = model.val(data="coco8.yaml")
# image_metrics is a dictionary with image filenames as keys
print(results.box.image_metrics)
# Output: {'image1.jpg': {'precision': 0.85, 'recall': 0.92, 'f1': 0.88, 'tp': 17, 'fp': 3, 'fn': 1}, ...}
# Access metrics for a specific image
results.box.image_metrics["image1.jpg"] # {'precision': 0.85, 'recall': 0.92, 'f1': 0.88, 'tp': 17, 'fp': 3, 'fn': 1}Each entry in image_metrics contains the following keys:
| Key | Description |
|---|---|
precision | Precision score for the image (tp / (tp + fp)). |
recall | Recall score for the image (tp / (tp + fn)). |
f1 | Harmonic mean of precision and recall. |
tp | Number of true positives for the image. |
fp | Number of false positives for the image. |
fn | Number of false negatives for the image. |
This feature is available for detection, segmentation, pose, and OBB tasks.
The returned metrics object also exposes export helpers from DataExportMixin for downstream analysis:
| Method | Return Type | Description |
|---|---|---|
summary() | List[Dict[str, Any]] | Converts validation results to a summarized dictionary. |
to_df() | DataFrame | Returns the validation results as a structured Polars DataFrame. |
to_csv() | str | Exports the validation results in CSV format and returns the CSV string. |
to_json() | str | Exports the validation results in JSON format and returns the JSON string. |
What's Next#
Happy with the metrics? Export the model to a deployment format. If accuracy is off, go back and retrain with different hyperparameters or more training data.
FAQ#
To validate your YOLO26 model, you can use the Val mode provided by Ultralytics. For example, using the Python API, you can load a model and run validation with:
from ultralytics import YOLO # Load a model model = YOLO("yolo26n.pt") # Validate the model metrics = model.val() print(metrics.box.map) # map50-95Alternatively, you can use the command-line interface (CLI):
yolo detect val model=yolo26n.pt data=coco8.yamlFor further customization, you can adjust various arguments like
imgsz,batch, andconfin both Python and CLI modes. Check the Arguments for YOLO Model Validation section for the full list of parameters.YOLO26 model validation provides several key metrics to assess model performance. These include:
- mAP50 (mean Average Precision at IoU threshold 0.5)
- mAP75 (mean Average Precision at IoU threshold 0.75)
- mAP50-95 (mean Average Precision across multiple IoU thresholds from 0.5 to 0.95)
Using the Python API, you can access these metrics as follows:
metrics = model.val() # assumes `model` has been loaded print(metrics.box.map) # mAP50-95 print(metrics.box.map50) # mAP50 print(metrics.box.map75) # mAP75 print(metrics.box.maps) # mAP50-95 per class; classes absent from the val set hold the overall mAP print(metrics.box.ap_class_index) # class indices that were actually evaluated print(metrics.box.image_metrics) # per-image metrics dictionary with precision, recall, F1, TP, FP, and FNReview all of these metrics for a complete performance evaluation.
Using Ultralytics YOLO for validation provides several advantages:
- Precision: YOLO26 offers accurate performance metrics including mAP50, mAP75, and mAP50-95.
- Convenience: The models remember their training settings, making validation straightforward.
- Flexibility: You can validate against the same or different datasets and image sizes.
- Hyperparameter Tuning: Validation metrics help in fine-tuning models for better performance.
These benefits help you evaluate models thoroughly and optimize them.
Yes, you can validate your YOLO26 model using a custom dataset. Specify the
dataargument with the path to your dataset YAML, which should include the path to the validation data. Classification instead takes a dataset directory or a built-in dataset name (e.g.,imagenet10).NoteValidation is performed using the model's own class names, which you can view using
model.names, and which may differ from those the dataset defines.Example in Python:
from ultralytics import YOLO # Load a model model = YOLO("yolo26n.pt") # Validate with a custom dataset metrics = model.val(data="path/to/your/custom_dataset.yaml") print(metrics.box.map) # map50-95Example using CLI:
yolo val model=yolo26n.pt data=path/to/your/custom_dataset.yamlFor more customizable options during validation, see the Example Validation with Arguments section.
To save the validation results to a JSON file, you can set the
save_jsonargument toTruewhen running validation. This can be done in both the Python API and CLI.Example in Python:
from ultralytics import YOLO # Load a model model = YOLO("yolo26n.pt") # Save validation results to JSON metrics = model.val(save_json=True)Example using CLI:
yolo val model=yolo26n.pt save_json=TrueOn detection datasets,
save_json=Truealso reports small-, medium-, and large-object mAP throughfaster-coco-eval. Check the Arguments for YOLO Model Validation for more details.
Comments279
Ask a question, share your results, or help someone else.
BedoHatem
I have a couple of models (a mix of object detection and segmentation), so I want to run them on the same validation dataset to compare them properly. The exact tasks for the seg and obj-det models are the same at a certain level, so I'm aware that seg models give a B-Box and Mask, while obj-det gives just a B-Box.
With that said, will a segmentation dataset work on both seg and obj-det models ? Or should i make a seg and a obj-det version of the same dataset, so i can use it to equally validate the models ?
Thanks in Advance
1BedoHatem
I tested it. It seems you can use a segmentation dataset to validate an obj-det model, as the seg datasets include B-Boxes and Masks of the classes.
1
Glenn JocherUltralytics(edited)@BedoHatem yes, you're correct! Segmentation datasets can be used to validate object detection models because they contain the bounding box annotations needed for detection evaluation. The segmentation masks are simply ignored when the dataset is used with a detection model.
This flexibility is an advantage of the YOLO annotation format - the additional segmentation data doesn't interfere with detection evaluation. For the most accurate comparison between models, using the same validation dataset ensures you're evaluating performance on exactly the same ground truth data.
@417dq the recall reported by
val()is taken at the confidence value that maximizes F1, while the confusion matrix is built at the validationconf(0.001 by default) with an IoU matching threshold of 0.45, so the two can differ. The metrics output fromval()is the reference for your model's performance.
Cyeden
请问如果验针集是已经被多尺度分割了,那么再进行验证的时候imgsz应该设置为不同尺度验证的逻辑吗?例如: if name == 'main': model = YOLO(r'C:\Users\Lazy\Desktop\yolo_detect\weights\best.pt')
multi_scale_sizes = [640, 800, 1024, 1280] for size in multi_scale_sizes: model.val( data='ultralytics/cfg/datasets/DOTAv1.yaml', split='val', imgsz=size, batch=16, project='runs/val', name=f'v8n-obb-LSKNet_prev8x-obbpt_{size}', )1
Glenn JocherUltralytics@Cyeden for multi-scale validation, you can indeed set
imgszto different scales within a loop. This approach allows you to evaluate the model's performance across various image sizes. Your implementation looks correct. Ensure you are using the latest version of the Ultralytics package to avoid any potential issues. For more details, you can refer to the validation documentation.
YunYeTang
hi, when I use yolov8-obb to validate DOTAv1, I found that confusion matrix is empty. Does it mean that confusion matrix is not supported in OBB validation?
1
Glenn JocherUltralytics(edited)Hi there! 👋
The confusion matrix is supported for OBB validation in current Ultralytics versions. If yours is empty, update with
pip install -U ultralyticsand re-run validation withplots=True. If it is still empty, please share youryolo checksoutput and the validation command so we can look into it.In the meantime, you can still rely on the other validation metrics such as mAP, precision, and recall.
YunYeTang
thank u very much
Glenn JocherUltralytics(edited)Hey there! 🚀
Thank you for reaching out! The confusion matrix is supported for OBB validation in current Ultralytics versions. If yours is empty, update with
pip install -U ultralyticsand re-run validation withplots=True; if it is still empty, share youryolo checksoutput and validation command so we can look into it.For a comprehensive evaluation you can also rely on the other metrics provided during validation, such as mAP, precision, and recall. Cheers! 🌟
xyzxyzxyzxyzxz
I want to read this page in English. Why it automatically become Chinese even though I click "GB English".
Glenn JocherUltralyticsIt looks like you’re on the Chinese locale (the URL contains
"/zh/"). Remove"/zh/"to view the English version, or use the top‑right language selector (GB English) and hard‑refresh; also ensure your browser’s auto‑translate is disabled.xyzxyzxyzxyzxz
Whether I remove "/zh/" in the URL or click "GB English", it will automatically turn to the Chinese page that is "https://docs.ultralytics.com/zh/modes/val/#how-do-i-save-validation-results-to-a-json-file-in-yolo11". But if I click other language such as Japanese, it will show Japanese correctly. Not only this page, other pages have the same problem. And turning on incognito mode don't work either.
Glenn JocherUltralyticsThanks for the detailed description—that behavior sounds like a docs locale‑routing bug on our side rather than anything you can fix locally; we’ll get it forwarded to the web/docs team, and in the meantime could you confirm whether going directly to the English URL Model Validation with Ultralytics YOLO (English) still forces you back to Chinese and share your OS + browser version so we can reproduce it?
xyzxyzxyzxyzxz
Yes. It will go to Chinese page "https://docs.ultralytics.com/zh/modes/val/" when I click the link you give. My OS is Windows 11 Professional Edition, 25H2, 26200.7171. And my browser is Chrome 142.0.7444.176. My system language is Chinese.
Glenn JocherUltralyticsThanks for the extra details—that confirms this is an issue on the docs side, likely tied to your system/browser language being Chinese and our locale detection forcing
/zh/even when you pick English. I’ve passed this to the web/docs team to investigate; as a temporary workaround you can try using a browser whose interface language is set to English (or move English to the top of Chrome’s language preferences) so the site stops auto‑redirecting to the Chinese locale.
AA278-HUB
I have a model trained on a dataset containing four classes (car, bus, motorbike, and trunk). Now, I have a new dataset with only one class (vehicle). How can I validate this model using the new dataset, given that I only care about whether the model can identify the vehicle and its position, without concern for the specific type of vehicle?
AA278-HUB
f I want to change the validation rules in this specific situation, which .py files need to be modified
Glenn JocherUltralytics@liujixingit
save_txtwrites normalized YOLOxywh(center x/y, width, height) relative to the original image size; recover pixelxyxyvia the originalW,Hthen center→corner conversion, e.g.:# line format: class x y w h [conf] cls, x, y, w, h, *rest = map(float, line.split()) x1 = (x - w/2) * W; y1 = (y - h/2) * H x2 = (x + w/2) * W; y2 = (y + h/2) * HFunction details are in the save_one_txt reference and the
save_txtformat is noted under Validation settings.@carlos-cell To get APs/APm/APl, run COCO-style evaluation with JSON saving and check the printed COCO summary:
yolo detect val model=yolo11n.pt data=coco.yaml save_json=TrueThis triggers COCO eval inside validation; see COCO evaluation in val and the size-specific metrics overview in the Performance metrics deep dive.
@AA278-HUB For “any vehicle” validation, use single-class evaluation so all types collapse to one:
metrics = model.val(data='vehicle.yaml', single_cls=True, agnostic_nms=True)Argument behavior is documented in the Val mode arguments.
@AA278-HUB You don’t need code changes for the above, but if you must customize matching/metrics, start from
DetectionValidatorand theval()entry point: see the DetectionValidator reference and theval()method in engine/model.py; if proposing a PR, please keep scope minimal and include tests.AA278-HUB
thank you,bro
carlos-cell
请问,如何输出不同尺度的mAP值呢,即APs、APm、APl
liujixingit
YOLOv8 调用验证功能开启save_txt后保存的坐标如何还原到原图,我尝试了直接×原图宽高,还原的坐标是错误的。save_txt保存的结果是相对什么计算得出的归一化坐标?
Cherishzyh
hello, I read some dialog about the IOU threshold and confidence threshold and have some questions.
Cherishzyh
- the document shows that 'iou' is the threshold for NMS.Is it also a threshold for calculate the confusion matrix? eg. I hope that if the IoU between the prediction and the ground truth is greater than 0.2, it will be considered a true positive (TP). At the same time, does the NMS threshold also have to be 0.2?
Cherishzyh
- For confidence threshold, if I set it to 0.1, that mean all bboxes with a score lower than 0.1 will be removed when calculate the PR-curve?. If so, does it will also be remove in result json or txt ?
Glenn JocherUltralytics@Cherishzyh great questions:
-
The
iouargument inval()controls NMS overlap removal only; it does not change the IoU used to determine TP/FP or mAP. Metrics are computed over fixed IoU thresholds 0.50–0.95. If you need evaluation at IoU=0.2, export predictions and compute custom metrics offline. See the Performance Metrics deep dive. -
The
confargument is a minimum score filter. Settingconf=0.1removes all predictions with score < 0.1 prior to evaluation and from saved outputs (save_json/save_txt). You can still access PR data from the results object:
from ultralytics import YOLO model = YOLO("yolo11n.pt") res = model.val(conf=0.1, iou=0.7, save_json=True, save_txt=True, plots=True) print(res.box.p_curve) # precision curve vs score thresholds print(res.box.r_curve) # recall curve vs score thresholdsArgument details are in the Val mode arguments.
-
lauravchrobak
When I run validate without setting plots=True I still get the f1, PR curve plots in the val folder. Potentially the default for this flag is actually true despite it being false in the table above?
sea190
The question about val of yoloworld, and I used my custom dataset, and I make sure the format of ma dataset is corret. While when I run the val.py the code still validate the categories of COCO Dataset instead of my dataset? How can I solve this problem?
ihciab
You can try specifying the path of the validation set. When calling the val function, specify model.val(data=‘your_data’)
Glenn JocherUltralytics@sea190 for YOLO-World validation with custom datasets, ensure your dataset YAML file correctly defines the class names and paths. YOLO-World may default to COCO categories if the dataset configuration isn't properly specified. Try:
model.val(data='path/to/your/custom_dataset.yaml')Make sure your YAML file includes the correct
namesfield with your custom class names and verify thevalpath points to your validation images and labels. If issues persist, check that your dataset follows the expected format for YOLO-World validation.