
    .hT                        d Z ddlmZ ddlZddlZddlZddlZddlZddlmZ ddl	Z
ddlZddlmZmZ ddlmZmZmZmZmZmZ ddlmZ ddlmZ dd	lmZ  G d
 d      Zy)a5  
Module provides functionalities for hyperparameter tuning of the Ultralytics YOLO models for object detection, instance
segmentation, image classification, pose estimation, and multi-object tracking.

Hyperparameter tuning is the process of systematically searching for the optimal set of hyperparameters
that yield the best model performance. This is particularly crucial in deep learning models like YOLO,
where small changes in hyperparameters can lead to significant differences in model accuracy and efficiency.

Examples:
    Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=30 for 300 tuning iterations.
    >>> from ultralytics import YOLO
    >>> model = YOLO("yolo11n.pt")
    >>> model.tune(data="coco8.yaml", epochs=10, iterations=300, optimizer="AdamW", plots=False, save=False, val=False)
    )annotationsN)datetime)get_cfgget_save_dir)DEFAULT_CFGLOGGERYAML	callbackscolorstrremove_colorstr)check_requirements)
torch_load)plot_tune_resultsc                  z    e Zd ZdZedfddZdddZddZdddZddZ	d Z
ddd	Z	 	 	 d	 	 	 	 	 	 	 dd
ZdddZy)TuneraF  
    A class for hyperparameter tuning of YOLO models.

    The class evolves YOLO model hyperparameters over a given number of iterations by mutating them according to the
    search space and retraining the model to evaluate their performance. Supports both local CSV storage and
    distributed MongoDB Atlas coordination for multi-machine hyperparameter optimization.

    Attributes:
        space (dict[str, tuple]): Hyperparameter search space containing bounds and scaling factors for mutation.
        tune_dir (Path): Directory where evolution logs and results will be saved.
        tune_csv (Path): Path to the CSV file where evolution logs are saved.
        args (dict): Configuration arguments for the tuning process.
        callbacks (list): Callback functions to be executed during tuning.
        prefix (str): Prefix string for logging messages.
        mongodb (MongoClient): Optional MongoDB client for distributed tuning.
        collection (Collection): MongoDB collection for storing tuning results.

    Methods:
        _mutate: Mutate hyperparameters based on bounds and scaling factors.
        __call__: Execute the hyperparameter evolution across multiple iterations.

    Examples:
        Tune hyperparameters for YOLO11n on COCO8 at imgsz=640 and epochs=30 for 300 tuning iterations.
        >>> from ultralytics import YOLO
        >>> model = YOLO("yolo11n.pt")
        >>> model.tune(
        >>>     data="coco8.yaml",
        >>>     epochs=10,
        >>>     iterations=300,
        >>>     plots=False,
        >>>     save=False,
        >>>     val=False
        >>> )

        Tune with distributed MongoDB Atlas coordination across multiple machines:
        >>> model.tune(
        >>>     data="coco8.yaml",
        >>>     epochs=10,
        >>>     iterations=300,
        >>>     mongodb_uri="mongodb+srv://user:pass@cluster.mongodb.net/",
        >>>     mongodb_db="ultralytics",
        >>>     mongodb_collection="tune_results"
        >>> )

        Tune with custom search space:
        >>> model.tune(space={"lr0": (1e-5, 1e-1), "momentum": (0.6, 0.98)})
    Nc           
        |j                  dd      xs@ i ddddddd	d
ddddddddddddddddddddddddd d
d!d!d!d!d!d!d!dd"| _        |j                  d#d      }|j                  d$d%      }|j                  d&d'      }t        |(      | _        | j                  j                  | j                  _        t        | j                  | j                  j                  xs d)*      | _        d+\  | j                  _        | j                  _        | j                  _        | j                  d,z  | _	        |xs t        j                         | _
        t        d-      | _        t        j                  |        d| _        |r| j!                  |||       t#        j$                  | j                   d.| j                   d/| j                   d0       y)1z
        Initialize the Tuner with configurations.

        Args:
            args (dict): Configuration for hyperparameter evolution.
            _callbacks (list | None, optional): Callback functions to be executed during tuning.
        spaceNlr0)gh㈵>皙?lrf)g-C6?r   momentum)gffffff?g\(\?g333333?weight_decay)        gMbP?warmup_epochs)r   g      @warmup_momentum)r   gffffff?box)      ?g      4@cls)r         @dfl)g?g      @hsv_h)r   r   hsv_s)r   g?hsv_vdegrees)r   g     F@	translatescaleshear)r   g      $@perspective)r   r   )flipudfliplrbgrmosaicmixupcutmix
copy_pasteclose_mosaicmongodb_uri
mongodb_dbultralyticsmongodb_collectiontuner_results)	overridestune)name)NFFztune_results.csvzTuner: z*Initialized Tuner instance with 'tune_dir=z'
uT   💡 Learn about tuning at https://docs.ultralytics.com/guides/hyperparameter-tuning)popr   r   argsresumeexist_okr   r8   tune_dirtune_csvr
   get_default_callbacksr   prefixadd_integration_callbacksmongodb_init_mongodbr   info)selfr:   
_callbacksr1   r2   r4   s         V/var/www/html/ai-service/venv/lib/python3.12/site-packages/ultralytics/engine/tuner.py__init__zTuner.__init__U   s3    XXgt, 
 1
<1
 =1
 (	1

 L1
 Z1
 {1
 ;1
 :1
 :1
 Z1
 Z1
 Z1
 {1
 1
  [!1
" [#1
$ <%1
& !   $'51

8 hh}d3XXlM:
!XX&:OLd+	!YY--		$TYYTYY^^5MvN?S<				*DII,<(::#Hy'F'F'Hy)++D1 {J8JK{{mEdmm_TW{{moq	
    c                   t        d       ddlm} ddlm}m} t        |      D ]Z  }	  ||dddddd	d
d	      }|j                  j                  d       t        j                  | j                   d|dz    d       |c S  y# ||f$ rQ ||dz
  k(  r d|z  }t        j                  | j                   d|dz    d| d       t        j                  |       Y w xY w)ao  
        Create MongoDB client with exponential backoff retry on connection failures.

        Args:
            uri (str): MongoDB connection string with credentials and cluster information.
            max_retries (int): Maximum number of connection attempts before giving up.

        Returns:
            (MongoClient): Connected MongoDB client instance.
        pymongor   )MongoClient)ConnectionFailureServerSelectionTimeoutErrori0u  i N  i@  T      i`  )serverSelectionTimeoutMSconnectTimeoutMSsocketTimeoutMSretryWrites
retryReadsmaxPoolSizeminPoolSizemaxIdleTimeMSpingz$Connected to MongoDB Atlas (attempt    )   z#MongoDB connection failed (attempt z), retrying in zs...N)r   rK   rL   pymongo.errorsrM   rN   rangeadmincommandr   rD   r@   warningtimesleep)	rE   urimax_retriesrL   rM   rN   attemptclient	wait_times	            rG   _connectzTuner._connect   s     	9%'Q[) 	&G&$-2%*$) $# " !"'
 $$V,t{{m+OPWZ[P[}\]^_	&  &'BC &kAo-wJ	{{m#FwQR{mSbclbmmqr 

9%&s   ABACCc                    | j                  |      | _        | j                  |   |   | _        | j                  j                  dgd       t	        j
                  | j                   d       y)a  
        Initialize MongoDB connection for distributed tuning.

        Connects to MongoDB Atlas for distributed hyperparameter optimization across multiple machines.
        Each worker saves results to a shared collection and reads the latest best hyperparameters
        from all workers for evolution.

        Args:
            mongodb_uri (str): MongoDB connection string, e.g. 'mongodb+srv://username:password@cluster.mongodb.net/'.
            mongodb_db (str, optional): Database name.
            mongodb_collection (str, optional): Collection name.

        Notes:
            - Creates a fitness index for fast queries of top results
            - Falls back to CSV-only mode if connection fails
            - Uses connection pooling and retry logic for production reliability
        )fitnessT)
backgroundz*Using MongoDB Atlas for distributed tuningN)ri   rB   
collectioncreate_indexr   rD   r@   )rE   r1   r2   r4   s       rG   rC   zTuner._init_mongodb   s\    $ }}[1,,z23EF$$o%64$Ht{{m#MNOrI   c                    	 t        | j                  j                         j                  dd      j	                  |            S # t
        $ r g cY S w xY w)z
        Get top N results from MongoDB sorted by fitness.

        Args:
            n (int): Number of top results to retrieve.

        Returns:
            (list[dict]): List of result documents with fitness scores and hyperparameters.
        rk   rl   )listrn   findsortlimit	Exception)rE   ns     rG   _get_mongodb_resultszTuner._get_mongodb_results   sK    	,,.33IrBHHKLL 	I	s   AA AAc                z   	 | j                   j                  t        |      |j                         D ci c]$  \  }}|t	        |d      r|j                         n|& c}}|t        j                         |d       yc c}}w # t        $ r.}t        j                  | j                   d|        Y d}~yd}~ww xY w)a  
        Save results to MongoDB with proper type conversion.

        Args:
            fitness (float): Fitness score achieved with these hyperparameters.
            hyperparameters (dict[str, float]): Dictionary of hyperparameter values.
            metrics (dict): Complete training metrics dictionary (mAP, precision, recall, losses, etc.).
            iteration (int): Current iteration number.
        item)rk   hyperparametersmetrics	timestamp	iterationzMongoDB save failed: N)rn   
insert_onefloatitemshasattrry   r   nowru   r   ra   r@   )rE   rk   rz   r{   r}   kves           rG   _save_to_mongodbzTuner._save_to_mongodb   s    	EOO&&$W~_n_t_t_v'wW[WXZ[68JAFFHPQ(Q'w&!)!* (x  	ENNdkk]*?sCDD	Es(   2B )A=B =B 	B:$B55B:c           
        	 t        | j                  j                         j                  dd            }|sydj	                  dgt        | j
                  j                               z         dz   }t        | j                  dd	      5 }|j                  |       |D ]u  }|d   }| j
                  j                         D cg c]
  }|d
   |    }}t        |d      g|z   }|j                  dj	                  t        t        |            dz          w 	 ddd       yc c}w # 1 sw Y   yxY w# t        $ r.}	t        j                  | j                    d|	        Y d}	~	yd}	~	ww xY w)a  
        Sync MongoDB results to CSV for plotting compatibility.

        Downloads all results from MongoDB and writes them to the local CSV file in chronological order. This enables
        the existing plotting functions to work seamlessly with distributed MongoDB data.
        r}   rZ   N,rk   
wutf-8encodingrz      zMongoDB to CSV sync failed: )rq   rn   rr   rs   joinr   keysopenr>   writeroundmapstrru   r   ra   r@   )
rE   all_resultsheadersfresultrk   r   
hyp_valueslog_rowr   s
             rG   _sync_mongodb_to_csvzTuner._sync_mongodb_to_csv   sL   	Lt335::;JKK hh	{T$**//2C-DDELGdmmS7; @q ) @F$Y/GHL

HY!Z1&):";A">!ZJ!Z$Wa01J>GGGCHHSg%67$>?	@@ @ "[	@ @  	LNNdkk]*FqcJKK	LsN   5D0 AD0 	8D$DAD$D0 D$$D-)D0 -D0 0	E'9$E""E'c                b   t        |t        |            }|dddf   |dddf   j                         z
  dz   }t        j                  |      j	                         r|j                         dk(  rt        j                  |      }t        j                  t        t        |            ||      }t        j                  |D cg c]
  }||   dd  c}d      }|j                  d      |j                  d      }	}|	|z
  }
t        j                  j                  |||
z  z
  |	||
z  z         S c c}w )uG   BLX-α crossover from up to top-k parents (x[:,0]=fitness, rest=genes).Nr   gư>)weightsr   rZ   )minlennpisfiniteallsum	ones_likerandomchoicesr^   stackmaxuniform)rE   xalphar   r   idxsiparents_matlohispans              rG   
_crossoverzTuner._crossover  s    3q6NAqD'AadGKKM)D0{{7#'')W[[]a-?ll7+G~~eCFmWBhh$7Q!QR7;#[__Q%7BBwyy  edl!2B4EFF  8s   D,c                   d}| j                   r| j                  |      }|rYt        j                  |D cg c]7  }|d   g| j                  j                         D cg c]
  }|d   |    c}z   9 c}}      }n| j                  j                  | j                  j                  j                         v rTt        j                  dg| j                  j                         D cg c]  }t        | j                  |       c}z   g      }|r| j                  j                         rXt        j                  | j                  ddd      }t        |      d	kD  r'|ddd	f   }	t        j                   |	       }
||
   d| }|t        j"                  j%                  t'        t)        j(                                      t        | j                        }| j+                  |      }t        j                  | j                  j-                         D cg c]  }t        |      d
k(  r|d   nd c}      }t        j.                  |      }t        j0                  |dk(        rt        j"                  j#                  |      |k  }t        j"                  j3                  |      ||z  z  }t        j4                  |t        j6                  |      d      j9                  dd      }t        j0                  |dk(        rt;        | j                  j                               D ci c]  \  }}|t=        ||   ||   z         }}}n<| j                  j                         D ci c]  }|t        | j                  |       }}| j                  j?                         D ]1  \  }}tA        tC        tE        ||   |d	         |d         d      ||<   3 d|v rt'        tA        |d               |d<   |S c c}w c c}}w c c}w c c}w c c}}w c c}w )a#  
        Mutate hyperparameters based on bounds and scaling factors specified in `self.space`.

        Args:
            parent (str): Parent selection method (kept for API compatibility, unused in BLX mode).
            n (int): Number of top parents to consider.
            mutation (float): Probability of a parameter mutation in any given iteration.
            sigma (float): Standard deviation for Gaussian random number generator.

        Returns:
            (dict[str, float]): A dictionary containing mutated hyperparameters.
        Nrk   rz   r   r\   r   rZ   ndmin	delimiterskiprowsr   rP   r   g      ?r   r   r0   )#rB   rw   r   arrayr   r   rn   r8   databaselist_collection_namesgetattrr:   r>   existsloadtxtr   argsortr   seedintrb   r   valuesonesr   randnwhereexpclip	enumerater   r   r   r   r   )rE   rv   mutationsigmar   resultsrr   csv_datark   ordernggenesr   gainsfactorsmaskstepr   hypboundss                        rG   _mutatezTuner._mutate  s=   $  <<//2GHHmtuhiq|nQUQ[Q[Q`Q`Qb/cA2C0DQ0G/ccuv%%)A)A)W)W)YYHHsedjjooFW&Xwtyy!'<&XXYZ 9--/zz$--qCRSTH8}q "1a4.

G8,UOBQ' =IINN3tyy{+,TZZB OOA&E HHDJJDUDUDWXqc!fkads:XYEggbkG&&A&yy''+h6yyr*eem<((4s;@@sK &&A& @IIZ?[\tq!1eE!Hwqz122\C\59ZZ__5FG1gdii++GCG ))+ 	FIAv3s3q66!95vayA1ECF	F S "%eC,?&@"AC
O 0du&X& Y ]Gs/   &O-
O(+O-
"O3
O8O=P(O-
c                   t        j                          }d\  }}| j                  dz  j                  dd       | j                  r| j	                          d}| j
                  j                         rgt        j                  | j
                  ddd	      }|j                  d   }t        j                  | j                   d
| j                   d|dz    d       t        ||      D ]  }	t        |	dz  d      }
dd|
z  z
  }| j                  |      }t        j                  | j                   d|	dz    d| d|        i }i t!        | j"                        |}t%        t'        |            }|dz  }	 t)        d      j*                  ddg}g |dd |j-                         D        }t/        j0                  |d      j2                  }||dz  j                         rdndz  }t5        |      d   }|dk(  sJ d       t        j6                  d       t9        j:                          t<        j>                  jA                          |jG                  d"d#      }| j                  rr| jI                  ||||	dz          | j	                          | jJ                  jM                  i       }||k\  rt        j                  | j                   d$| d%| d&        y!tO        |d'      g| jP                  jS                         D cg c]  }||   	 c}z   }| j
                  j                         rd(n8djU                  d"gtW        | jP                  jS                               z         d z   }tY        | j
                  d)d*+      5 }|j[                  |djU                  t]        t^        |            z   d z          d!d!d!       t        j                  | j
                  ddd	      }|d!d!df   }|ja                         }||	k(  }|rrt_        |      }|j-                         D ci c]  \  }}|tO        |d'       }}}|jc                  d,      D ]%  }te        jf                  || j                  dz         ' n|r|rte        jh                  |d-       tk        t_        | j
                               | j                   |	dz    d| d.t        j                          |z
  d/d0| j                   d1tm        d2| j                         d | j                   d3||    d4|dz    d | j                   d5| d | j                   d6| } t        j                  d | z          to        | jP                  jS                               D 	ci c]  \  }	}|tq        |||	dz   f          }!}	}ts        jt                  | j                  d7z  |!tw        | jy                  | j                  d8            d z   9       ts        jz                  | j                  d7z          y!# tB        $ r)}t        jD                  d|	dz    d |        Y d!}~d!}~ww xY wc c}w # 1 sw Y   xY wc c}}w c c}}	w ):aV  
        Execute the hyperparameter evolution process when the Tuner instance is called.

        This method iterates through the specified number of iterations, performing the following steps:
        1. Sync MongoDB results to CSV (if using distributed mode)
        2. Mutate hyperparameters using the best previous results or defaults
        3. Train a YOLO model with the mutated hyperparameters
        4. Log fitness scores and hyperparameters to MongoDB and/or CSV
        5. Track the best performing configuration across all iterations

        Args:
            model (Model | None, optional): A pre-initialized YOLO model to be used for training.
            iterations (int): The number of generations to run the evolution for.
            cleanup (bool): Whether to delete iteration weights to reduce storage space during tuning.
        )NNr   T)parentsr<   r   r\   r   rZ   r   zResuming tuning run z from iteration z...g     r@r   皙?r   )r   zStarting iteration /z with hyperparameters: sysz-mzultralytics.cfg.__init__trainc              3  0   K   | ]  \  }}| d |   yw)=N ).0r   r   s      rG   	<genexpr>z!Tuner.__call__.<locals>.<genexpr>  s     *U$!QaS!:*Us   )checkzbest.ptzlast.pttrain_metricsztraining failedz5training failure for hyperparameter tuning iteration r   Nrk   r   zTarget iterations (z) reached in MongoDB (z). Stopping.r    ar   r   z*.pt)ignore_errorsu    iterations complete ✅ (z.2fzs)
zResults saved to boldzBest fitness=z observed at iteration zBest fitness metrics are zBest fitness model is zbest_hyperparameters.yamlz# )dataheader)>rb   r=   mkdirrB   r   r>   r   r   r   shaper   rD   r@   r^   r   r   varsr:   r   r   
__import__
executabler   
subprocessrun
returncoder   rc   gccollecttorchcudaempty_cacheru   errorgetr   rn   count_documentsr   r   r   r   rq   r   r   r   r   argmaxglobshutilcopy2rmtreer   r   r   r   r	   saver   replaceprint)"rE   model
iterationscleanupt0best_save_dirbest_metricsstartr   r   fracsigma_imutated_hypr{   
train_argssave_dirweights_dirlaunchcmdreturn_code	ckpt_filer   rk   total_mongo_iterationsr   r   r   r   best_idxbest_is_currentr   ckptr   r   s"                                     rG   __call__zTuner.__call___  s     YY[&0#|		"))$)F <<%%'==!

4==S1MAGGAJEKK4;;-';DMM?JZ[`cd[dZeehijuj) O	DAq5y#&DC$J&G ,,W,5KKK4;;-':1q5':,NefqerstG;DO;{;J#GJ$78H"Y.Kc$U+66>XYVVV*U*BRBRBT*UV(nnS=HH'y9P8X8X8Z9`ij	$Y/@"a':)::' 

1



&&( kk)S1G||%%g{GQUK))+)-)H)H)L&)Z7KK;;-'::,F\]s\t  uA  B  !!,-IZ0[AQ0[[ $ 4 4 6"SXXykTXY]YcYcYhYhYjTkFk=los=s$--w? J1GGGchhs3/@&AADHIJ 

4==S1MA1gG~~'H&!mO #H;B==?K41a5A;KK',,V4 BDLLt}}y'@AB]m4@ c$--01 ;;-Awa
|3Mdiik\^N^_bMccg;;-0&$--1P0QQS;;-}WX->,??VW_bcWcVddf;;-8b;;-5m_	F  KKv&=FtzzGX=YZTQAuQxQ/00ZDZII ;;&v~~dkk4'HIDP
 JJt}}'BBC_O	D6  cTUVYZUZT[[]^_]`abbc  1\J J  L$ [s7   4CX=X7;5X<Y	0Y	X4X//X4<Y	)rF   zlist | None)z4mongodb+srv://username:password@cluster.mongodb.net/rP   )rd   r   re   r   )r   r   r   )r   )rv   r   returnrq   )rk   r   rz   dict[str, float]r{   dictr}   r   )r   	   )r   
np.ndarrayr   r   r   r   r  r  )r  g      ?r   )rv   r   r   r   r   r   r  r  )N
   T)r  r   r  bool)__name__
__module____qualname____doc__r   rH   ri   rC   rw   r   r   r   r   r  r   rI   rG   r   r   $   s{    .` (4 9
v'&RP.E.L4G 	@@ @ 	@
 
@DlDrI   r   )r#  
__future__r   r   r   r   r   rb   r   numpyr   r   ultralytics.cfgr   r   ultralytics.utilsr   r   r	   r
   r   r   ultralytics.utils.checksr   ultralytics.utils.patchesr   ultralytics.utils.plottingr   r   r   rI   rG   <module>r+     sG    # 	        1 ] ] 7 0 8gD gDrI   