Skip to content

Commit 10103f8

Browse files
authored
MNT scikit-learn 0.23 compatibility (#65)
1 parent a5355a2 commit 10103f8

File tree

12 files changed

+108
-86
lines changed

12 files changed

+108
-86
lines changed

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ Dependencies
3333
scikit-learn-extra requires,
3434

3535
- Python (>=3.6)
36-
- scikit-learn (>=0.21), and its dependencies
36+
- scikit-learn (>=0.22), and its dependencies
3737

3838

3939
User installation

azure-pipelines.yml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ jobs:
99
python.version: '3.6'
1010
NUMPY_VERSION: "1.13.3"
1111
SCIPY_VERSION: "0.19.1"
12-
SKLEARN_VERSION: "0.21.2"
12+
SKLEARN_VERSION: "0.22.2post1"
1313
Python37:
1414
python.version: '3.7'
1515
NUMPY_VERSION: "1.16.5"
@@ -63,7 +63,7 @@ jobs:
6363
python.version: '3.6'
6464
NUMPY_VERSION: "1.13.3"
6565
SCIPY_VERSION: "0.19.1"
66-
SKLEARN_VERSION: "0.21.2"
66+
SKLEARN_VERSION: "0.22.2post1"
6767
Python37:
6868
python.version: '3.7'
6969
NUMPY_VERSION: "1.16.5"
@@ -115,7 +115,7 @@ jobs:
115115
python.version: '3.6'
116116
NUMPY_VERSION: "1.13.3"
117117
SCIPY_VERSION: "1.0.1"
118-
SKLEARN_VERSION: "0.21.2"
118+
SKLEARN_VERSION: "0.22.2post1"
119119
Python38:
120120
python_ver: '38'
121121
python.version: '3.8'

conftest.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
import sys
2+
from distutils.version import LooseVersion
3+
import sklearn
4+
5+
import pytest
6+
from _pytest.doctest import DoctestItem
7+
8+
9+
def pytest_collection_modifyitems(config, items):
10+
11+
# numpy changed the str/repr formatting of numpy arrays in 1.14. We want to
12+
# run doctests only for numpy >= 1.14.
13+
skip_doctests = False
14+
try:
15+
import numpy as np
16+
17+
if LooseVersion(np.__version__) < LooseVersion("1.14") or LooseVersion(
18+
sklearn.__version__
19+
) < LooseVersion("0.23.0"):
20+
reason = (
21+
"doctests are only run for numpy >= 1.14 "
22+
"and scikit-learn >=0.23.0"
23+
)
24+
skip_doctests = True
25+
elif sys.platform.startswith("win32"):
26+
reason = (
27+
"doctests are not run for Windows because numpy arrays "
28+
"repr is inconsistent across platforms."
29+
)
30+
skip_doctests = True
31+
except ImportError:
32+
pass
33+
34+
if skip_doctests:
35+
skip_marker = pytest.mark.skip(reason=reason)
36+
37+
for item in items:
38+
if isinstance(item, DoctestItem):
39+
item.add_marker(skip_marker)

doc/install.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ Dependencies
77
scikit-learn-extra requires,
88

99
- Python (>=3.6)
10-
- scikit-learn (>=0.21), and its dependencies
10+
- scikit-learn (>=0.22), and its dependencies
1111

1212

1313
User installation

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@
2626
LICENSE = "new BSD"
2727
DOWNLOAD_URL = "https://github.com/scikit-learn-contrib/scikit-learn-extra"
2828
VERSION = __version__ # noqa
29-
INSTALL_REQUIRES = ["numpy>=1.13.3", "scipy>=0.19.1", "scikit-learn>=0.21.0"]
29+
INSTALL_REQUIRES = ["numpy>=1.13.3", "scipy>=0.19.1", "scikit-learn>=0.22.0"]
3030
CLASSIFIERS = [
3131
"Intended Audience :: Science/Research",
3232
"Intended Audience :: Developers",

sklearn_extra/cluster/tests/test_k_medoids.py

Lines changed: 34 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
import numpy as np
44
from unittest import mock
55
from scipy.sparse import csc_matrix
6+
import pytest
67

78
from sklearn.datasets import load_iris
89
from sklearn.metrics.pairwise import PAIRWISE_DISTANCE_FUNCTIONS
910
from sklearn.metrics.pairwise import euclidean_distances
10-
from sklearn.utils.testing import assert_array_equal, assert_equal
11-
from sklearn.utils.testing import assert_raise_message, assert_warns_message
12-
from sklearn.utils.testing import assert_allclose
11+
from numpy.testing import assert_allclose, assert_array_equal
1312

1413
from sklearn_extra.cluster import KMedoids
1514
from sklearn.cluster import KMeans
@@ -21,51 +20,37 @@
2120
def test_kmedoids_input_validation_and_fit_check():
2221
rng = np.random.RandomState(seed)
2322
# Invalid parameters
24-
assert_raise_message(
25-
ValueError,
26-
"n_clusters should be a nonnegative " "integer. 0 was given",
27-
KMedoids(n_clusters=0).fit,
28-
X,
29-
)
23+
msg = "n_clusters should be a nonnegative integer. 0 was given"
24+
with pytest.raises(ValueError, match=msg):
25+
KMedoids(n_clusters=0).fit(X)
3026

31-
assert_raise_message(
32-
ValueError,
33-
"n_clusters should be a nonnegative " "integer. None was given",
34-
KMedoids(n_clusters=None).fit,
35-
X,
36-
)
27+
msg = "n_clusters should be a nonnegative integer. None was given"
28+
with pytest.raises(ValueError, match=msg):
29+
KMedoids(n_clusters=None).fit(X)
3730

38-
assert_raise_message(
39-
ValueError,
40-
"max_iter should be a nonnegative " "integer. 0 was given",
41-
KMedoids(n_clusters=1, max_iter=0).fit,
42-
X,
43-
)
31+
msg = "max_iter should be a nonnegative integer. 0 was given"
32+
with pytest.raises(ValueError, match=msg):
33+
KMedoids(n_clusters=1, max_iter=0).fit(X)
4434

45-
assert_raise_message(
46-
ValueError,
47-
"max_iter should be a nonnegative " "integer. None was given",
48-
KMedoids(n_clusters=1, max_iter=None).fit,
49-
X,
50-
)
35+
msg = "max_iter should be a nonnegative integer. None was given"
36+
with pytest.raises(ValueError, match=msg):
37+
KMedoids(n_clusters=1, max_iter=None).fit(X)
5138

52-
assert_raise_message(
53-
ValueError,
54-
"init needs to be one of the following: "
55-
"['random', 'heuristic', 'k-medoids++']",
56-
KMedoids(init=None).fit,
57-
X,
39+
msg = (
40+
r"init needs to be one of the following: "
41+
r".*random.*heuristic.*k-medoids\+\+"
5842
)
43+
with pytest.raises(ValueError, match=msg):
44+
KMedoids(init=None).fit(X)
5945

6046
# Trying to fit 3 samples to 8 clusters
61-
Xsmall = rng.rand(5, 2)
62-
assert_raise_message(
63-
ValueError,
64-
"The number of medoids (8) must be less "
65-
"than the number of samples 5.",
66-
KMedoids(n_clusters=8).fit,
67-
Xsmall,
47+
msg = (
48+
"The number of medoids \(8\) must be less "
49+
"than the number of samples 5."
6850
)
51+
Xsmall = rng.rand(5, 2)
52+
with pytest.raises(ValueError, match=msg):
53+
KMedoids(n_clusters=8).fit(Xsmall)
6954

7055

7156
def test_random_deterministic():
@@ -113,7 +98,8 @@ def test_kmedoids_empty_clusters():
11398
rng = np.random.RandomState(seed)
11499
X = [[1], [1], [1]]
115100
kmedoids = KMedoids(n_clusters=2, random_state=rng)
116-
assert_warns_message(UserWarning, "Cluster 1 is empty!", kmedoids.fit, X)
101+
with pytest.warns(UserWarning, match="Cluster 1 is empty!"):
102+
kmedoids.fit(X)
117103

118104

119105
@mock.patch.object(KMedoids, "_kpp_init", return_value=object())
@@ -212,12 +198,10 @@ def test_max_iter():
212198
model = KMedoids(
213199
n_clusters=10, init="random", random_state=rng, max_iter=1
214200
)
215-
assert_warns_message(
216-
UserWarning,
217-
"Maximum number of iteration reached before",
218-
model.fit,
219-
X_iris,
220-
)
201+
msg = "Maximum number of iteration reached before"
202+
203+
with pytest.warns(UserWarning, match=msg):
204+
model.fit(X_iris)
221205

222206

223207
def test_kmedoids_iris():
@@ -261,7 +245,7 @@ def test_kmedoids_fit_predict_transform():
261245
model = KMedoids(random_state=rng)
262246

263247
labels1 = model.fit_predict(X)
264-
assert_equal(len(labels1), 100)
248+
assert len(labels1) == 100
265249
assert_array_equal(labels1, model.labels_)
266250

267251
labels2 = model.predict(X)
@@ -282,7 +266,7 @@ def my_metric(a, b):
282266

283267
model = KMedoids(random_state=rng, metric=my_metric)
284268
labels1 = model.fit_predict(X)
285-
assert_equal(len(labels1), 100)
269+
assert len(labels1) == 100
286270
assert_array_equal(labels1, model.labels_)
287271

288272

@@ -308,5 +292,5 @@ def test_kmedoids_on_sparse_input():
308292
data = np.array([1, 1])
309293
X = csc_matrix((data, (row, col)), shape=(2, 5))
310294
labels = model.fit_predict(X)
311-
assert_equal(len(labels), 2)
295+
assert len(labels) == 2
312296
assert_array_equal(labels, model.labels_)

sklearn_extra/kernel_approximation/_fastfood.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
# License: BSD 3 clause
22

3+
from math import sqrt
34
import numpy as np
45
from scipy.stats import chi
56

@@ -56,7 +57,7 @@ class Fastfood(BaseEstimator, TransformerMixin):
5657

5758
def __init__(
5859
self,
59-
sigma=np.sqrt(1 / 2),
60+
sigma=sqrt(1 / 2),
6061
n_components=100,
6162
tradeoff_mem_accuracy="accuracy",
6263
random_state=None,

sklearn_extra/kernel_approximation/test_fastfood.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import pytest
22
import numpy as np
33

4-
from sklearn.utils.testing import assert_equal
5-
from sklearn.utils.testing import assert_array_almost_equal
4+
from numpy.testing import assert_array_almost_equal
65
from sklearn.metrics.pairwise import rbf_kernel
76

87
from sklearn_extra.kernel_approximation import Fastfood
@@ -28,7 +27,7 @@
2827
def test_fastfood_enforce_dimensionality_constraint(message, input_, expected):
2928
d, n = input_
3029
output = Fastfood._enforce_dimensionality_constraints(d, n)
31-
assert_equal(expected, output, message)
30+
assert expected == output, message
3231

3332

3433
def test_fastfood():

sklearn_extra/kernel_methods/_eigenpro.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -394,10 +394,12 @@ def _raw_predict(self, X):
394394
return Y
395395

396396
def _get_tags(self):
397-
return {"multioutput": True}
397+
tags = super()._get_tags()
398+
tags["multioutput"] = True
399+
return tags
398400

399401

400-
class EigenProRegressor(BaseEigenPro, RegressorMixin):
402+
class EigenProRegressor(RegressorMixin, BaseEigenPro):
401403
"""Regression using EigenPro iteration.
402404
403405
Train least squared kernel regression model with mini-batch EigenPro
@@ -470,9 +472,7 @@ class EigenProRegressor(BaseEigenPro, RegressorMixin):
470472
>>> y_train = rng.randn(n_samples, n_targets)
471473
>>> rgs = EigenProRegressor(n_epoch=3, gamma=.5, subsample_size=50)
472474
>>> rgs.fit(x_train, y_train)
473-
EigenProRegressor(batch_size='auto', coef0=1, degree=3, gamma=0.5, kernel='rbf',
474-
kernel_params=None, n_components=1000, n_epoch=3,
475-
random_state=None, subsample_size=50)
475+
EigenProRegressor(gamma=0.5, n_epoch=3, subsample_size=50)
476476
>>> y_pred = rgs.predict(x_train)
477477
>>> loss = np.mean(np.square(y_train - y_pred))
478478
"""
@@ -510,7 +510,7 @@ def predict(self, X):
510510
return self._raw_predict(X)
511511

512512

513-
class EigenProClassifier(BaseEigenPro, ClassifierMixin):
513+
class EigenProClassifier(ClassifierMixin, BaseEigenPro):
514514
"""Classification using EigenPro iteration.
515515
516516
Train least squared kernel classification model with mini-batch EigenPro
@@ -584,9 +584,7 @@ class EigenProClassifier(BaseEigenPro, ClassifierMixin):
584584
>>> y_train = rng.randint(n_targets, size=n_samples)
585585
>>> rgs = EigenProClassifier(n_epoch=3, gamma=.01, subsample_size=50)
586586
>>> rgs.fit(x_train, y_train)
587-
EigenProClassifier(batch_size='auto', coef0=1, degree=3, gamma=0.01,
588-
kernel='rbf', kernel_params=None, n_components=1000,
589-
n_epoch=3, random_state=None, subsample_size=50)
587+
EigenProClassifier(gamma=0.01, n_epoch=3, subsample_size=50)
590588
>>> y_pred = rgs.predict(x_train)
591589
>>> loss = np.mean(y_train != y_pred)
592590
"""

sklearn_extra/kernel_methods/tests/test_eigenpro.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import numpy as np
22

33
from sklearn.datasets import make_regression, make_classification
4-
from sklearn.utils.testing import assert_allclose
4+
from numpy.testing import assert_allclose
55
from sklearn_extra.kernel_methods import EigenProRegressor, EigenProClassifier
66

77
import pytest

0 commit comments

Comments
 (0)