Skip to content

Commit

Permalink
merge from version 0.1.3
Browse files Browse the repository at this point in the history
  • Loading branch information
AngelG14 committed Sep 18, 2024
2 parents 6d8e5eb + 89ea280 commit c4bb1a0
Show file tree
Hide file tree
Showing 5 changed files with 120 additions and 4 deletions.
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ Other than most AutoML tools, `naiveautoml` has no (also no implicit) definition

## Python
Install via `pip install naiveautoml.`
The current version is 0.1.2.
The current version is 0.1.3.

We highly recommend to check out the [usage example python notebook](https://github.com/fmohr/naiveautoml/blob/master/python/usage-example.ipynb).

Expand Down
30 changes: 30 additions & 0 deletions python/naiveautoml/algorithm_selection/sklearn.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ def __init__(self,
search_space=None,
standard_classifier=KNeighborsClassifier,
standard_regressor=LinearRegression,
excluded_steps: list = None,
excluded_components: dict = None,
random_state=None,
show_progress=False,
opt_ordering=None,
Expand All @@ -60,6 +62,10 @@ def __init__(self,
:param standard_classifier:
:param standard_regressor:
:param excluded_steps:
list of names of steps to be excluded entirely from the process (`learner` must not be excluded)
:param excluded_components:
dict with keys being step names and values being lists of names of components to be excluded.
:param show_progress:
:param opt_ordering:
:param sparse: whether data is treated sparsely in pre-processing.
Expand All @@ -78,6 +84,15 @@ def __init__(self,
self.opt_ordering = opt_ordering
self.standard_classifier = standard_classifier
self.standard_regressor = standard_regressor

# check whether steps or components are excluedd
if excluded_steps is not None:
if not isinstance(excluded_steps, list):
raise ValueError("excluded_steps must be None or a list of step names")
if "learner" in excluded_steps:
raise ValueError("The 'learner' step must not be excluded in excluded_steps.")
self.excluded_steps = excluded_steps
self.excluded_components = excluded_components
self.strictly_naive = strictly_naive
self.sparse = sparse
self.raise_errors = raise_errors
Expand Down Expand Up @@ -159,6 +174,11 @@ def run(self, deadline=None):
best_score = -np.inf
for step_index, step_name in enumerate(self.opt_ordering):

# check whether this step should be skipped.
if self.excluded_steps is not None and step_name in self.excluded_steps:
self.logger.info(f"No component will be selected for excluded step {step_name}")
continue

# create list of components to try for this slot
step = [step for step in self.search_space if step["name"] == step_name][0]
self.logger.info("--------------------------------------------------")
Expand All @@ -168,6 +188,16 @@ def run(self, deadline=None):
# find best default parametrization for this slot (depending on choice of previously configured slots)
decision = None
for comp in step["components"]:

# check whether this component is excluded by some pattern
if (
self.excluded_components is not None and
step_name in self.excluded_components and
any([pattern in comp["class"] for pattern in self.excluded_components[step_name]])
):
self.logger.info(f"Skipping excluded component {comp['class']}.")
continue

if deadline is not None:
remaining_time = deadline - 10 - time.time()
if remaining_time is not None and remaining_time < 0:
Expand Down
2 changes: 1 addition & 1 deletion python/naiveautoml/naiveautoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ def leaderboard(self):

@property
def chosen_model(self):
return self._chosen_model.clone()
return self._chosen_model

def get_evaluation_pool(self, task):
return EvaluationPool(
Expand Down
3 changes: 1 addition & 2 deletions python/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,12 @@
setup(
name = 'naiveautoml',
packages = find_packages(exclude=["test"]),
version = '0.1.2',
version = '0.1.3',
license='MIT',
description = 'Fast and Timeout-Free Automated Machine Learning for Multi-Class classification, Multi-Label classification, and regression.',
author = 'Felix Mohr',
author_email = '[email protected]',
url = 'https://github.com/fmohr/naiveautoml',
download_url = 'https://github.com/fmohr/naiveautoml/archive/refs/tags/v0.0.27.tar.gz',
keywords = ['AutoML', 'sklearn', 'naive', 'simple', 'multi-class', 'multi-label', 'regression', 'no timeouts'],
install_requires=[
'numpy==1.26.4',
Expand Down
87 changes: 87 additions & 0 deletions python/test/test_naiveautoml.py
Original file line number Diff line number Diff line change
Expand Up @@ -756,3 +756,90 @@ def test_process_leak(self, openmlid):
timeout_candidate=10
)
automl.fit(X_train, y_train)

@parameterized.expand([
(61,)
])
def test_exclusion_of_steps(self, openmlid):

excluded_steps = ["data-pre-processor", "feature-pre-processor"]

self.logger.info(f"Testing exclusion of steps.")
X, y = get_dataset(openmlid, as_numpy=False)
naml = naiveautoml.NaiveAutoML(
logger_name="naml",
timeout_overall=15,
max_hpo_iterations=1,
show_progress=True,
raise_errors=True,
kwargs_as={
"excluded_steps": excluded_steps
}
)
naml.fit(X, y)

# check that no results are there for excluded pre-processors
for excluded_step in excluded_steps:
self.assertEqual(0, len(naml.history[f"{excluded_step}_class"].dropna()))

@parameterized.expand([
(61,)
])
def test_exclusion_of_steps_fails_if_excluding_learner(self, openmlid):

def f():
excluded_steps = ["learner"]

self.logger.info(f"Testing exclusion of steps.")
X, y = get_dataset(openmlid, as_numpy=False)
naml = naiveautoml.NaiveAutoML(
logger_name="naml",
timeout_overall=15,
max_hpo_iterations=1,
show_progress=True,
raise_errors=True,
kwargs_as={
"excluded_steps": excluded_steps
}
)
naml.fit(X, y)

self.assertRaises(ValueError, f)

@parameterized.expand([
(61,)
])
def test_exclusion_of_components(self, openmlid):

excluded_components = {
"data-pre-processor": ["MinMax"],
"feature-pre-processor": ["PolynomialFeatures"]
}

self.logger.info(f"Testing exclusion of steps.")
X, y = get_dataset(openmlid, as_numpy=False)
naml = naiveautoml.NaiveAutoML(
logger_name="naml",
timeout_overall=15,
max_hpo_iterations=0,
show_progress=True,
raise_errors=True,
kwargs_as={
"excluded_components": excluded_components
}
)
naml.fit(X, y)

# check that no results are there for excluded pre-processors
for excluded_step, list_of_excluded_component_names in excluded_components.items():
self.assertTrue(len(naml.history[f"{excluded_step}_class"].dropna()) > 0)
if len(list_of_excluded_component_names) > 0:
for excluded_component_name in list_of_excluded_component_names:

self.assertEqual(
0,
sum([
(n is not None and excluded_component_name in n)
for n in naml.history[f"{excluded_step}_class"]
])
)

0 comments on commit c4bb1a0

Please sign in to comment.