CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
test_mocking.py206 linesDownload Raw Back to tests
1import numpy as np
2import pytest
3from numpy.testing import assert_array_equal
4from scipy import sparse
5
6from sklearn.datasets import load_iris
7from sklearn.utils import _safe_indexing, check_array
8from sklearn.utils._mocking import (
9    CheckingClassifier,
10    _MockEstimatorOnOffPrediction,
11)
12from sklearn.utils._testing import _convert_container
13from sklearn.utils.fixes import CSR_CONTAINERS
14
15
16@pytest.fixture
17def iris():
18    return load_iris(return_X_y=True)
19
20
21def _success(x):
22    return True
23
24
25def _fail(x):
26    return False
27
28
29@pytest.mark.parametrize(
30    "kwargs",
31    [
32        {},
33        {"check_X": _success},
34        {"check_y": _success},
35        {"check_X": _success, "check_y": _success},
36    ],
37)
38def test_check_on_fit_success(iris, kwargs):
39    X, y = iris
40    CheckingClassifier(**kwargs).fit(X, y)
41
42
43@pytest.mark.parametrize(
44    "kwargs",
45    [
46        {"check_X": _fail},
47        {"check_y": _fail},
48        {"check_X": _success, "check_y": _fail},
49        {"check_X": _fail, "check_y": _success},
50        {"check_X": _fail, "check_y": _fail},
51    ],
52)
53def test_check_on_fit_fail(iris, kwargs):
54    X, y = iris
55    clf = CheckingClassifier(**kwargs)
56    with pytest.raises(AssertionError):
57        clf.fit(X, y)
58
59
60@pytest.mark.parametrize(
61    "pred_func", ["predict", "predict_proba", "decision_function", "score"]
62)
63def test_check_X_on_predict_success(iris, pred_func):
64    X, y = iris
65    clf = CheckingClassifier(check_X=_success).fit(X, y)
66    getattr(clf, pred_func)(X)
67
68
69@pytest.mark.parametrize(
70    "pred_func", ["predict", "predict_proba", "decision_function", "score"]
71)
72def test_check_X_on_predict_fail(iris, pred_func):
73    X, y = iris
74    clf = CheckingClassifier(check_X=_success).fit(X, y)
75    clf.set_params(check_X=_fail)
76    with pytest.raises(AssertionError):
77        getattr(clf, pred_func)(X)
78
79
80@pytest.mark.parametrize("input_type", ["list", "array", "sparse", "dataframe"])
81def test_checking_classifier(iris, input_type):
82    # Check that the CheckingClassifier outputs what we expect
83    X, y = iris
84    X = _convert_container(X, input_type)
85    clf = CheckingClassifier()
86    clf.fit(X, y)
87
88    assert_array_equal(clf.classes_, np.unique(y))
89    assert len(clf.classes_) == 3
90    assert clf.n_features_in_ == 4
91
92    y_pred = clf.predict(X)
93    assert all(pred in clf.classes_ for pred in y_pred)
94
95    assert clf.score(X) == pytest.approx(0)
96    clf.set_params(foo_param=10)
97    assert clf.fit(X, y).score(X) == pytest.approx(1)
98
99    y_proba = clf.predict_proba(X)
100    assert y_proba.shape == (150, 3)
101    assert np.logical_and(y_proba >= 0, y_proba <= 1).all()
102
103    y_decision = clf.decision_function(X)
104    assert y_decision.shape == (150, 3)
105
106    # check the shape in case of binary classification
107    first_2_classes = np.logical_or(y == 0, y == 1)
108    X = _safe_indexing(X, first_2_classes)
109    y = _safe_indexing(y, first_2_classes)
110    clf.fit(X, y)
111
112    y_proba = clf.predict_proba(X)
113    assert y_proba.shape == (100, 2)
114    assert np.logical_and(y_proba >= 0, y_proba <= 1).all()
115
116    y_decision = clf.decision_function(X)
117    assert y_decision.shape == (100,)
118
119
120@pytest.mark.parametrize("csr_container", CSR_CONTAINERS)
121def test_checking_classifier_with_params(iris, csr_container):
122    X, y = iris
123    X_sparse = csr_container(X)
124
125    clf = CheckingClassifier(check_X=sparse.issparse)
126    with pytest.raises(AssertionError):
127        clf.fit(X, y)
128    clf.fit(X_sparse, y)
129
130    clf = CheckingClassifier(
131        check_X=check_array, check_X_params={"accept_sparse": False}
132    )
133    clf.fit(X, y)
134    with pytest.raises(TypeError, match="Sparse data was passed"):
135        clf.fit(X_sparse, y)
136
137
138def test_checking_classifier_fit_params(iris):
139    # check the error raised when the number of samples is not the one expected
140    X, y = iris
141    clf = CheckingClassifier(expected_sample_weight=True)
142    sample_weight = np.ones(len(X) // 2)
143
144    msg = f"sample_weight.shape == ({len(X) // 2},), expected ({len(X)},)!"
145    with pytest.raises(ValueError) as exc:
146        clf.fit(X, y, sample_weight=sample_weight)
147    assert exc.value.args[0] == msg
148
149
150def test_checking_classifier_missing_fit_params(iris):
151    X, y = iris
152    clf = CheckingClassifier(expected_sample_weight=True)
153    err_msg = "Expected sample_weight to be passed"
154    with pytest.raises(AssertionError, match=err_msg):
155        clf.fit(X, y)
156
157
158@pytest.mark.parametrize(
159    "methods_to_check",
160    [["predict"], ["predict", "predict_proba"]],
161)
162@pytest.mark.parametrize(
163    "predict_method", ["predict", "predict_proba", "decision_function", "score"]
164)
165def test_checking_classifier_methods_to_check(iris, methods_to_check, predict_method):
166    # check that methods_to_check allows to bypass checks
167    X, y = iris
168
169    clf = CheckingClassifier(
170        check_X=sparse.issparse,
171        methods_to_check=methods_to_check,
172    )
173
174    clf.fit(X, y)
175    if predict_method in methods_to_check:
176        with pytest.raises(AssertionError):
177            getattr(clf, predict_method)(X)
178    else:
179        getattr(clf, predict_method)(X)
180
181
182@pytest.mark.parametrize(
183    "response_methods",
184    [
185        ["predict"],
186        ["predict", "predict_proba"],
187        ["predict", "decision_function"],
188        ["predict", "predict_proba", "decision_function"],
189    ],
190)
191def test_mock_estimator_on_off_prediction(iris, response_methods):
192    X, y = iris
193    estimator = _MockEstimatorOnOffPrediction(response_methods=response_methods)
194
195    estimator.fit(X, y)
196    assert hasattr(estimator, "classes_")
197    assert_array_equal(estimator.classes_, np.unique(y))
198
199    possible_responses = ["predict", "predict_proba", "decision_function"]
200    for response in possible_responses:
201        if response in response_methods:
202            assert hasattr(estimator, response)
203            assert getattr(estimator, response)(X) == response
204        else:
205            assert not hasattr(estimator, response)
206 
Aluode/PerceptionLabPortable · CoolFace