From b6957cb5bdae0f3d1eb6d9af1b974749127b9bfb Mon Sep 17 00:00:00 2001 From: Yizhou Cai <yizhou.cai@cern.ch> Date: Thu, 17 Apr 2025 21:44:14 +0800 Subject: [PATCH 1/5] optimize retry --- quickstats/components/extended_minimizer.py | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index 357ed050..237cfd61 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -681,12 +681,15 @@ class ExtendedMinimizer(AbstractObject): self.status = status return status - def robust_minimize(self, cascade:bool=True): + def robust_minimize(self, cascade:bool=True, fit_from_initial:bool=True): self.stdout.debug('Begin robust minimization.') strategy = self.config['strategy'] retry = self.config['retry'] minimizer_type = self.config['minimizer_type'] minimizer_algo = self.config['minimizer_algo'] + if fit_from_initial: + variables = self.pdf.getVariables() + snapshot = variables.snapshot() status = self.single_minimize(minimizer_type, minimizer_algo) # repeat if fit failed or poi(s) at boundary @@ -700,6 +703,8 @@ class ExtendedMinimizer(AbstractObject): self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' f'Retrying with strategy {strategy}') self.minimizer.setStrategy(strategy) + if fit_from_initial: + variables.__assign__(snapshot) status = self.single_minimize(minimizer_type, minimizer_algo) expanded_pois = self.expand_poi_bounds() -- GitLab From 67b0fe8cfb0b1b1c276b5b9a5c16a72238a455e1 Mon Sep 17 00:00:00 2001 From: Yizhou Cai <yizhou.cai@cern.ch> Date: Thu, 17 Apr 2025 21:51:33 +0800 Subject: [PATCH 2/5] robust the prefit --- quickstats/components/extended_minimizer.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index 237cfd61..3d0dc836 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -625,7 +625,7 @@ class ExtendedMinimizer(AbstractObject): # prefit minimization self.minimizer.setStrategy(0) self.minimizer.setEps(self.config['eps']*10) - status = self.single_minimize(self.config['minimizer_type'], self.config['minimizer_algo']) + self.robust_minimize(cascade=cascade) self.minimizer.setStrategy(self.config['strategy']) self.minimizer.setEps(self.config['eps']) -- GitLab From 9fce1d4fe918ed9377b99b0be0e98df93e51c268 Mon Sep 17 00:00:00 2001 From: Yizhou Cai <yizhou.cai@cern.ch> Date: Thu, 24 Apr 2025 22:07:16 +0800 Subject: [PATCH 3/5] new retry --- quickstats/components/extended_minimizer.py | 70 +++++++++++++-------- 1 file changed, 44 insertions(+), 26 deletions(-) diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index 3d0dc836..fabbc364 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -55,6 +55,7 @@ class ExtendedMinimizer(AbstractObject): 'postfit_hesse': 0, 'minuit2_storage_level': 0, 'do_prefit': 0, + 'retry_diff_eps': 0, # cms dedicated configs 'set_zero_point': 1, # change the reference point of the NLL to be zero during minimization # discrete nuisance configs @@ -624,8 +625,8 @@ class ExtendedMinimizer(AbstractObject): self.stdout.info('ExtendedMinimizer::minimize("{}") prefit minimization'.format(self.name)) # prefit minimization self.minimizer.setStrategy(0) - self.minimizer.setEps(self.config['eps']*10) - self.robust_minimize(cascade=cascade) + self.minimizer.setEps(self.config['eps']*100) + self.robust_minimize(cascade=cascade, is_prefit=True) self.minimizer.setStrategy(self.config['strategy']) self.minimizer.setEps(self.config['eps']) @@ -681,37 +682,54 @@ class ExtendedMinimizer(AbstractObject): self.status = status return status - def robust_minimize(self, cascade:bool=True, fit_from_initial:bool=True): + def robust_minimize(self, cascade:bool=True, is_prefit:bool=False): self.stdout.debug('Begin robust minimization.') - strategy = self.config['strategy'] retry = self.config['retry'] minimizer_type = self.config['minimizer_type'] minimizer_algo = self.config['minimizer_algo'] - if fit_from_initial: - variables = self.pdf.getVariables() - snapshot = variables.snapshot() - + + def require_cascade(fit_status:int): + return cascade and (fit_status not in [0, 1]) status = self.single_minimize(minimizer_type, minimizer_algo) # repeat if fit failed or poi(s) at boundary expanded_pois = self.expand_poi_bounds() - def require_cascade(fit_status:int): - return cascade and (fit_status not in [0, 1]) - while ((require_cascade(status) or expanded_pois) and (retry > 0)): - if (not expanded_pois) and (strategy < 2): - strategy += 1 - retry -= 1 - self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' - f'Retrying with strategy {strategy}') - self.minimizer.setStrategy(strategy) - if fit_from_initial: - variables.__assign__(snapshot) - status = self.single_minimize(minimizer_type, minimizer_algo) - expanded_pois = self.expand_poi_bounds() - - if status not in [0, 1]: - self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') - - self.minimizer.setStrategy(self.config['strategy']) + + if self.config['retry_diff_eps']: + eps_init = self.config['eps'] * 100 if is_prefit else self.config['eps'] + eps = eps_init + + while ((require_cascade(status) or expanded_pois) and (retry > 0)): + if (not expanded_pois): + eps *= 10 + retry -= 1 + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' + f'Retrying with eps {eps}') + self.minimizer.setEps(eps) + status = self.single_minimize(minimizer_type, minimizer_algo) + expanded_pois = self.expand_poi_bounds() + + if status not in [0, 1]: + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') + + self.minimizer.setEps(eps_init) + + else: + strategy = self.config['strategy'] + + while ((require_cascade(status) or expanded_pois) and (retry > 0)): + if (not expanded_pois) and (strategy < 2): + strategy += 1 + retry -= 1 + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}. ' + f'Retrying with strategy {strategy}') + self.minimizer.setStrategy(strategy) + status = self.single_minimize(minimizer_type, minimizer_algo) + expanded_pois = self.expand_poi_bounds() + + if status not in [0, 1]: + self.stdout.error(f'ExtendedMinimizer::robust_minimize("{self.name}") fit failed with status {status}') + + self.minimizer.setStrategy(self.config['strategy']) return status -- GitLab From b9d141aaa698f1ff8c20197fcfafa03fb6ad46ae Mon Sep 17 00:00:00 2001 From: Yizhou Cai <yizhou.cai@cern.ch> Date: Sat, 26 Apr 2025 23:12:50 +0800 Subject: [PATCH 4/5] option of prefit_eps --- quickstats/components/extended_minimizer.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index fabbc364..7588ec61 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -55,6 +55,7 @@ class ExtendedMinimizer(AbstractObject): 'postfit_hesse': 0, 'minuit2_storage_level': 0, 'do_prefit': 0, + 'prefit_eps': 1.0, 'retry_diff_eps': 0, # cms dedicated configs 'set_zero_point': 1, # change the reference point of the NLL to be zero during minimization @@ -625,7 +626,7 @@ class ExtendedMinimizer(AbstractObject): self.stdout.info('ExtendedMinimizer::minimize("{}") prefit minimization'.format(self.name)) # prefit minimization self.minimizer.setStrategy(0) - self.minimizer.setEps(self.config['eps']*100) + self.minimizer.setEps(self.config['prefit_eps']) self.robust_minimize(cascade=cascade, is_prefit=True) self.minimizer.setStrategy(self.config['strategy']) self.minimizer.setEps(self.config['eps']) @@ -695,7 +696,7 @@ class ExtendedMinimizer(AbstractObject): expanded_pois = self.expand_poi_bounds() if self.config['retry_diff_eps']: - eps_init = self.config['eps'] * 100 if is_prefit else self.config['eps'] + eps_init = self.config['prefit_eps'] if is_prefit else self.config['eps'] eps = eps_init while ((require_cascade(status) or expanded_pois) and (retry > 0)): -- GitLab From bff396d63be6d2c9830f42fa55c2e9202d1e1b1a Mon Sep 17 00:00:00 2001 From: Yizhou Cai <yizhou.cai@cern.ch> Date: Sat, 26 Apr 2025 23:19:51 +0800 Subject: [PATCH 5/5] replace do_prefit option by prefit_eps --- quickstats/components/extended_minimizer.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/quickstats/components/extended_minimizer.py b/quickstats/components/extended_minimizer.py index 7588ec61..6c0b6d47 100644 --- a/quickstats/components/extended_minimizer.py +++ b/quickstats/components/extended_minimizer.py @@ -54,8 +54,7 @@ class ExtendedMinimizer(AbstractObject): 'prefit_hesse': 0, 'postfit_hesse': 0, 'minuit2_storage_level': 0, - 'do_prefit': 0, - 'prefit_eps': 1.0, + 'prefit_eps': 0, 'retry_diff_eps': 0, # cms dedicated configs 'set_zero_point': 1, # change the reference point of the NLL to be zero during minimization @@ -622,7 +621,7 @@ class ExtendedMinimizer(AbstractObject): else: self.discrete_nuisance.freeze_discrete_params(True) - if self.config['do_prefit']: + if self.config['prefit_eps'] > 0: self.stdout.info('ExtendedMinimizer::minimize("{}") prefit minimization'.format(self.name)) # prefit minimization self.minimizer.setStrategy(0) -- GitLab