
    hL*                        S SK Jr  S SKJr  S SKJr  S SKrS SKJr	  S SK
JrJr  S SKJr  S SKJrJr  S SKJrJr  S S	KJr   " S
 S\5      rg)    )annotations)Path)AnyN)ClassificationDatasetbuild_dataloader)BaseValidator)LOGGERRANK)ClassifyMetricsConfusionMatrix)plot_imagesc                     ^  \ rS rSrSrSSU 4S jjjrSS jrSS jrSS jrSS jr	SS jr
SS	 jrSS
 jrSS jrSS jrSS jrSS jrSS jrSS jrSrU =r$ )ClassificationValidator   au  
A class extending the BaseValidator class for validation based on a classification model.

This validator handles the validation process for classification models, including metrics calculation,
confusion matrix generation, and visualization of results.

Attributes:
    targets (list[torch.Tensor]): Ground truth class labels.
    pred (list[torch.Tensor]): Model predictions.
    metrics (ClassifyMetrics): Object to calculate and store classification metrics.
    names (dict): Mapping of class indices to class names.
    nc (int): Number of classes.
    confusion_matrix (ConfusionMatrix): Matrix to evaluate model performance across classes.

Methods:
    get_desc: Return a formatted string summarizing classification metrics.
    init_metrics: Initialize confusion matrix, class names, and tracking containers.
    preprocess: Preprocess input batch by moving data to device.
    update_metrics: Update running metrics with model predictions and batch targets.
    finalize_metrics: Finalize metrics including confusion matrix and processing speed.
    postprocess: Extract the primary prediction from model output.
    get_stats: Calculate and return a dictionary of metrics.
    build_dataset: Create a ClassificationDataset instance for validation.
    get_dataloader: Build and return a data loader for classification validation.
    print_results: Print evaluation metrics for the classification model.
    plot_val_samples: Plot validation image samples with their ground truth labels.
    plot_predictions: Plot images with their predicted class labels.

Examples:
    >>> from ultralytics.models.yolo.classify import ClassificationValidator
    >>> args = dict(model="yolo11n-cls.pt", data="imagenet10")
    >>> validator = ClassificationValidator(args=args)
    >>> validator()

Notes:
    Torchvision classification models can also be passed to the 'model' argument, i.e. model='resnet18'.
c                   > [         TU ]  XX45        SU l        SU l        SU R                  l        [        5       U l        g)a  
Initialize ClassificationValidator with dataloader, save directory, and other parameters.

Args:
    dataloader (torch.utils.data.DataLoader, optional): Dataloader to use for validation.
    save_dir (str | Path, optional): Directory to save results.
    args (dict, optional): Arguments containing model and validation configuration.
    _callbacks (list, optional): List of callback functions to be called during validation.

Examples:
    >>> from ultralytics.models.yolo.classify import ClassificationValidator
    >>> args = dict(model="yolo11n-cls.pt", data="imagenet10")
    >>> validator = ClassificationValidator(args=args)
    >>> validator()
Nclassify)super__init__targetspredargstaskr   metrics)self
dataloadersave_dirr   
_callbacks	__class__s        ^/home/james-whalen/.local/lib/python3.13/site-packages/ultralytics/models/yolo/classify/val.pyr    ClassificationValidator.__init__9   s7      	t@	#		&(    c                    SS-  $ )z=Return a formatted string summarizing classification metrics.z%22s%11s%11s)classestop1_acctop5_acc r   s    r   get_desc ClassificationValidator.get_descO   s    #'JJJr!   c                    UR                   U l         [        UR                   5      U l        / U l        / U l        [        UR                   S9U l        g)z^Initialize confusion matrix, class names, and tracking containers for predictions and targets.)namesN)r+   lenncr   r   r   confusion_matrix)r   models     r   init_metrics$ClassificationValidator.init_metricsS   s<    [[
ekk"	 /ekk Br!   c                j   US   R                  U R                  U R                  R                  S:H  S9US'   U R                  R                  (       a  US   R	                  5       OUS   R                  5       US'   US   R                  U R                  U R                  R                  S:H  S9US'   U$ )zTPreprocess input batch by moving data to device and converting to appropriate dtype.imgcuda)non_blockingcls)todevicetyper   halffloat)r   batchs     r   
preprocess"ClassificationValidator.preprocess[   s    U|t{{AQAQU[A[\e.2iinnuU|((*%,BTBTBVeU|t{{AQAQU[A[\er!   c                   [        [        U R                  5      S5      nU R                  R	                  UR                  SSS9SS2SU24   R                  [        R                  5      R                  5       5        U R                  R	                  US   R                  [        R                  5      R                  5       5        g)a  
Update running metrics with model predictions and batch targets.

Args:
    preds (torch.Tensor): Model predictions, typically logits or probabilities for each class.
    batch (dict): Batch data containing images and class labels.

Notes:
    This method appends the top-N predictions (sorted by confidence in descending order) to the
    prediction list for later evaluation. N is limited to the minimum of 5 and the number of classes.
      T)
descendingNr6   )minr,   r+   r   appendargsortr9   torchint32cpur   )r   predsr<   n5s       r   update_metrics&ClassificationValidator.update_metricsb   s     TZZ!$		qT:1crc6BGGTXXZ[E%L--ekk:>>@Ar!   c                   U R                   R                  U R                  U R                  5        U R                  R
                  (       a7  S H1  nU R                   R                  U R                  XR                  S9  M3     U R                  U R                  l	        U R                  U R                  l        U R                   U R                  l         g)aM  
Finalize metrics including confusion matrix and processing speed.

Notes:
    This method processes the accumulated predictions and targets to generate the confusion matrix,
    optionally plots it, and updates the metrics object with speed information.

Examples:
    >>> validator = ClassificationValidator()
    >>> validator.pred = [torch.tensor([[0, 1, 2]])]  # Top-3 predictions for one sample
    >>> validator.targets = [torch.tensor([0])]  # Ground truth class
    >>> validator.finalize_metrics()
    >>> print(validator.metrics.confusion_matrix)  # Access the confusion matrix
)TF)r   	normalizeon_plotN)r.   process_cls_predsr   r   r   plotsplotr   rO   speedr   )r   rN   s     r   finalize_metrics(ClassificationValidator.finalize_metricsr   s     	//		4<<H99??(	%%**DMMY`l`l*m )!ZZ $(,(=(=%r!   c                F    [        U[        [        45      (       a  US   $ U$ )zSExtract the primary prediction from model output if it's in a list or tuple format.r   )
isinstancelisttuple)r   rI   s     r   postprocess#ClassificationValidator.postprocess   s!    %edE];;uQxFFr!   c                    U R                   R                  U R                  U R                  5        U R                   R                  $ )zSCalculate and return a dictionary of metrics by processing targets and predictions.)r   processr   r   results_dictr'   s    r   	get_stats!ClassificationValidator.get_stats   s.    T\\4995||(((r!   c                4   [         S:X  a  S/[        R                  " 5       -  nS/[        R                  " 5       -  n[        R                  " U R                  USS9  [        R                  " U R
                  USS9  U VVs/ s H  o3  H  oDPM     M     snnU l        U VVs/ s H  o3  H  oUPM     M     snnU l        g[         S:  aA  [        R                  " U R                  SSS9  [        R                  " U R
                  SSS9  ggs  snnf s  snnf )zGather stats from all GPUs.r   N)dst)r
   distget_world_sizegather_objectr   r   )r   gathered_predsgathered_targetsrankr   r   s         r   gather_stats$ClassificationValidator.gather_stats   s    19"Vd&9&9&;;N $v(;(;(==tyy.a@t||-=1E*8J.$TTT.JDI0@U0@PTWGPTG0@UDLAXtyy$A6t||Tq9  KUs   D$Dc                T    [        XR                  SU R                  R                  S9$ )z7Create a ClassificationDataset instance for validation.F)rootr   augmentprefix)r   r   split)r   img_paths     r   build_dataset%ClassificationValidator.build_dataset   s"    $(EZ^ZcZcZiZijjr!   c                b    U R                  U5      n[        X2U R                  R                  SS9$ )a!  
Build and return a data loader for classification validation.

Args:
    dataset_path (str | Path): Path to the dataset directory.
    batch_size (int): Number of samples per batch.

Returns:
    (torch.utils.data.DataLoader): DataLoader object for the classification validation dataset.
)rh   )rq   r   r   workers)r   dataset_path
batch_sizedatasets       r   get_dataloader&ClassificationValidator.get_dataloader   s-     $$\2TYY5F5FRPPr!   c                    SS[        U R                  R                  5      -  -   n[        R                  " USU R                  R
                  U R                  R                  4-  5        g)z6Print evaluation metrics for the classification model.z%22sz%11.3gallN)r,   r   keysr	   infotop1top5)r   pfs     r   print_results%ClassificationValidator.print_results   sL    hT\\%6%6!777B%!2!2DLL4E4EFFGr!   c                    [         R                  " US   R                  S   5      US'   [        UU R                  SU S3-  U R
                  U R                  S9  g)a  
Plot validation image samples with their ground truth labels.

Args:
    batch (dict[str, Any]): Dictionary containing batch data with 'img' (images) and 'cls' (class labels).
    ni (int): Batch index used for naming the output file.

Examples:
    >>> validator = ClassificationValidator()
    >>> batch = {"img": torch.rand(16, 3, 224, 224), "cls": torch.randint(0, 10, (16,))}
    >>> validator.plot_val_samples(batch, 0)
r3   r   	batch_idx	val_batchz_labels.jpg)labelsfnamer+   rO   N)rF   arangeshaper   r   r+   rO   )r   r<   nis      r   plot_val_samples(ClassificationValidator.plot_val_samples   sT     #\\%,*<*<Q*?@k--IbT"==**LL		
r!   c           
        [        US   [        R                  " US   R                  S   5      [        R                  " USS9[        R
                  " USS9S9n[        UU R                  SU S3-  U R                  U R                  S9  g	)
a  
Plot images with their predicted class labels and save the visualization.

Args:
    batch (dict[str, Any]): Batch data containing images and other information.
    preds (torch.Tensor): Model predictions with shape (batch_size, num_classes).
    ni (int): Batch index used for naming the output file.

Examples:
    >>> validator = ClassificationValidator()
    >>> batch = {"img": torch.rand(16, 3, 224, 224)}
    >>> preds = torch.rand(16, 10)  # 16 images, 10 classes
    >>> validator.plot_predictions(batch, preds, 0)
r3   r   rA   )dim)r3   r   r6   confr   z	_pred.jpg)r   r+   rO   N)
dictrF   r   r   argmaxamaxr   r   r+   rO   )r   r<   rI   r   batched_predss        r   plot_predictions(ClassificationValidator.plot_predictions   s|     ell5<#5#5a#89U*Eq)	
 	--IbT";;**LL		
r!   )r.   r   r+   r-   r   r   )NNNN)returnNone)r   str)r/   ztorch.nn.Moduler   r   )r<   dict[str, Any]r   r   )rI   torch.Tensorr<   r   r   r   )rI   z7torch.Tensor | list[torch.Tensor] | tuple[torch.Tensor]r   r   )r   zdict[str, float])rp   r   r   r   )rv   z
Path | strrw   intr   ztorch.utils.data.DataLoader)r<   r   r   r   r   r   )r<   r   rI   r   r   r   r   r   )__name__
__module____qualname____firstlineno____doc__r   r(   r0   r=   rK   rT   rZ   r_   ri   rq   ry   r   r   r   __static_attributes____classcell__)r   s   @r   r   r      s`    $L) ),KCB >.G)
:kQH

*
 
r!   r   )
__future__r   pathlibr   typingr   rF   torch.distributeddistributedrc   ultralytics.datar   r   ultralytics.engine.validatorr   ultralytics.utilsr	   r
   ultralytics.utils.metricsr   r   ultralytics.utils.plottingr   r   r&   r!   r   <module>r      s3    #      D 6 * F 2S
m S
r!   