"""Progress abstraction holding stopping criteria and progress information."""importloggingimporttimefromevalml.utils.loggerimportget_logger
[docs]classProgress:"""Progress object holding stopping criteria and progress information. Args: max_time (int): Maximum time to search for pipelines. max_iterations (int): Maximum number of iterations to search. max_batches (int): The maximum number of batches of pipelines to search. Parameters max_time, and max_iterations have precedence over stopping the search. patience (int): Number of iterations without improvement to stop search early. tolerance (float): Minimum percentage difference to qualify as score improvement for early stopping. automl_algorithm (str): The automl algorithm to use. Used to calculate iterations if max_batches is selected as stopping criteria. objective (str, ObjectiveBase): The objective used in search. verbose (boolean): Whether or not to log out stopping information. """def__init__(self,max_time=None,max_batches=None,max_iterations=None,patience=None,tolerance=None,automl_algorithm=None,objective=None,verbose=False,):self.max_time=max_timeself.current_time=Noneself.start_time=Noneself.max_batches=max_batchesself.current_batch=0self.max_iterations=max_iterationsself.current_iterations=0self.patience=patienceself.tolerance=toleranceself.automl_algorithm=automl_algorithmself.objective=objectiveself._best_score=Noneself._without_improvement=0self._last_id=0ifverbose:self.logger=get_logger(f"{__name__}.verbose")else:self.logger=logging.getLogger(__name__)
[docs]defstart_timing(self):"""Sets start time to current time."""self.start_time=time.time()
[docs]defelapsed(self):"""Return time elapsed using the start time and current time."""returnself.current_time-self.start_time
[docs]defshould_continue(self,results,interrupted=False,mid_batch=False):"""Given AutoML Results, return whether or not the search should continue. Args: results (dict): AutoMLSearch results. interrupted (bool): whether AutoMLSearch was given an keyboard interrupt. Defaults to False. mid_batch (bool): whether this method was called while in the middle of a batch or not. Defaults to False. Returns: bool: True if search should continue, False otherwise. """ifinterrupted:returnFalse# update and check max_time, max_iterations, and max_batchesself.current_time=time.time()self.current_iterations=len(results["pipeline_results"])self.current_batch=self.automl_algorithm.batch_numberifself.max_timeandself.elapsed()>=self.max_time:returnFalseelifself.max_iterationsandself.current_iterations>=self.max_iterations:returnFalseelif(self.max_batchesandself.current_batch>=self.max_batchesandnotmid_batch):returnFalse# check for early stoppingifself.patienceisnotNoneandself.toleranceisnotNone:last_id=results["search_order"][-1]curr_score=results["pipeline_results"][last_id]["mean_cv_score"]ifself._best_scoreisNone:self._best_score=curr_scorereturnTrueeliflast_id>self._last_id:self._last_id=last_idscore_improved=(curr_score>self._best_scoreifself.objective.greater_is_betterelsecurr_score<self._best_score)significant_change=(abs((curr_score-self._best_score)/self._best_score)>self.tolerance)ifscore_improvedandsignificant_change:self._best_score=curr_scoreself._without_improvement=0else:self._without_improvement+=1ifself._without_improvement>=self.patience:self.logger.info("\n\n{} iterations without improvement. Stopping search early...".format(self.patience,),)returnFalsereturnTrue
[docs]defreturn_progress(self):"""Return information about current and end state of each stopping criteria in order of priority. Returns: List[Dict[str, unit]]: list of dictionaries containing information of each stopping criteria. """progress=[]ifself.max_time:progress.append({"stopping_criteria":"max_time","current_state":self.elapsed(),"end_state":self.max_time,"unit":"seconds",},)ifself.max_iterationsorself.max_batches:max_iterations=(self.max_iterationsifself.max_iterationselsesum([self.automl_algorithm.num_pipelines_per_batch(n)forninrange(self.max_batches)],))progress.append({"stopping_criteria":"max_iterations","current_state":self.current_iterations,"end_state":max_iterations,"unit":"iterations",},)ifself.max_batches:progress.append({"stopping_criteria":"max_batches","current_state":self.current_batch,"end_state":self.max_batches,"unit":"batches",},)returnprogress