Skip to content

MAINT deprecate n_jobs in over-sampling algorithms #887

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

Merged
merged 2 commits into from
Jan 16, 2022
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
13 changes: 13 additions & 0 deletions doc/whats_new/v0.10.rst
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,19 @@ Version 0.10.0 (ongoing)
Changelog
---------

Deprecation
...........

- The parameter `n_jobs` has been deprecated from the classes
:class:`~imblearn.over_sampling.ADASYN`,
:class:`~imblearn.over_sampling.BorderlineSMOTE`,
:class:`~imblearn.over_sampling.SMOTE`,
:class:`~imblearn.over_sampling.SMOTENC`,
:class:`~imblearn.over_sampling.SMOTEN`, and
:class:`~imblearn.over_sampling.SVMSMOTE`. Instead, pass a nearest neighbors
estimator where `n_jobs` is set.
:pr:`887` by :user:`Guillaume Lemaitre <glemaitre>`.

Enhancements
............

Expand Down
17 changes: 17 additions & 0 deletions imblearn/over_sampling/_adasyn.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@
# Christos Aridas
# License: MIT

import warnings

import numpy as np
from scipy import sparse

Expand Down Expand Up @@ -53,6 +55,12 @@ class ADASYN(BaseOverSampler):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

Attributes
----------
sampling_strategy_ : dict
Expand Down Expand Up @@ -133,6 +141,15 @@ def _validate_estimator(self):
)

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self._validate_estimator()
random_state = check_random_state(self.random_state)

Expand Down
48 changes: 47 additions & 1 deletion imblearn/over_sampling/_smote/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
# License: MIT

import math
import warnings
from collections import Counter

import numpy as np
Expand Down Expand Up @@ -238,6 +239,12 @@ class SMOTE(BaseSMOTE):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

Attributes
----------
sampling_strategy_ : dict
Expand Down Expand Up @@ -316,6 +323,15 @@ def __init__(
)

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self._validate_estimator()

X_resampled = [X.copy()]
Expand Down Expand Up @@ -388,6 +404,12 @@ class SMOTENC(SMOTE):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

See Also
--------
SMOTE : Over-sample using SMOTE.
Expand Down Expand Up @@ -496,6 +518,15 @@ def _validate_estimator(self):
)

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self.n_features_ = X.shape[1]
self._validate_estimator()

Expand Down Expand Up @@ -636,7 +667,7 @@ def _generate_samples(self, X, nn_data, nn_num, rows, cols, steps):
class SMOTEN(SMOTE):
"""Synthetic Minority Over-sampling Technique for Nominal.

This method is refered as SMOTEN in [1]_. It expects that the data to
This method is referred as SMOTEN in [1]_. It expects that the data to
resample are only made of categorical features.

Read more in the :ref:`User Guide <smote_adasyn>`.
Expand Down Expand Up @@ -664,6 +695,12 @@ class SMOTEN(SMOTE):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

Attributes
----------
sampling_strategy_ : dict
Expand Down Expand Up @@ -755,6 +792,15 @@ def _make_samples(self, X_class, klass, y_dtype, nn_indices, n_samples):
return X_new, y_new

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self._validate_estimator()

X_resampled = [X.copy()]
Expand Down
32 changes: 32 additions & 0 deletions imblearn/over_sampling/_smote/filter.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@
# Dzianis Dudnik
# License: MIT

import warnings

import numpy as np
from scipy import sparse

Expand Down Expand Up @@ -61,6 +63,12 @@ class BorderlineSMOTE(BaseSMOTE):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

m_neighbors : int or object, default=10
The nearest neighbors used to determine if a minority sample is in
"danger". You can pass:
Expand Down Expand Up @@ -176,6 +184,15 @@ def _validate_estimator(self):
)

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self._validate_estimator()

X_resampled = X.copy()
Expand Down Expand Up @@ -289,6 +306,12 @@ class SVMSMOTE(BaseSMOTE):

{n_jobs}

.. deprecated:: 0.10
`n_jobs` has been deprecated in 0.10 and will be removed in 0.12.
It was previously used to set `n_jobs` of nearest neighbors
algorithm. From now on, you can pass an estimator where `n_jobs` is
already set instead.

m_neighbors : int or object, default=10
The nearest neighbors used to determine if a minority sample is in
"danger". You can pass:
Expand Down Expand Up @@ -416,6 +439,15 @@ def _validate_estimator(self):
self.svm_estimator_ = clone(self.svm_estimator)

def _fit_resample(self, X, y):
# FIXME: to be removed in 0.12
if self.n_jobs is not None:
warnings.warn(
"The parameter `n_jobs` has been deprecated in 0.10 and will be "
"removed in 0.12. You can pass an nearest neighbors estimator where "
"`n_jobs` is already set instead.",
FutureWarning,
)

self._validate_estimator()
random_state = check_random_state(self.random_state)
X_resampled = X.copy()
Expand Down
20 changes: 20 additions & 0 deletions imblearn/over_sampling/tests/test_common.py
Original file line number Diff line number Diff line change
Expand Up @@ -116,3 +116,23 @@ def test_numerical_smote_extra_custom_nn(numerical_data, smote):

assert X_res.shape == (120, 2)
assert Counter(y_res) == {0: 60, 1: 60}


# FIXME: to be removed in 0.12
@pytest.mark.parametrize(
"sampler",
[
ADASYN(random_state=0),
BorderlineSMOTE(random_state=0),
SMOTE(random_state=0),
SMOTEN(random_state=0),
SMOTENC([0], random_state=0),
SVMSMOTE(random_state=0),
],
)
def test_n_jobs_deprecation_warning(numerical_data, sampler):
X, y = numerical_data
sampler.set_params(n_jobs=2)
warning_msg = "The parameter `n_jobs` has been deprecated"
with pytest.warns(FutureWarning, match=warning_msg):
sampler.fit_resample(X, y)