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

SequentialFeatureSelection Early Stopping Criterion #886

Open
wants to merge 6 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from 1 commit
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
Prev Previous commit
Next Next commit
improvements: #886 (comment)
  • Loading branch information
aldder committed Feb 2, 2022
commit f99fec4c2c16d5d35db8df8d869b812a4eae1d91
21 changes: 9 additions & 12 deletions mlxtend/feature_selection/sequential_feature_selector.py
Original file line number Diff line number Diff line change
Expand Up @@ -114,14 +114,11 @@ class SequentialFeatureSelector(_BaseXComposition, MetaEstimatorMixin):
n_jobs : int (default: 1)
The number of CPUs to use for evaluating different feature subsets
in parallel. -1 means 'all CPUs'.
early_stop : bool (default: False)
Determines whether to prematurely stop execution if the score does not
improve after a number of iterations set by the `early_stop_rounds`
parameter.
early_stop_rounds : int (default 3)
Used when `early_stop` is True, it determines the number of iterations
after which, if no performance boost has been seen, execution is
stopped.
early_stop_rounds : int (default 0)
Enable early stopping criterion when > 0, this value determines the
number of iterations after which, if no performance boost has been
seen, execution is stopped.
Used only when `k_features == 'best'` or `k_features == 'parsimonious'`
pre_dispatch : int, or string (default: '2*n_jobs')
Controls the number of jobs that get dispatched
during parallel execution if `n_jobs > 1` or `n_jobs=-1`.
Expand Down Expand Up @@ -186,8 +183,7 @@ def __init__(self, estimator, k_features=1,
forward=True, floating=False,
verbose=0, scoring=None,
cv=5, n_jobs=1,
early_stop=False,
early_stop_rounds=3,
early_stop_rounds=0,
pre_dispatch='2*n_jobs',
clone_estimator=True,
fixed_features=None):
Expand Down Expand Up @@ -216,7 +212,6 @@ def __init__(self, estimator, k_features=1,
'an integer value greater than or equal to 0.'
'Got %d' % early_stop_rounds)
Copy link
Owner

Choose a reason for hiding this comment

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

I think ...Got %d' % early_stop_rounds might not work if early_stop_rounds is not an integer. Maybe it's better to replace it with

...Got %s' % early_stop_rounds

Copy link
Author

Choose a reason for hiding this comment

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

Right!


self.early_stop = early_stop
self.early_stop_rounds = early_stop_rounds

if fixed_features is not None:
Expand Down Expand Up @@ -571,7 +566,9 @@ def fit(self, X, y, custom_feature_names=None, groups=None, **fit_params):
raise KeyboardInterrupt

# early stop
if self.early_stop and k != k_to_select:
if self.early_stop_rounds \
and k != k_to_select \
and self.k_features in {'best', 'parsimonious'}:
if k_score <= best_score:
early_stop_count -= 1
if early_stop_count == 0:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -997,7 +997,7 @@ def test_run_forward_earlystop():
knn = KNeighborsClassifier()
esr = 2
sfs = SFS(estimator=knn,
k_features=X_iris_with_noise.shape[1],
k_features='best',
forward=True,
floating=False,
early_stop=True,
Expand All @@ -1021,7 +1021,7 @@ def test_run_backward_earlystop():
knn = KNeighborsClassifier()
esr = 2
sfs = SFS(estimator=knn,
k_features=1,
k_features='best',
forward=False,
floating=False,
early_stop=True,
Expand Down