o
    WhB%                     @   s   d dl Z d dlZd dlmZ d dlZd dlmZ d dlmZm	Z	 d dl
mZ d dlmZ d dlmZ d dlmZmZ d dlmZmZmZ d d	lmZmZ G d
d deZdS )    N)copy)build_dataloaderbuild_yolo_dataset)BaseTrainer)yolo)DetectionModel)LOGGERRANK)plot_imagesplot_labelsplot_results)de_paralleltorch_distributed_zero_firstc                       s   e Zd ZdZdddZd dd	Zd
d Zdd Zd!ddZdd Z	d"ddZ
dd Zdd Zdd Zdd Z fddZ  ZS )#DetectionTrainera  
    A class extending the BaseTrainer class for training based on a detection model.

    This trainer specializes in object detection tasks, handling the specific requirements for training YOLO models
    for object detection.

    Attributes:
        model (DetectionModel): The YOLO detection model being trained.
        data (dict): Dictionary containing dataset information including class names and number of classes.
        loss_names (Tuple[str]): Names of the loss components used in training (box_loss, cls_loss, dfl_loss).

    Methods:
        build_dataset: Build YOLO dataset for training or validation.
        get_dataloader: Construct and return dataloader for the specified mode.
        preprocess_batch: Preprocess a batch of images by scaling and converting to float.
        set_model_attributes: Set model attributes based on dataset information.
        get_model: Return a YOLO detection model.
        get_validator: Return a validator for model evaluation.
        label_loss_items: Return a loss dictionary with labeled training loss items.
        progress_string: Return a formatted string of training progress.
        plot_training_samples: Plot training samples with their annotations.
        plot_metrics: Plot metrics from a CSV file.
        plot_training_labels: Create a labeled training plot of the YOLO model.
        auto_batch: Calculate optimal batch size based on model memory requirements.

    Examples:
        >>> from ultralytics.models.yolo.detect import DetectionTrainer
        >>> args = dict(model="yolo11n.pt", data="coco8.yaml", epochs=3)
        >>> trainer = DetectionTrainer(overrides=args)
        >>> trainer.train()
    trainNc              	   C   sB   t t| jrt| jj  ndd}t| j||| j||dk|dS )a  
        Build YOLO Dataset for training or validation.

        Args:
            img_path (str): Path to the folder containing images.
            mode (str): `train` mode or `val` mode, users are able to customize different augmentations for each mode.
            batch (int, optional): Size of batches, this is for `rect`.

        Returns:
            (Dataset): YOLO dataset object configured for the specified mode.
        r       val)moderectstride)maxintmodelr   r   r   argsdata)selfimg_pathr   batchgs r   X/var/www/vscode/kcb/lib/python3.10/site-packages/ultralytics/models/yolo/detect/train.pybuild_dataset4   s   $zDetectionTrainer.build_dataset   r   c                 C   s   |dv sJ d| dt | | |||}W d   n1 s"w   Y  |dk}t|ddr:|r:td d}|dkrB| jjn| jjd	 }t|||||S )
a  
        Construct and return dataloader for the specified mode.

        Args:
            dataset_path (str): Path to the dataset.
            batch_size (int): Number of images per batch.
            rank (int): Process rank for distributed training.
            mode (str): 'train' for training dataloader, 'val' for validation dataloader.

        Returns:
            (DataLoader): PyTorch dataloader object.
        >   r   r   z#Mode must be 'train' or 'val', not .Nr   r   FzJ'rect=True' is incompatible with DataLoader shuffle, setting shuffle=False   )r   r!   getattrr   warningr   workersr   )r   dataset_path
batch_sizerankr   datasetshuffler'   r   r   r    get_dataloaderC   s   

zDetectionTrainer.get_dataloaderc                    s   |d j  jdd d |d<  jjr_|d }tt jjd t jjd  j	  j	  j	 }|t
|jdd  d	kr[ fd
d|jdd D }tjj||ddd}||d< |S )a   
        Preprocess a batch of images by scaling and converting to float.

        Args:
            batch (dict): Dictionary containing batch data with 'img' tensor.

        Returns:
            (dict): Preprocessed batch with normalized images.
        imgT)non_blocking   g      ?g      ?r$   N   c                    s&   g | ]}t |  j  j qS r   )mathceilr   .0xr   sfr   r    
<listcomp>n   s    z5DetectionTrainer.preprocess_batch.<locals>.<listcomp>bilinearF)sizer   align_corners)todevicefloatr   multi_scalerandom	randranger   imgszr   r   shapenn
functionalinterpolate)r   r   imgssznsr   r7   r    preprocess_batchZ   s"    
(z!DetectionTrainer.preprocess_batchc                 C   s*   | j d | j_| j d | j_| j| j_dS )z2Set model attributes based on dataset information.ncnamesN)r   r   rL   rM   r   r   r   r   r    set_model_attributesu   s   z%DetectionTrainer.set_model_attributesTc                 C   s6   t || jd | jd |otdkd}|r|| |S )aF  
        Return a YOLO detection model.

        Args:
            cfg (str, optional): Path to model configuration file.
            weights (str, optional): Path to model weights.
            verbose (bool): Whether to display model information.

        Returns:
            (DetectionModel): YOLO detection model.
        rL   channels)rL   chverbose)r   r   r	   load)r   cfgweightsrS   r   r   r   r    	get_model   s   $
zDetectionTrainer.get_modelc                 C   s&   d| _ tjj| j| jt| j| jdS )z6Return a DetectionValidator for YOLO model validation.)box_losscls_lossdfl_loss)save_dirr   
_callbacks)	
loss_namesr   detectDetectionValidatortest_loaderr[   r   r   	callbacksrN   r   r   r    get_validator   s   zDetectionTrainer.get_validatorc                    s<    fdd| j D }|durdd |D }tt||S |S )ah  
        Return a loss dict with labeled training loss items tensor.

        Args:
            loss_items (List[float], optional): List of loss values.
            prefix (str): Prefix for keys in the returned dictionary.

        Returns:
            (Dict | List): Dictionary of labeled loss items if loss_items is provided, otherwise list of keys.
        c                    s   g | ]	}  d | qS )/r   r4   prefixr   r    r9          z5DetectionTrainer.label_loss_items.<locals>.<listcomp>Nc                 S   s   g | ]	}t t|d qS )   )roundr?   r4   r   r   r    r9      rf   )r]   dictzip)r   
loss_itemsre   keysr   rd   r    label_loss_items   s
   z!DetectionTrainer.label_loss_itemsc                 C   s.   dddt | j   ddg| jddR  S )z`Return a formatted string of training progress with epoch, GPU memory, loss, instances and size.
z%11s   EpochGPU_mem	InstancesSize)lenr]   rN   r   r   r    progress_string   s   z DetectionTrainer.progress_stringc              
   C   sD   t |d |d |d d|d |d | jd| d | jd	 d
S )z
        Plot training samples with their annotations.

        Args:
            batch (dict): Dictionary containing batch data.
            ni (int): Number of iterations.
        r.   	batch_idxclsrQ   bboxesim_filetrain_batchz.jpg)imagesrv   rw   rx   pathsfnameon_plotN)r
   squeezer[   r~   )r   r   nir   r   r    plot_training_samples   s   
z&DetectionTrainer.plot_training_samplesc                 C   s   t | j| jd dS )zPlot metrics from a CSV file.)filer~   N)r   csvr~   rN   r   r   r    plot_metrics   s   zDetectionTrainer.plot_metricsc                 C   s\   t dd | jjjD d}t dd | jjjD d}t|| | jd | j| j	d dS )z1Create a labeled training plot of the YOLO model.c                 S      g | ]}|d  qS )rx   r   r5   lbr   r   r    r9          z9DetectionTrainer.plot_training_labels.<locals>.<listcomp>r   c                 S   r   )rw   r   r   r   r   r    r9      r   rM   )rM   r[   r~   N)
npconcatenatetrain_loaderr+   labelsr   r   r   r[   r~   )r   boxesrw   r   r   r    plot_training_labels   s   $z%DetectionTrainer.plot_training_labelsc                    s6   | j | jddd}tdd |jD d }t |S )z
        Get optimal batch size by calculating memory occupation of model.

        Returns:
            (int): Optimal batch size.
        r   r"   )r   r   c                 s   s    | ]	}t |d  V  qdS )rw   N)rt   )r5   labelr   r   r    	<genexpr>   s    z.DetectionTrainer.auto_batch.<locals>.<genexpr>ro   )r!   trainsetr   r   super
auto_batch)r   train_datasetmax_num_obj	__class__r   r    r      s   zDetectionTrainer.auto_batch)r   N)r"   r   r   )NNT)Nr   )__name__
__module____qualname____doc__r!   r-   rK   rO   rW   rb   rm   ru   r   r   r   r   __classcell__r   r   r   r    r      s    
 



r   )r2   rA   r   numpyr   torch.nnrE   ultralytics.datar   r   ultralytics.engine.trainerr   ultralytics.modelsr   ultralytics.nn.tasksr   ultralytics.utilsr   r	   ultralytics.utils.plottingr
   r   r   ultralytics.utils.torch_utilsr   r   r   r   r   r   r    <module>   s   