1717)
1818from ax .analysis .utils import validate_experiment
1919from ax .core .base_trial import TrialStatus
20- from ax .core .data import MAP_KEY
2120from ax .core .experiment import Experiment
2221from ax .core .map_metric import MapMetric
2322from ax .core .optimization_config import MultiObjectiveOptimizationConfig
2423from ax .early_stopping .dispatch import get_default_ess_or_none
2524from ax .early_stopping .experiment_replay import replay_experiment
2625from ax .early_stopping .strategies .base import BaseEarlyStoppingStrategy
2726from ax .early_stopping .strategies .percentile import PercentileEarlyStoppingStrategy
28- from ax .early_stopping .utils import estimate_early_stopping_savings
27+ from ax .early_stopping .utils import (
28+ EARLY_STOPPING_NUDGE_MSG ,
29+ EARLY_STOPPING_NUDGE_TITLE ,
30+ EARLY_STOPPING_SAVINGS_TITLE ,
31+ estimate_early_stopping_savings ,
32+ format_early_stopping_savings_message ,
33+ )
2934from ax .generation_strategy .generation_strategy import GenerationStrategy
3035from ax .service .utils .early_stopping import get_early_stopping_metrics
3136from pyre_extensions import none_throws , override
@@ -350,26 +355,10 @@ def _report_early_stopping_status(
350355 n_running = len (experiment .trial_indices_by_status [TrialStatus .RUNNING ])
351356 n_ran = n_stopped + n_completed + n_failed + n_running
352357
353- ess_msg = (
354- f"Throughout this experiment, { n_stopped } trials were early stopped, "
355- f"out of a total of { n_ran } trials. "
356- )
357-
358- if savings > 0 :
359- ess_msg += (
360- f"The capacity savings (computed using { MAP_KEY } ) are "
361- f"estimated to be { savings * 100 :.0f} %."
362- )
363- else :
364- ess_msg += (
365- "Capacity savings are not yet available. Either no trials have "
366- "been early stopped, or no trials have completed (which is "
367- "required to estimate savings). Check back once more trials are "
368- "completed and/or early stopped."
369- )
370-
371358 # Add multi-objective note if applicable
372- subtitle = ess_msg
359+ subtitle = format_early_stopping_savings_message (
360+ n_stopped = n_stopped , n_ran = n_ran , savings = savings
361+ )
373362 if len (target_ess_metric_names ) > 1 :
374363 subtitle += (
375364 f"\n \n Note: Although { len (target_ess_metric_names )} metrics are "
@@ -397,7 +386,7 @@ def _report_early_stopping_status(
397386 )
398387
399388 return self ._create_card (
400- title = "Capacity savings due to early stopping" ,
389+ title = EARLY_STOPPING_SAVINGS_TITLE ,
401390 subtitle = subtitle ,
402391 df = df ,
403392 status = HealthcheckStatus .PASS ,
@@ -437,13 +426,8 @@ def _report_early_stopping_nudge(
437426 best_metric_name = max (metric_to_savings , key = metric_to_savings .get )
438427 best_savings = metric_to_savings [best_metric_name ]
439428
440- subtitle = (
441- "This sweep uses metrics that are **compatible with early stopping**! "
442- "Using early stopping could have saved you both capacity and "
443- "optimization wall time. For example, we estimate that using early "
444- f"stopping on the '{ best_metric_name } ' metric could have provided "
445- f"{ best_savings :.0f} % capacity savings, with no regression in "
446- "optimization performance."
429+ subtitle = EARLY_STOPPING_NUDGE_MSG .format (
430+ metric_name = best_metric_name , savings = best_savings
447431 )
448432
449433 # Append additional info if provided
@@ -462,10 +446,7 @@ def _report_early_stopping_nudge(
462446 ]
463447 df = pd .DataFrame (metric_rows )
464448
465- title = (
466- f"{ best_savings :.0f} % potential capacity savings if you turn on "
467- f"early stopping feature"
468- )
449+ title = EARLY_STOPPING_NUDGE_TITLE .format (savings = best_savings )
469450
470451 return self ._create_card (
471452 title = title ,
0 commit comments