Skip to content

Commit 9442805

Browse files
committed
update
1 parent 1c61099 commit 9442805

11 files changed

+21
-222
lines changed

imblearn/ensemble/_bagging.py

Lines changed: 2 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -12,15 +12,13 @@
1212
from sklearn.ensemble import BaggingClassifier
1313
from sklearn.tree import DecisionTreeClassifier
1414
from sklearn.utils._param_validation import HasMethods, Interval, StrOptions
15-
from sklearn.utils.fixes import parse_version
1615

1716
from ..pipeline import Pipeline
1817
from ..under_sampling import RandomUnderSampler
1918
from ..under_sampling.base import BaseUnderSampler
2019
from ..utils import Substitution, check_sampling_strategy, check_target_type
2120
from ..utils._docstring import _n_jobs_docstring, _random_state_docstring
22-
from ..utils._sklearn_compat import _fit_context, sklearn_version
23-
from ._common import _bagging_parameter_constraints
21+
from ..utils._sklearn_compat import _fit_context
2422

2523

2624
@Substitution(
@@ -224,11 +222,7 @@ class BalancedBaggingClassifier(BaggingClassifier):
224222
"""
225223

226224
# make a deepcopy to not modify the original dictionary
227-
if sklearn_version >= parse_version("1.4"):
228-
_parameter_constraints = copy.deepcopy(BaggingClassifier._parameter_constraints)
229-
else:
230-
_parameter_constraints = copy.deepcopy(_bagging_parameter_constraints)
231-
225+
_parameter_constraints = copy.deepcopy(BaggingClassifier._parameter_constraints)
232226
_parameter_constraints.update(
233227
{
234228
"sampling_strategy": [
@@ -241,9 +235,6 @@ class BalancedBaggingClassifier(BaggingClassifier):
241235
"sampler": [HasMethods(["fit_resample"]), None],
242236
}
243237
)
244-
# TODO: remove when minimum supported version of scikit-learn is 1.4
245-
if "base_estimator" in _parameter_constraints:
246-
del _parameter_constraints["base_estimator"]
247238

248239
def __init__(
249240
self,

imblearn/ensemble/_common.py

Lines changed: 1 addition & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -19,10 +19,8 @@ def _estimator_has(attr):
1919
def check(self):
2020
if hasattr(self, "estimators_"):
2121
return hasattr(self.estimators_[0], attr)
22-
elif self.estimator is not None:
22+
else: # self.estimator is not None
2323
return hasattr(self.estimator, attr)
24-
else: # TODO(1.4): Remove when the base_estimator deprecation cycle ends
25-
return hasattr(self.base_estimator, attr)
2624

2725
return check
2826

@@ -45,11 +43,6 @@ def check(self):
4543
"n_jobs": [None, Integral],
4644
"random_state": ["random_state"],
4745
"verbose": ["verbose"],
48-
"base_estimator": [
49-
HasMethods(["fit", "predict"]),
50-
StrOptions({"deprecated"}),
51-
None,
52-
],
5346
}
5447

5548
_adaboost_classifier_parameter_constraints = {

imblearn/ensemble/_easy_ensemble.py

Lines changed: 1 addition & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -5,19 +5,13 @@
55
# License: MIT
66

77
import copy
8-
import inspect
98
import numbers
109

1110
import numpy as np
1211
from sklearn.base import clone
1312
from sklearn.ensemble import AdaBoostClassifier, BaggingClassifier
14-
from sklearn.ensemble._bagging import _parallel_decision_function
15-
from sklearn.ensemble._base import _partition_estimators
1613
from sklearn.utils._param_validation import Interval, StrOptions
1714
from sklearn.utils.fixes import parse_version
18-
from sklearn.utils.metaestimators import available_if
19-
from sklearn.utils.parallel import Parallel, delayed
20-
from sklearn.utils.validation import check_is_fitted
2115

2216
from ..pipeline import Pipeline
2317
from ..under_sampling import RandomUnderSampler
@@ -28,9 +22,8 @@
2822
_fit_context,
2923
get_tags,
3024
sklearn_version,
31-
validate_data,
3225
)
33-
from ._common import _bagging_parameter_constraints, _estimator_has
26+
from ._common import _bagging_parameter_constraints
3427

3528
MAX_INT = np.iinfo(np.int32).max
3629

@@ -276,61 +269,6 @@ def _fit(self, X, y, max_samples=None, max_depth=None, sample_weight=None):
276269
# None.
277270
return super()._fit(X, y, self.max_samples)
278271

279-
# TODO: remove when minimum supported version of scikit-learn is 1.1
280-
@available_if(_estimator_has("decision_function"))
281-
def decision_function(self, X):
282-
"""Average of the decision functions of the base classifiers.
283-
284-
Parameters
285-
----------
286-
X : {array-like, sparse matrix} of shape (n_samples, n_features)
287-
The training input samples. Sparse matrices are accepted only if
288-
they are supported by the base estimator.
289-
290-
Returns
291-
-------
292-
score : ndarray of shape (n_samples, k)
293-
The decision function of the input samples. The columns correspond
294-
to the classes in sorted order, as they appear in the attribute
295-
``classes_``. Regression and binary classification are special
296-
cases with ``k == 1``, otherwise ``k==n_classes``.
297-
"""
298-
check_is_fitted(self)
299-
300-
# Check data
301-
X = validate_data(
302-
self,
303-
X=X,
304-
accept_sparse=["csr", "csc"],
305-
dtype=None,
306-
ensure_all_finite=(
307-
"allow_nan" if get_tags(self).input_tags.allow_nan else True
308-
),
309-
reset=False,
310-
)
311-
312-
# Parallel loop
313-
n_jobs, _, starts = _partition_estimators(self.n_estimators, self.n_jobs)
314-
315-
kwargs = {}
316-
if "params" in inspect.signature(_parallel_decision_function).parameters:
317-
kwargs["params"] = {}
318-
319-
all_decisions = Parallel(n_jobs=n_jobs, verbose=self.verbose)(
320-
delayed(_parallel_decision_function)(
321-
self.estimators_[starts[i] : starts[i + 1]],
322-
self.estimators_features_[starts[i] : starts[i + 1]],
323-
X,
324-
**kwargs,
325-
)
326-
for i in range(n_jobs)
327-
)
328-
329-
# Reduce
330-
decisions = sum(all_decisions) / self.n_estimators
331-
332-
return decisions
333-
334272
@property
335273
def base_estimator_(self):
336274
"""Attribute for older sklearn version compatibility."""

imblearn/ensemble/_forest.py

Lines changed: 15 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,9 @@ def _local_parallel_build_trees(
7474
"bootstrap": bootstrap,
7575
}
7676

77-
if sklearn_version >= parse_version("1.4"):
78-
# TODO: remove when the minimum supported version of scikit-learn will be 1.4
79-
# support for missing values
80-
params_parallel_build_trees["missing_values_in_feature_mask"] = (
81-
missing_values_in_feature_mask
82-
)
77+
params_parallel_build_trees["missing_values_in_feature_mask"] = (
78+
missing_values_in_feature_mask
79+
)
8380

8481
tree = _parallel_build_trees(**params_parallel_build_trees)
8582

@@ -469,20 +466,9 @@ def __init__(
469466
"min_impurity_decrease": min_impurity_decrease,
470467
"ccp_alpha": ccp_alpha,
471468
"max_samples": max_samples,
469+
"monotonic_cst": monotonic_cst,
472470
}
473-
# TODO: remove when the minimum supported version of scikit-learn will be 1.4
474-
if sklearn_version >= parse_version("1.4"):
475-
# use scikit-learn support for monotonic constraints
476-
params_random_forest["monotonic_cst"] = monotonic_cst
477-
else:
478-
if monotonic_cst is not None:
479-
raise ValueError(
480-
"Monotonic constraints are not supported for scikit-learn "
481-
"version < 1.4."
482-
)
483-
# create an attribute for compatibility with other scikit-learn tools such
484-
# as HTML representation.
485-
self.monotonic_cst = monotonic_cst
471+
486472
super().__init__(**params_random_forest)
487473

488474
self.sampling_strategy = sampling_strategy
@@ -548,37 +534,26 @@ def fit(self, X, y, sample_weight=None):
548534
if issparse(y):
549535
raise ValueError("sparse multilabel-indicator for y is not supported.")
550536

551-
# TODO: remove when the minimum supported version of scipy will be 1.4
552-
# Support for missing values
553-
if sklearn_version >= parse_version("1.4"):
554-
ensure_all_finite = False
555-
else:
556-
ensure_all_finite = True
557-
558537
X, y = validate_data(
559538
self,
560539
X=X,
561540
y=y,
562541
multi_output=True,
563542
accept_sparse="csc",
564543
dtype=DTYPE,
565-
ensure_all_finite=ensure_all_finite,
544+
ensure_all_finite=False,
566545
)
567546

568-
# TODO: remove when the minimum supported version of scikit-learn will be 1.4
569-
if sklearn_version >= parse_version("1.4"):
570-
# _compute_missing_values_in_feature_mask checks if X has missing values and
571-
# will raise an error if the underlying tree base estimator can't handle
572-
# missing values. Only the criterion is required to determine if the tree
573-
# supports missing values.
574-
estimator = type(self.estimator)(criterion=self.criterion)
575-
missing_values_in_feature_mask = (
576-
estimator._compute_missing_values_in_feature_mask(
577-
X, estimator_name=self.__class__.__name__
578-
)
547+
# _compute_missing_values_in_feature_mask checks if X has missing values and
548+
# will raise an error if the underlying tree base estimator can't handle
549+
# missing values. Only the criterion is required to determine if the tree
550+
# supports missing values.
551+
estimator = type(self.estimator)(criterion=self.criterion)
552+
missing_values_in_feature_mask = (
553+
estimator._compute_missing_values_in_feature_mask(
554+
X, estimator_name=self.__class__.__name__
579555
)
580-
else:
581-
missing_values_in_feature_mask = None
556+
)
582557

583558
if sample_weight is not None:
584559
sample_weight = _check_sample_weight(sample_weight, X)

imblearn/under_sampling/_prototype_selection/_condensed_nearest_neighbour.py

Lines changed: 0 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@
66
# License: MIT
77

88
import numbers
9-
import warnings
109
from collections import Counter
1110

1211
import numpy as np
@@ -57,14 +56,6 @@ class CondensedNearestNeighbour(BaseCleaningSampler):
5756
corresponds to the class labels from which to sample and the values
5857
are the number of samples to sample.
5958
60-
estimator_ : estimator object
61-
The validated K-nearest neighbor estimator created from `n_neighbors` parameter.
62-
63-
.. deprecated:: 0.12
64-
`estimator_` is deprecated in 0.12 and will be removed in 0.14. Use
65-
`estimators_` instead that contains the list of all K-nearest
66-
neighbors estimator used for each pair of class.
67-
6859
estimators_ : list of estimator objects of shape (n_resampled_classes - 1,)
6960
Contains the K-nearest neighbor estimator used for per of classes.
7061
@@ -247,18 +238,6 @@ def _fit_resample(self, X, y):
247238

248239
return _safe_indexing(X, idx_under), _safe_indexing(y, idx_under)
249240

250-
@property
251-
def estimator_(self):
252-
"""Last fitted k-NN estimator."""
253-
warnings.warn(
254-
(
255-
"`estimator_` attribute has been deprecated in 0.12 and will be "
256-
"removed in 0.14. Use `estimators_` instead."
257-
),
258-
FutureWarning,
259-
)
260-
return self.estimators_[-1]
261-
262241
def _more_tags(self):
263242
return {"sample_indices": True}
264243

imblearn/under_sampling/_prototype_selection/_neighbourhood_cleaning_rule.py

Lines changed: 1 addition & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,14 +5,13 @@
55
# License: MIT
66

77
import numbers
8-
import warnings
98
from collections import Counter
109

1110
import numpy as np
1211
from sklearn.base import clone
1312
from sklearn.neighbors import KNeighborsClassifier, NearestNeighbors
1413
from sklearn.utils import _safe_indexing
15-
from sklearn.utils._param_validation import HasMethods, Hidden, Interval, StrOptions
14+
from sklearn.utils._param_validation import HasMethods, Interval
1615

1716
from ...utils import Substitution
1817
from ...utils._docstring import _n_jobs_docstring
@@ -48,22 +47,6 @@ class NeighbourhoodCleaningRule(BaseCleaningSampler):
4847
:class:`~sklearn.neighbors.base.KNeighborsMixin` that will be used to
4948
find the nearest-neighbors. By default, it will be a 3-NN.
5049
51-
kind_sel : {{"all", "mode"}}, default='all'
52-
Strategy to use in order to exclude samples in the ENN sampling.
53-
54-
- If ``'all'``, all neighbours will have to agree with the samples of
55-
interest to not be excluded.
56-
- If ``'mode'``, the majority vote of the neighbours will be used in
57-
order to exclude a sample.
58-
59-
The strategy `"all"` will be less conservative than `'mode'`. Thus,
60-
more samples will be removed when `kind_sel="all"` generally.
61-
62-
.. deprecated:: 0.12
63-
`kind_sel` is deprecated in 0.12 and will be removed in 0.14.
64-
Currently the parameter has no effect and corresponds always to the
65-
`"all"` strategy.
66-
6750
threshold_cleaning : float, default=0.5
6851
Threshold used to whether consider a class or not during the cleaning
6952
after applying ENN. A class will be considered during cleaning when:
@@ -150,7 +133,6 @@ class NeighbourhoodCleaningRule(BaseCleaningSampler):
150133
Interval(numbers.Integral, 1, None, closed="left"),
151134
HasMethods(["kneighbors", "kneighbors_graph"]),
152135
],
153-
"kind_sel": [StrOptions({"all", "mode"}), Hidden(StrOptions({"deprecated"}))],
154136
"threshold_cleaning": [Interval(numbers.Real, 0, None, closed="neither")],
155137
"n_jobs": [numbers.Integral, None],
156138
}
@@ -161,14 +143,12 @@ def __init__(
161143
sampling_strategy="auto",
162144
edited_nearest_neighbours=None,
163145
n_neighbors=3,
164-
kind_sel="deprecated",
165146
threshold_cleaning=0.5,
166147
n_jobs=None,
167148
):
168149
super().__init__(sampling_strategy=sampling_strategy)
169150
self.edited_nearest_neighbours = edited_nearest_neighbours
170151
self.n_neighbors = n_neighbors
171-
self.kind_sel = kind_sel
172152
self.threshold_cleaning = threshold_cleaning
173153
self.n_jobs = n_jobs
174154

@@ -197,14 +177,6 @@ def _validate_estimator(self):
197177
self.edited_nearest_neighbours_ = clone(self.edited_nearest_neighbours)
198178

199179
def _fit_resample(self, X, y):
200-
if self.kind_sel != "deprecated":
201-
warnings.warn(
202-
(
203-
"`kind_sel` is deprecated in 0.12 and will be removed in 0.14. "
204-
"It already has not effect and corresponds to the `'all'` option."
205-
),
206-
FutureWarning,
207-
)
208180
self._validate_estimator()
209181
self.edited_nearest_neighbours_.fit_resample(X, y)
210182
index_not_a1 = self.edited_nearest_neighbours_.sample_indices_

0 commit comments

Comments
 (0)