Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

FIX_123 #133

Merged
merged 4 commits into from
Mar 11, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion autoPyTorch/api/base_task.py
Original file line number Diff line number Diff line change
Expand Up @@ -227,7 +227,7 @@ def set_pipeline_config(
Args:
**pipeline_config_kwargs: Valid config options include "num_run",
"device", "budget_type", "epochs", "runtime", "torch_num_threads",
"early_stopping", "use_tensorboard_logger", "use_pynisher",
"early_stopping", "use_tensorboard_logger",
"metrics_during_training"

Returns:
Expand Down
1 change: 0 additions & 1 deletion autoPyTorch/configs/default_pipeline_options.json
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,5 @@
"torch_num_threads": 1,
"early_stopping": 20,
"use_tensorboard_logger": "False",
"use_pynisher": "False",
"metrics_during_training": "True"
}
1 change: 0 additions & 1 deletion autoPyTorch/pipeline/base_pipeline.py
Original file line number Diff line number Diff line change
Expand Up @@ -546,6 +546,5 @@ def get_default_pipeline_options() -> Dict[str, Any]:
'torch_num_threads': 1,
'early_stopping': 10,
'use_tensorboard_logger': True,
'use_pynisher': False,
'metrics_during_training': True
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,6 @@ def __init__(self,

It also allows to define a 'epoch_or_time' budget type, which means,
the first of them both which is exhausted, is honored

In case use_pynisher is set to false, this function allows to
still terminate the task with a time domain consideration
"""
self.start_time = time.time()
self.budget_type = budget_type
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,8 +12,6 @@

import numpy as np

import pynisher

import torch
from torch.optim import Optimizer
from torch.optim.lr_scheduler import _LRScheduler
Expand Down Expand Up @@ -196,37 +194,16 @@ def fit(self, X: Dict[str, Any], y: Any = None, **kwargs: Any) -> autoPyTorchCom
] if 'logger_port' in X else logging.handlers.DEFAULT_TCP_LOGGING_PORT,
)

fit_function = self._fit
if X['use_pynisher']:
wall_time_in_s = X['runtime'] if 'runtime' in X else None
memory_limit = X['cpu_memory_limit'] if 'cpu_memory_limit' in X else None
fit_function = pynisher.enforce_limits(
wall_time_in_s=wall_time_in_s,
mem_in_mb=memory_limit,
logger=self.logger
)(self._fit)

# Call the actual fit function.
state_dict = fit_function(
self._fit(
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to return the state_dict on line 339

X=X,
y=y,
**kwargs
)

if X['use_pynisher']:
# Normally the X[network] is a pointer to the object, so at the
# end, when we train using X, the pipeline network is updated for free
# If we do multiprocessing (because of pynisher) we have to update
# X[network] manually. we do so in a way that every pipeline component
# can see this new network -- via an update, not overwrite of the pointer
state_dict = state_dict.result
X['network'].load_state_dict(state_dict)

# TODO: when have the optimizer code, the pynisher object might have failed
# We should process this function as Failure if so trough fit_function.exit_status
return cast(autoPyTorchComponent, self.choice)

def _fit(self, X: Dict[str, Any], y: Any = None, **kwargs: Any) -> torch.nn.Module:
def _fit(self, X: Dict[str, Any], y: Any = None, **kwargs: Any) -> 'TrainerChoice':
"""
Fits a component by using an input dictionary with pre-requisites

Expand Down Expand Up @@ -359,7 +336,7 @@ def _fit(self, X: Dict[str, Any], y: Any = None, **kwargs: Any) -> torch.nn.Modu
# Tag as fitted
self.fitted_ = True

return X['network'].state_dict()
return self

def early_stop_handler(self, X: Dict[str, Any]) -> bool:
"""
Expand Down Expand Up @@ -444,10 +421,6 @@ def check_requirements(self, X: Dict[str, Any], y: Any = None) -> None:
raise ValueError('Need a backend to provide the working directory, '
"yet 'backend' was not found in the fit dictionary")

# For resource allocation, we need to know if pynisher is enabled
if 'use_pynisher' not in X:
raise ValueError('To fit a Trainer, expected fit dictionary to have use_pynisher')

# Whether we should evaluate metrics during training or no
if 'metrics_during_training' not in X:
raise ValueError('Missing metrics_during_training in the fit dictionary')
Expand Down
1 change: 0 additions & 1 deletion test/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -290,7 +290,6 @@ def get_fit_dictionary(X, y, validator, backend):
'early_stopping': 10,
'working_dir': '/tmp',
'use_tensorboard_logger': True,
'use_pynisher': False,
'metrics_during_training': True,
'split_id': 0,
'backend': backend,
Expand Down
2 changes: 1 addition & 1 deletion test/test_api/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -268,7 +268,7 @@ def test_tabular_regression(openml_name, resampling_strategy, backend):
# Check that smac was able to find proper models
succesful_runs = [run_value.status for run_value in estimator.run_history.data.values(
) if 'SUCCESS' in str(run_value.status)]
assert len(succesful_runs) > 1, [(k, v) for k, v in estimator.run_history.data.items()]
assert len(succesful_runs) >= 1, [(k, v) for k, v in estimator.run_history.data.items()]

# Search for an existing run key in disc. A individual model might have
# a timeout and hence was not written to disc
Expand Down
7 changes: 5 additions & 2 deletions test/test_pipeline/test_tabular_classification.py
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,10 @@ def test_pipeline_fit(self, fit_dictionary_tabular):
cs = pipeline.get_hyperparameter_search_space()
config = cs.sample_configuration()
pipeline.set_hyperparameters(config)
pipeline.fit(fit_dictionary_tabular)
try:
pipeline.fit(fit_dictionary_tabular)
except Exception as e:
pytest.fail(f"Failed due to {e} for config={config}")

# To make sure we fitted the model, there should be a
# run summary object with accuracy
Expand Down Expand Up @@ -197,7 +200,7 @@ def test_remove_key_check_requirements(self, fit_dictionary_tabular):
"""Makes sure that when a key is removed from X, correct error is outputted"""
pipeline = TabularClassificationPipeline(
dataset_properties=fit_dictionary_tabular['dataset_properties'])
for key in ['num_run', 'device', 'split_id', 'use_pynisher', 'torch_num_threads', 'dataset_properties']:
for key in ['num_run', 'device', 'split_id', 'torch_num_threads', 'dataset_properties']:
fit_dictionary_tabular_copy = fit_dictionary_tabular.copy()
fit_dictionary_tabular_copy.pop(key)
with pytest.raises(ValueError, match=r"To fit .+?, expected fit dictionary to have"):
Expand Down
2 changes: 1 addition & 1 deletion test/test_pipeline/test_tabular_regression.py
Original file line number Diff line number Diff line change
Expand Up @@ -188,7 +188,7 @@ def test_remove_key_check_requirements(self, fit_dictionary_tabular):
"""Makes sure that when a key is removed from X, correct error is outputted"""
pipeline = TabularRegressionPipeline(
dataset_properties=fit_dictionary_tabular['dataset_properties'])
for key in ['num_run', 'device', 'split_id', 'use_pynisher', 'torch_num_threads', 'dataset_properties']:
for key in ['num_run', 'device', 'split_id', 'torch_num_threads', 'dataset_properties']:
fit_dictionary_tabular_copy = fit_dictionary_tabular.copy()
fit_dictionary_tabular_copy.pop(key)
with pytest.raises(ValueError, match=r"To fit .+?, expected fit dictionary to have"):
Expand Down