def test_eval_with_limits_holdout_timeout_with_results_in_queue( self, pynisher_mock): def side_effect(**kwargs): queue = kwargs['queue'] queue.put({ 'status': StatusType.SUCCESS, 'loss': 0.5, 'additional_run_info': {} }) m1 = unittest.mock.Mock() m2 = unittest.mock.Mock() m1.return_value = m2 pynisher_mock.return_value = m1 m2.side_effect = side_effect m2.exit_status = pynisher.TimeoutException m2.wall_clock_time = 30 # Test for a succesful run ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) info = ta.start(None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.SUCCESS) self.assertEqual(info[1], 0.5) self.assertIsInstance(info[2], float) # And a crashed run which is in the queue def side_effect(**kwargs): queue = kwargs['queue'] queue.put({ 'status': StatusType.CRASHED, 'loss': 2.0, 'additional_run_info': {} }) m2.side_effect = side_effect ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) info = ta.start(None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.CRASHED) self.assertEqual(info[1], 1.0) self.assertIsInstance(info[2], float)
def test_eval_with_limits_holdout_timeout_with_results_in_queue(self, pynisher_mock): config = unittest.mock.Mock() config.config_id = 198 def side_effect(**kwargs): queue = kwargs['queue'] queue.put({'status': StatusType.SUCCESS, 'loss': 0.5, 'additional_run_info': {}}) m1 = unittest.mock.Mock() m2 = unittest.mock.Mock() m1.return_value = m2 pynisher_mock.return_value = m1 m2.side_effect = side_effect m2.exit_status = pynisher.TimeoutException m2.wall_clock_time = 30 # Test for a succesful run ta = ExecuteTaFuncWithQueue(backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, pynisher_context='forkserver', ) info = ta.run_wrapper(RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.SUCCESS) self.assertEqual(info[1].cost, 0.5) self.assertIsInstance(info[1].time, float) self.assertNotIn('exitcode', info[1].additional_info) # And a crashed run which is in the queue def side_effect(**kwargs): queue = kwargs['queue'] queue.put({'status': StatusType.CRASHED, 'loss': 2.0, 'additional_run_info': {}}) m2.side_effect = side_effect ta = ExecuteTaFuncWithQueue(backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, pynisher_context='forkserver', ) info = ta.run_wrapper(RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.CRASHED) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float) self.assertNotIn('exitcode', info[1].additional_info)
def test_cutoff_lower_than_remaining_time(self, pynisher_mock): config = unittest.mock.Mock() config.config_id = 198 ta = ExecuteTaFuncWithQueue( backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, pynisher_context='forkserver', ) self.stats.ta_runs = 1 ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(pynisher_mock.call_args[1]['wall_time_in_s'], 4) self.assertIsInstance(pynisher_mock.call_args[1]['wall_time_in_s'], int)
def test_eval_with_limits_holdout_fail_timeout(self, pynisher_mock): config = unittest.mock.Mock() config.config_id = 198 m1 = unittest.mock.Mock() m2 = unittest.mock.Mock() m1.return_value = m2 pynisher_mock.return_value = m1 m2.exit_status = pynisher.TimeoutException m2.wall_clock_time = 30 ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) info = ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.TIMEOUT) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float)
def test_eval_with_limits_holdout_2(self, eval_houldout_mock): def side_effect(*args, **kwargs): queue = kwargs['queue'] queue.put({ 'status': StatusType.SUCCESS, 'loss': 0.5, 'additional_run_info': kwargs['instance'] }) eval_houldout_mock.side_effect = side_effect ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.scenario.wallclock_limit = 180 instance = "{'subsample': 30}" info = ta.start(None, cutoff=30, instance=instance) self.assertEqual(info[0], StatusType.SUCCESS) self.assertEqual(info[-1], { 'message': "{'subsample': 30}", 'configuration_origin': 'UNKNOWN' })
def test_eval_with_limits_holdout_fail_silent(self, pynisher_mock): pynisher_mock.return_value = None ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) # The following should not fail because abort on first config crashed is false info = ta.start(config=None, instance=None, cutoff=60) self.assertEqual(info[0], StatusType.CRASHED) self.assertEqual(info[1], 1.0) self.assertIsInstance(info[2], float) self.assertEqual(info[3], { 'configuration_origin': 'UNKNOWN', 'error': "Result queue is empty" }) self.stats.ta_runs += 1 info = ta.start(config=None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.CRASHED) self.assertEqual(info[1], 1.0) self.assertIsInstance(info[2], float) self.assertEqual(info[3], { 'configuration_origin': 'UNKNOWN', 'error': "Result queue is empty" })
def test_exception_in_target_function(self, eval_holdout_mock): config = unittest.mock.Mock() config.config_id = 198 eval_holdout_mock.side_effect = ValueError ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.stats.submitted_ta_runs += 1 info = ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.CRASHED) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float) self.assertEqual(info[1].additional_info['error'], 'ValueError()') self.assertIn('traceback', info[1].additional_info)
def test_eval_with_limits_holdout(self, pynisher_mock): pynisher_mock.side_effect = safe_eval_success_mock config = unittest.mock.Mock() config.config_id = 198 ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) info = ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[0].config.config_id, 198) self.assertEqual(info[1].status, StatusType.SUCCESS) self.assertEqual(info[1].cost, 0.5) self.assertIsInstance(info[1].time, float)
def test_eval_with_limits_holdout_2(self, eval_houldout_mock): config = unittest.mock.Mock() config.config_id = 198 def side_effect(*args, **kwargs): queue = kwargs['queue'] queue.put({'status': StatusType.SUCCESS, 'loss': 0.5, 'additional_run_info': kwargs['instance']}) eval_houldout_mock.side_effect = side_effect ta = ExecuteTaFuncWithQueue(backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, pynisher_context='fork', ) self.scenario.wallclock_limit = 180 instance = "{'subsample': 30}" info = ta.run_wrapper(RunInfo(config=config, cutoff=30, instance=instance, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.SUCCESS) self.assertEqual(len(info[1].additional_info), 2) self.assertIn('configuration_origin', info[1].additional_info) self.assertEqual(info[1].additional_info['message'], "{'subsample': 30}")
def test_eval_with_limits_holdout_fail_memory_error(self, pynisher_mock): pynisher_mock.side_effect = MemoryError config = unittest.mock.Mock() config.config_id = 198 ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=log_loss, cost_for_crash=get_cost_of_crash(log_loss), abort_on_first_run_crash=False, ) info = ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.MEMOUT) # For logloss, worst possible result is MAXINT worst_possible_result = MAXINT self.assertEqual(info[1].cost, worst_possible_result) self.assertIsInstance(info[1].time, float)
def test_eval_with_limits_holdout_fail_silent(self, pynisher_mock): pynisher_mock.return_value = None config = unittest.mock.Mock() config.origin = 'MOCK' config.config_id = 198 ta = ExecuteTaFuncWithQueue( backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, pynisher_context='fork', ) # The following should not fail because abort on first config crashed is false info = ta.run_wrapper( RunInfo(config=config, cutoff=60, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.CRASHED) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float) self.assertEqual( info[1].additional_info, { 'configuration_origin': 'MOCK', 'error': "Result queue is empty", 'exit_status': 0, 'exitcode': 0, 'subprocess_stdout': '', 'subprocess_stderr': '' }) self.stats.submitted_ta_runs += 1 info = ta.run_wrapper( RunInfo(config=config, cutoff=30, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.CRASHED) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float) self.assertEqual( info[1].additional_info, { 'configuration_origin': 'MOCK', 'error': "Result queue is empty", 'exit_status': 0, 'exitcode': 0, 'subprocess_stdout': '', 'subprocess_stderr': '' })
def test_cutoff_lower_than_remaining_time(self, pynisher_mock): ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.stats.ta_runs = 1 ta.start(None, cutoff=30, instance=None) self.assertEqual(pynisher_mock.call_args[1]['wall_time_in_s'], 4) self.assertIsInstance(pynisher_mock.call_args[1]['wall_time_in_s'], int)
def test_zero_or_negative_cutoff(self, pynisher_mock): config = unittest.mock.Mock() config.config_id = 198 ta = ExecuteTaFuncWithQueue(backend=self.backend, autosklearn_seed=1, port=self.logger_port, resampling_strategy='holdout', stats=self.stats, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.scenario.wallclock_limit = 5 self.stats.submitted_ta_runs += 1 run_info, run_value = ta.run_wrapper(RunInfo(config=config, cutoff=9, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(run_value.status, StatusType.STOP)
def test_eval_with_limits_holdout(self, pynisher_mock): pynisher_mock.side_effect = safe_eval_success_mock ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) info = ta.start(None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.SUCCESS) self.assertEqual(info[1], 0.5) self.assertIsInstance(info[2], float)
def test_zero_or_negative_cutoff(self, pynisher_mock): ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.scenario.wallclock_limit = 5 self.stats.ta_runs += 1 self.assertRaises(BudgetExhaustedException, ta.start, None, instance=None, cutoff=9)
def test_silent_exception_in_target_function(self): config = unittest.mock.Mock() config.config_id = 198 delattr(self.backend, 'save_targets_ensemble') ta = ExecuteTaFuncWithQueue( backend=self.backend, port=self.logger_port, autosklearn_seed=1, resampling_strategy='holdout', stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, iterative=False, pynisher_context='fork', ) ta.pynisher_logger = unittest.mock.Mock() self.stats.submitted_ta_runs += 1 info = ta.run_wrapper( RunInfo(config=config, cutoff=3000, instance=None, instance_specific=None, seed=1, capped=False)) self.assertEqual(info[1].status, StatusType.CRASHED, msg=str(info[1].additional_info)) self.assertEqual(info[1].cost, 1.0) self.assertIsInstance(info[1].time, float) self.assertIn( info[1].additional_info['error'], ("""AttributeError("'BackendMock' object has no attribute """ """'save_targets_ensemble'",)""", """AttributeError("'BackendMock' object has no attribute """ """'save_targets_ensemble'")""", """AttributeError('save_targets_ensemble')""")) self.assertNotIn('exitcode', info[1].additional_info) self.assertNotIn('exit_status', info[1].additional_info) self.assertNotIn('traceback', info[1])
def test_eval_with_limits_holdout_fail_memory_error(self, pynisher_mock): pynisher_mock.side_effect = MemoryError ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=log_loss, cost_for_crash=get_cost_of_crash(log_loss), abort_on_first_run_crash=False, ) info = ta.start(None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.MEMOUT) # For logloss, worst possible result is MAXINT worst_possible_result = MAXINT self.assertEqual(info[1], worst_possible_result) self.assertIsInstance(info[2], float)
def test_exception_in_target_function(self, eval_holdout_mock): eval_holdout_mock.side_effect = ValueError ta = ExecuteTaFuncWithQueue( backend=BackendMock(), autosklearn_seed=1, resampling_strategy='holdout', logger=self.logger, stats=self.stats, memory_limit=3072, metric=accuracy, cost_for_crash=get_cost_of_crash(accuracy), abort_on_first_run_crash=False, ) self.stats.ta_runs += 1 info = ta.start(None, instance=None, cutoff=30) self.assertEqual(info[0], StatusType.CRASHED) self.assertEqual(info[1], 1.0) self.assertIsInstance(info[2], float) self.assertEqual(info[3]['error'], 'ValueError()') self.assertIn('traceback', info[3])
# To avoid the output "first run crashed"... stats.submitted_ta_runs += 1 stats.finished_ta_runs += 1 memory_lim = memory_limit_factor * automl_arguments['memory_limit'] ta = ExecuteTaFuncWithQueue( backend=automl.automl_._backend, autosklearn_seed=seed, resampling_strategy='test', memory_limit=memory_lim, disable_file_output=True, logger=logger, stats=stats, scoring_functions=scoring_functions, include=include, metric=automl_arguments['metric'], cost_for_crash=get_cost_of_crash(automl_arguments['metric']), abort_on_first_run_crash=False, ) run_info, run_value = ta.run_wrapper( RunInfo( config=config, instance=None, instance_specific=None, seed=1, cutoff=per_run_time_limit * 3, capped=False, )) if run_value.status == StatusType.SUCCESS: assert len( run_value.additional_info) > 1, run_value.additional_info
def __init__( self, config_space, dataset_name, backend, total_walltime_limit, func_eval_time_limit, memory_limit, metric, watcher, n_jobs, dask_client: dask.distributed.Client, start_num_run=1, data_memory_limit=None, num_metalearning_cfgs=25, config_file=None, seed=1, metadata_directory=None, resampling_strategy='holdout', resampling_strategy_args=None, include_estimators=None, exclude_estimators=None, include_preprocessors=None, exclude_preprocessors=None, disable_file_output=False, smac_scenario_args=None, get_smac_object_callback=None, scoring_functions=None, ensemble_callback: typing.Optional[EnsembleBuilderManager] = None, ): super(AutoMLSMBO, self).__init__() # data related self.dataset_name = dataset_name self.datamanager = None self.metric = metric self.task = None self.backend = backend # the configuration space self.config_space = config_space # the number of parallel workers/jobs self.n_jobs = n_jobs self.dask_client = dask_client # Evaluation self.resampling_strategy = resampling_strategy if resampling_strategy_args is None: resampling_strategy_args = {} self.resampling_strategy_args = resampling_strategy_args # and a bunch of useful limits self.worst_possible_result = get_cost_of_crash(self.metric) self.total_walltime_limit = int(total_walltime_limit) self.func_eval_time_limit = int(func_eval_time_limit) self.memory_limit = memory_limit self.data_memory_limit = data_memory_limit self.watcher = watcher self.num_metalearning_cfgs = num_metalearning_cfgs self.config_file = config_file self.seed = seed self.metadata_directory = metadata_directory self.start_num_run = start_num_run self.include_estimators = include_estimators self.exclude_estimators = exclude_estimators self.include_preprocessors = include_preprocessors self.exclude_preprocessors = exclude_preprocessors self.disable_file_output = disable_file_output self.smac_scenario_args = smac_scenario_args self.get_smac_object_callback = get_smac_object_callback self.scoring_functions = scoring_functions self.ensemble_callback = ensemble_callback dataset_name_ = "" if dataset_name is None else dataset_name logger_name = '%s(%d):%s' % (self.__class__.__name__, self.seed, ":" + dataset_name_) self.logger = get_logger(logger_name)