Skip to content

Commit 8eb775e

Browse files
authored
FIX Add support for scikit-learn 1.8 (#360)
* Handle sklearn force_all_finite rename via local wrappers * Simplify wrappers * Change EOL to CRLF
1 parent dc7e449 commit 8eb775e

1 file changed

Lines changed: 35 additions & 11 deletions

File tree

metric_learn/_util.py

Lines changed: 35 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import numpy as np
22
from numpy.linalg import LinAlgError
3+
from inspect import signature
34
from sklearn.datasets import make_spd_matrix
45
from sklearn.decomposition import PCA
56
from sklearn.utils import check_array
@@ -22,6 +23,29 @@ def vector_norm(X):
2223
return np.linalg.norm(X, axis=1)
2324

2425

26+
_CHECK_ARRAY_SUPPORTS_FORCE_ALL_FINITE = (
27+
'force_all_finite' in signature(check_array).parameters)
28+
_CHECK_X_Y_SUPPORTS_FORCE_ALL_FINITE = (
29+
'force_all_finite' in signature(check_X_y).parameters)
30+
31+
32+
def _check_array(*args, **kwargs):
33+
"""Local wrapper around `sklearn.utils.check_array` to deal with the change
34+
from `force_all_finite` to `ensure_all_finite` in scikit-learn."""
35+
if not _CHECK_ARRAY_SUPPORTS_FORCE_ALL_FINITE and "force_all_finite" in kwargs:
36+
kwargs = kwargs.copy()
37+
kwargs["ensure_all_finite"] = kwargs.pop("force_all_finite")
38+
return check_array(*args, **kwargs)
39+
40+
def _check_X_y(*args, **kwargs):
41+
"""Local wrapper around `sklearn.utils.check_X_y` to deal with the change
42+
from `force_all_finite` to `ensure_all_finite` in scikit-learn."""
43+
if not _CHECK_X_Y_SUPPORTS_FORCE_ALL_FINITE and "force_all_finite" in kwargs:
44+
kwargs = kwargs.copy()
45+
kwargs["ensure_all_finite"] = kwargs.pop("force_all_finite")
46+
return check_X_y(*args, **kwargs)
47+
48+
2549
def check_input(input_data, y=None, preprocessor=None,
2650
type_of_inputs='classic', tuple_size=None, accept_sparse=False,
2751
dtype='numeric', order=None,
@@ -115,14 +139,14 @@ def check_input(input_data, y=None, preprocessor=None,
115139

116140
# We need to convert input_data into a numpy.ndarray if possible, before
117141
# any further checks or conversions, and deal with y if needed. Therefore
118-
# we use check_array/check_X_y with fixed permissive arguments.
142+
# we use the wrappers _check_array/_check_X_y with fixed permissive arguments.
119143
if y is None:
120-
input_data = check_array(input_data, ensure_2d=False, allow_nd=True,
144+
input_data = _check_array(input_data, ensure_2d=False, allow_nd=True,
121145
copy=False, force_all_finite=False,
122146
accept_sparse=True, dtype=None,
123147
ensure_min_features=0, ensure_min_samples=0)
124148
else:
125-
input_data, y = check_X_y(input_data, y, ensure_2d=False, allow_nd=True,
149+
input_data, y = _check_X_y(input_data, y, ensure_2d=False, allow_nd=True,
126150
copy=False, force_all_finite=False,
127151
accept_sparse=True, dtype=None,
128152
ensure_min_features=0, ensure_min_samples=0,
@@ -165,9 +189,9 @@ def check_input_tuples(input_data, context, preprocessor, args_for_sk_checks,
165189
make_error_input(420, input_data, context)
166190
else:
167191
make_error_input(200, input_data, context)
168-
input_data = check_array(input_data, allow_nd=True, ensure_2d=False,
192+
input_data = _check_array(input_data, allow_nd=True, ensure_2d=False,
169193
**args_for_sk_checks)
170-
# we need to check num_features because check_array does not check it
194+
# we need to check num_features because _check_array does not check it
171195
# for 3D inputs:
172196
if args_for_sk_checks['ensure_min_features'] > 0:
173197
n_features = input_data.shape[2]
@@ -180,7 +204,7 @@ def check_input_tuples(input_data, context, preprocessor, args_for_sk_checks,
180204
# normally we don't need to check_tuple_size too because tuple_size
181205
# shouldn't be able to be modified by any preprocessor
182206
if input_data.ndim != 3:
183-
# we have to ensure this because check_array above does not
207+
# we have to ensure this because _check_array above does not
184208
if preprocessor_has_been_applied:
185209
make_error_input(211, input_data, context)
186210
else:
@@ -205,10 +229,10 @@ def check_input_classic(input_data, context, preprocessor, args_for_sk_checks):
205229
else:
206230
make_error_input(100, input_data, context)
207231

208-
input_data = check_array(input_data, allow_nd=True, ensure_2d=False,
232+
input_data = _check_array(input_data, allow_nd=True, ensure_2d=False,
209233
**args_for_sk_checks)
210234
if input_data.ndim != 2:
211-
# we have to ensure this because check_array above does not
235+
# we have to ensure this because _check_array above does not
212236
if preprocessor_has_been_applied:
213237
make_error_input(111, input_data, context)
214238
else:
@@ -317,7 +341,7 @@ def __init__(self, X):
317341
# format with arguments in check_input, and only this latter function
318342
# should return the appropriate errors). We do this only to have a numpy
319343
# array object which can be indexed by another numpy array object.
320-
X = check_array(X,
344+
X = _check_array(X,
321345
accept_sparse=True, dtype=None,
322346
force_all_finite=False,
323347
ensure_2d=False, allow_nd=True,
@@ -514,7 +538,7 @@ def _initialize_components(n_components, input, y=None, init='auto',
514538
if isinstance(init, np.ndarray):
515539
# we copy the array, so that if we update the metric, we don't want to
516540
# update the init
517-
init = check_array(init, copy=True)
541+
init = _check_array(init, copy=True)
518542

519543
# Assert that init.shape[1] = X.shape[1]
520544
if init.shape[1] != n_features:
@@ -656,7 +680,7 @@ def _initialize_metric_mahalanobis(input, init='identity', random_state=None,
656680
if isinstance(init, np.ndarray):
657681
# we copy the array, so that if we update the metric, we don't want to
658682
# update the init
659-
init = check_array(init, copy=True)
683+
init = _check_array(init, copy=True)
660684

661685
# Assert that init.shape[1] = n_features
662686
if init.shape != (n_features,) * 2:

0 commit comments

Comments
 (0)