Skip to content

Commit f0f2bf6

Browse files
ArlindKadraravinkohli
authored andcommitted
Cocktail hotfixes (#245)
* Fixes for the development branch and regularization cocktails * Update implementation * Fix unit tests temporarily * Implementation update and bug fixes * Removing unecessary code * Addressing Ravin's comments [refactor] Address Shuhei's comments [refactor] Address Shuhei's comments [refactor] Address Shuhei's comments [refactor] Address Shuhei's comments
1 parent d0f2875 commit f0f2bf6

File tree

12 files changed

+78
-57
lines changed

12 files changed

+78
-57
lines changed

autoPyTorch/api/base_task.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -261,7 +261,7 @@ def get_dataset(self,
261261
NoResamplingStrategyTypes]] = None,
262262
resampling_strategy_args: Optional[Dict[str, Any]] = None,
263263
dataset_name: Optional[str] = None,
264-
return_only: Optional[bool] = False
264+
update_dataset_attribute: Optional[bool] = True
265265
) -> BaseDataset:
266266
raise NotImplementedError("Function called on BaseTask, this can only be called by "
267267
"specific task which is a child of the BaseTask")
@@ -294,7 +294,7 @@ def set_pipeline_config(self, **pipeline_config_kwargs: Any) -> None:
294294
None
295295
"""
296296
unknown_keys = []
297-
for option, value in pipeline_config_kwargs.items():
297+
for option in pipeline_config_kwargs.keys():
298298
if option in self.pipeline_options.keys():
299299
pass
300300
else:

autoPyTorch/api/tabular_classification.py

Lines changed: 12 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,13 @@ def search(
295295
resampling_strategy=self.resampling_strategy,
296296
resampling_strategy_args=self.resampling_strategy_args,
297297
)
298-
assert isinstance(self.resampling_strategy, (CrossValTypes, HoldoutValTypes)), \
299-
"Val Split is required for HPO search. " \
300-
"Expected 'self.resampling_strategy' in" \
301-
" '(CrossValTypes, HoldoutValTypes) got {}".format(self.resampling_strategy)
298+
299+
if not isinstance(self.resampling_strategy, (CrossValTypes, HoldoutValTypes)):
300+
raise ValueError(
301+
'Hyperparameter optimization requires a validation split. '
302+
'Expected `self.resampling_strategy` to be either '
303+
'(CrossValTypes, HoldoutValTypes), but got {}'.format(self.resampling_strategy)
304+
)
302305

303306

304307
return self._search(
@@ -340,24 +343,24 @@ def predict(
340343
raise ValueError("predict() is only supported after calling search. Kindly call first "
341344
"the estimator fit() method.")
342345

343-
X_test = self.InputValidator.feature_validator.transform(X_test)
346+
X_test = self.input_validator.feature_validator.transform(X_test)
344347
predicted_probabilities = super().predict(X_test, batch_size=batch_size,
345348
n_jobs=n_jobs)
346349

347-
if self.InputValidator.target_validator.is_single_column_target():
350+
if self.input_validator.target_validator.is_single_column_target():
348351
predicted_indexes = np.argmax(predicted_probabilities, axis=1)
349352
else:
350353
predicted_indexes = (predicted_probabilities > 0.5).astype(int)
351354

352355
# Allow to predict in the original domain -- that is, the user is not interested
353356
# in our encoded values
354-
return self.InputValidator.target_validator.inverse_transform(predicted_indexes)
357+
return self.input_validator.target_validator.inverse_transform(predicted_indexes)
355358

356359
def predict_proba(self,
357360
X_test: Union[np.ndarray, pd.DataFrame, List],
358361
batch_size: Optional[int] = None, n_jobs: int = 1) -> np.ndarray:
359-
if self.InputValidator is None or not self.InputValidator._is_fitted:
362+
if self.input_validator is None or not self.input_validator._is_fitted:
360363
raise ValueError("predict() is only supported after calling search. Kindly call first "
361364
"the estimator fit() method.")
362-
X_test = self.InputValidator.feature_validator.transform(X_test)
365+
X_test = self.input_validator.feature_validator.transform(X_test)
363366
return super().predict(X_test, batch_size=batch_size, n_jobs=n_jobs)

autoPyTorch/api/tabular_regression.py

Lines changed: 9 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -295,10 +295,12 @@ def search(
295295
resampling_strategy_args=self.resampling_strategy_args,
296296
)
297297

298-
assert isinstance(self.resampling_strategy, (CrossValTypes, HoldoutValTypes)), \
299-
"Val Split is required for HPO search. " \
300-
"Expected 'self.resampling_strategy' in" \
301-
" '(CrossValTypes, HoldoutValTypes) got {}".format(self.resampling_strategy)
298+
if not isinstance(self.resampling_strategy, (CrossValTypes, HoldoutValTypes)):
299+
raise ValueError(
300+
'Hyperparameter optimization requires a validation split. '
301+
'Expected `self.resampling_strategy` to be either '
302+
'(CrossValTypes, HoldoutValTypes), but got {}'.format(self.resampling_strategy)
303+
)
302304

303305

304306
return self._search(
@@ -326,14 +328,14 @@ def predict(
326328
batch_size: Optional[int] = None,
327329
n_jobs: int = 1
328330
) -> np.ndarray:
329-
if self.InputValidator is None or not self.InputValidator._is_fitted:
331+
if self.input_validator is None or not self.input_validator._is_fitted:
330332
raise ValueError("predict() is only supported after calling search. Kindly call first "
331333
"the estimator fit() method.")
332334

333-
X_test = self.InputValidator.feature_validator.transform(X_test)
335+
X_test = self.input_validator.feature_validator.transform(X_test)
334336
predicted_values = super().predict(X_test, batch_size=batch_size,
335337
n_jobs=n_jobs)
336338

337339
# Allow to predict in the original domain -- that is, the user is not interested
338340
# in our encoded values
339-
return self.InputValidator.target_validator.inverse_transform(predicted_values)
341+
return self.input_validator.target_validator.inverse_transform(predicted_values)

autoPyTorch/data/tabular_feature_validator.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -391,7 +391,7 @@ def _get_columns_to_encode(
391391
feat_type = []
392392

393393
# Make sure each column is a valid type
394-
for i, column in enumerate(X.columns):
394+
for column in X.columns:
395395
if X[column].dtype.name in ['category', 'bool']:
396396

397397
transformed_columns.append(column)
@@ -512,7 +512,7 @@ def infer_objects(self, X: pd.DataFrame) -> pd.DataFrame:
512512
X[key] = X[key].astype(dtype.name)
513513
except Exception as e:
514514
# Try inference if possible
515-
self.logger.warning(f"Tried to cast column {key} to {dtype} caused {e}")
515+
self.logger.warning(f'Casting the column {key} to {dtype} caused the exception {e}')
516516
pass
517517
else:
518518
X = X.infer_objects()

autoPyTorch/evaluation/fit_evaluator.py

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -58,10 +58,12 @@ def __init__(self, backend: Backend, queue: Queue,
5858
pipeline_config=pipeline_config,
5959
search_space_updates=search_space_updates
6060
)
61-
assert isinstance(self.datamanager.resampling_strategy, NoResamplingStrategyTypes),\
62-
"This Evaluator is used for fitting a pipeline on the whole dataset. " \
63-
"Expected 'self.resampling_strategy' to be" \
64-
" 'NoResamplingStrategyTypes' got {}".format(self.datamanager.resampling_strategy)
61+
if not isinstance(self.datamanager.resampling_strategy, NoResamplingStrategyTypes):
62+
raise ValueError(
63+
"FitEvaluator needs to be fitted on the whole dataset and resampling_strategy "
64+
"must be `NoResamplingStrategyTypes`, but got {}".format(
65+
self.datamanager.resampling_strategy
66+
))
6567

6668
self.splits = self.datamanager.splits
6769
self.Y_target: Optional[np.ndarray] = None

autoPyTorch/evaluation/tae.py

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -179,10 +179,10 @@ def __init__(
179179
elif isinstance(self.resampling_strategy, NoResamplingStrategyTypes):
180180
eval_function = autoPyTorch.evaluation.fit_evaluator.eval_function
181181
else:
182-
raise ValueError("Unknown resampling strategy specified."
183-
"Expected resampling strategy to be in "
184-
"'(HoldoutValTypes, CrossValTypes, NoResamplingStrategyTypes)"
185-
"got {}".format(self.resampling_strategy))
182+
raise ValueError("resampling strategy must be in "
183+
"(HoldoutValTypes, CrossValTypes, NoResamplingStrategyTypes), "
184+
"but got {}.".format(self.resampling_strategy)
185+
)
186186

187187
self.worst_possible_result = cost_for_crash
188188

@@ -331,6 +331,7 @@ def run(
331331
info: Optional[List[RunValue]]
332332
additional_run_info: Dict[str, Any]
333333
try:
334+
# By default, self.ta is fit_predict_try_except_decorator
334335
obj = pynisher.enforce_limits(**pynisher_arguments)(self.ta)
335336
obj(**obj_kwargs)
336337
except Exception as e:

autoPyTorch/evaluation/train_evaluator.py

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -133,11 +133,13 @@ def __init__(self, backend: Backend, queue: Queue,
133133
pipeline_config=pipeline_config,
134134
search_space_updates=search_space_updates
135135
)
136-
assert isinstance(self.datamanager.resampling_strategy, (CrossValTypes, HoldoutValTypes)),\
137-
"This Evaluator is used for HPO Search. " \
138-
"Val Split is required for HPO search. " \
139-
"Expected 'self.resampling_strategy' in" \
140-
" '(CrossValTypes, HoldoutValTypes)' got {}".format(self.datamanager.resampling_strategy)
136+
137+
if not isinstance(self.datamanager.resampling_strategy, (CrossValTypes, HoldoutValTypes)):
138+
raise ValueError(
139+
'TrainEvaluator expect to have (CrossValTypes, HoldoutValTypes) as '
140+
'resampling_strategy, but got {}'.format(self.datamanager.resampling_strategy)
141+
)
142+
141143

142144
self.splits = self.datamanager.splits
143145
if self.splits is None:

autoPyTorch/pipeline/components/setup/network_backbone/ResNetBackbone.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,8 @@ def _add_group(self, in_features: int, out_features: int,
6464
out_features (int): output dimensionality for the current block
6565
blocks_per_group (int): Number of ResNet per group
6666
last_block_index (int): block index for shake regularization
67-
dropout (bool): whether or not use dropout
67+
dropout (None, float): dropout value for the group. If none,
68+
no dropout is applied.
6869
"""
6970
blocks = list()
7071
for i in range(blocks_per_group):
@@ -180,9 +181,7 @@ def get_hyperparameter_search_space(
180181

181182
if skip_connection_flag:
182183

183-
shake_drop_prob_flag = False
184-
if 'shake-drop' in multi_branch_choice.value_range:
185-
shake_drop_prob_flag = True
184+
shake_drop_prob_flag = 'shake-drop' in multi_branch_choice.value_range
186185

187186
mb_choice = get_hyperparameter(multi_branch_choice, CategoricalHyperparameter)
188187
cs.add_hyperparameter(mb_choice)
@@ -290,13 +289,21 @@ def _build_block(self, in_features: int, out_features: int) -> nn.Module:
290289
if self.config['use_batch_norm']:
291290
layers.append(nn.BatchNorm1d(in_features))
292291
layers.append(self.activation())
292+
elif not self.config['use_skip_connection']:
293+
# if start norm is not None and skip connection is False
294+
# we will never apply the start_norm for the first layer in the block,
295+
# which is why we should account for this case.
296+
if self.config['use_batch_norm']:
297+
layers.append(nn.BatchNorm1d(in_features))
298+
layers.append(self.activation())
299+
293300
layers.append(nn.Linear(in_features, out_features))
294301

295302
if self.config['use_batch_norm']:
296303
layers.append(nn.BatchNorm1d(out_features))
297304
layers.append(self.activation())
298305

299-
if self.config["use_dropout"]:
306+
if self.dropout is not None:
300307
layers.append(nn.Dropout(self.dropout))
301308
layers.append(nn.Linear(out_features, out_features))
302309

@@ -321,6 +328,7 @@ def forward(self, x: torch.FloatTensor) -> torch.FloatTensor:
321328
if self.config["use_skip_connection"]:
322329
residual = self.shortcut(x)
323330

331+
# TODO make the below code better
324332
if self.config["use_skip_connection"]:
325333
if self.config["multi_branch_choice"] == 'shake-shake':
326334
x1 = self.layers(x)

autoPyTorch/pipeline/components/setup/network_backbone/ShapedResNetBackbone.py

Lines changed: 13 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,13 @@ def build_backbone(self, input_shape: Tuple[int, ...]) -> torch.nn.Sequential:
3131
out_features = self.config["output_dim"]
3232

3333
# use the get_shaped_neuron_counts to update the number of units
34-
neuron_counts = get_shaped_neuron_counts(self.config['resnet_shape'],
35-
in_features,
36-
out_features,
37-
self.config['max_units'],
38-
self.config['num_groups'] + 2)[:-1]
34+
neuron_counts = get_shaped_neuron_counts(
35+
shape=self.config['resnet_shape'],
36+
in_feat=in_features,
37+
out_feat=out_features,
38+
max_neurons=self.config['max_units'],
39+
layer_count=self.config['num_groups'] + 2,
40+
)[:-1]
3941
self.config.update(
4042
{"num_units_%d" % (i): num for i, num in enumerate(neuron_counts)}
4143
)
@@ -45,12 +47,12 @@ def build_backbone(self, input_shape: Tuple[int, ...]) -> torch.nn.Sequential:
4547
# n_units for the architecture, since, it is mostly implemented for the
4648
# output layer, which is part of the head and not of the backbone.
4749
dropout_shape = get_shaped_neuron_counts(
48-
self.config['dropout_shape'], 0, 0, 1000, self.config['num_groups']
49-
)
50-
51-
dropout_shape = [
52-
dropout / 1000 * self.config["max_dropout"] for dropout in dropout_shape
53-
]
50+
shape=self.config['dropout_shape'],
51+
in_feat=0,
52+
out_feat=0,
53+
max_neurons=self.config["max_dropout"],
54+
layer_count=self.config['num_groups'] + 1,
55+
)[:-1]
5456

5557
self.config.update(
5658
{"dropout_%d" % (i + 1): dropout for i, dropout in enumerate(dropout_shape)}

autoPyTorch/pipeline/components/setup/network_head/no_head.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ class NoHead(NetworkHeadComponent):
2020
"""
2121

2222
def build_head(self, input_shape: Tuple[int, ...], output_shape: Tuple[int, ...]) -> nn.Module:
23-
layers = [nn.Flatten()]
23+
layers = []
2424
in_features = np.prod(input_shape).item()
2525
out_features = np.prod(output_shape).item()
2626
layers.append(_activations[self.config["activation"]]())
@@ -34,8 +34,8 @@ def get_properties(dataset_properties: Optional[Dict[str, Any]] = None) -> Dict[
3434
'shortname': 'NoHead',
3535
'name': 'NoHead',
3636
'handles_tabular': True,
37-
'handles_image': True,
38-
'handles_time_series': True,
37+
'handles_image': False,
38+
'handles_time_series': False,
3939
}
4040

4141
@staticmethod

0 commit comments

Comments
 (0)