@@ -51,31 +51,46 @@ def __ne__(self, other):
51
51
class CheckingClassifier (ClassifierMixin , BaseEstimator ):
52
52
"""Dummy classifier to test pipelining and meta-estimators.
53
53
54
- Checks some property of X and y in fit / predict.
54
+ Checks some property of `X` and `y` in fit / predict.
55
55
This allows testing whether pipelines / cross-validation or metaestimators
56
56
changed the input.
57
57
58
58
Parameters
59
59
----------
60
- check_y
61
- check_X
62
- foo_param
63
- expected_fit_params
60
+ check_y, check_X : callable, default=None
61
+ The callable used to validate `X` and `y`. These callable should return
62
+ a bool where `False` will trigger an `AssertionError`.
63
+
64
+ check_y_params, check_X_params : dict, default=None
65
+ The optional parameters to pass to `check_X` and `check_y`.
66
+
67
+ foo_param : int, default=0
68
+ A `foo` param. When `foo > 1`, the output of :meth:`score` will be 1
69
+ otherwise it is 0.
70
+
71
+ expected_fit_params : list of str, default=None
72
+ A list of the expected parameters given when calling `fit`.
64
73
65
74
Attributes
66
75
----------
67
- classes_
76
+ classes_ : int
77
+ The classes seen during `fit`.
78
+
79
+ n_features_in_ : int
80
+ The number of features seen during `fit`.
68
81
"""
69
- def __init__ (self , check_y = None , check_X = None , foo_param = 0 ,
82
+ def __init__ (self , * , check_y = None , check_y_params = None ,
83
+ check_X = None , check_X_params = None , foo_param = 0 ,
70
84
expected_fit_params = None ):
71
85
self .check_y = check_y
86
+ self .check_y_params = check_y_params
72
87
self .check_X = check_X
88
+ self .check_X_params = check_X_params
73
89
self .foo_param = foo_param
74
90
self .expected_fit_params = expected_fit_params
75
91
76
92
def fit (self , X , y , ** fit_params ):
77
- """
78
- Fit classifier
93
+ """Fit classifier.
79
94
80
95
Parameters
81
96
----------
@@ -89,48 +104,114 @@ def fit(self, X, y, **fit_params):
89
104
90
105
**fit_params : dict of string -> object
91
106
Parameters passed to the ``fit`` method of the estimator
107
+
108
+ Returns
109
+ -------
110
+ self
92
111
"""
93
- assert len (X ) == len (y )
112
+ assert _num_samples (X ) == _num_samples (y )
94
113
if self .check_X is not None :
95
- assert self .check_X (X )
114
+ params = {} if self .check_X_params is None else self .check_X_params
115
+ assert self .check_X (X , ** params )
96
116
if self .check_y is not None :
117
+ params = {} if self .check_y_params is None else self .check_y_params
97
118
assert self .check_y (y )
98
- self .n_features_in_ = len (X )
99
- self .classes_ = np .unique (check_array (y , ensure_2d = False ,
100
- allow_nd = True ))
119
+ self .n_features_in_ = np .shape (X )[1 ]
120
+ self .classes_ = np .unique (
121
+ check_array (y , ensure_2d = False , allow_nd = True )
122
+ )
101
123
if self .expected_fit_params :
102
124
missing = set (self .expected_fit_params ) - set (fit_params )
103
- assert len (missing ) == 0 , 'Expected fit parameter(s) %s not ' \
104
- 'seen.' % list (missing )
125
+ if missing :
126
+ raise AssertionError (
127
+ f'Expected fit parameter(s) { list (missing )} not seen.'
128
+ )
105
129
for key , value in fit_params .items ():
106
- assert len (value ) == len (X ), (
107
- 'Fit parameter %s has length %d; '
108
- 'expected %d.'
109
- % (key , len (value ), len (X )))
130
+ if _num_samples (value ) != _num_samples (X ):
131
+ raise AssertionError (
132
+ f'Fit parameter { key } has length { _num_samples (value )} '
133
+ f'; expected { _num_samples (X )} .'
134
+ )
110
135
111
136
return self
112
137
113
- def predict (self , T ):
114
- """
138
+ def predict (self , X ):
139
+ """Predict the first class seen in `classes_`.
140
+
115
141
Parameters
116
142
----------
117
- T : indexable, length n_samples
143
+ X : array-like of shape (n_samples, n_features)
144
+ The input data.
145
+
146
+ Returns
147
+ -------
148
+ preds : ndarray of shape (n_samples,)
149
+ Predictions of the first class seens in `classes_`.
118
150
"""
119
151
if self .check_X is not None :
120
- assert self .check_X (T )
121
- return self .classes_ [np .zeros (_num_samples (T ), dtype = np .int )]
152
+ params = {} if self .check_X_params is None else self .check_X_params
153
+ assert self .check_X (X , ** params )
154
+ return self .classes_ [np .zeros (_num_samples (X ), dtype = np .int )]
122
155
123
- def score (self , X = None , Y = None ):
156
+ def predict_proba (self , X ):
157
+ """Predict probabilities for each class.
158
+
159
+ Here, the dummy classifier will provide a probability of 1 for the
160
+ first class of `classes_` and 0 otherwise.
161
+
162
+ Parameters
163
+ ----------
164
+ X : array-like of shape (n_samples, n_features)
165
+ The input data.
166
+
167
+ Returns
168
+ -------
169
+ proba : ndarray of shape (n_samples, n_classes)
170
+ The probabilities for each sample and class.
124
171
"""
172
+ proba = np .zeros ((_num_samples (X ), len (self .classes_ )))
173
+ proba [:, 0 ] = 1
174
+ return proba
175
+
176
+ def decision_function (self , X ):
177
+ """Confidence score.
178
+
179
+ Parameters
180
+ ----------
181
+ X : array-like of shape (n_samples, n_features)
182
+ The input data.
183
+
184
+ Returns
185
+ -------
186
+ decision : ndarray of shape (n_samples,) if n_classes == 2\
187
+ else (n_samples, n_classes)
188
+ Confidence score.
189
+ """
190
+ if len (self .classes_ ) == 2 :
191
+ # for binary classifier, the confidence score is related to
192
+ # classes_[1] and therefore should be null.
193
+ return np .zeros (_num_samples (X ))
194
+ else :
195
+ return self .predict_proba (X )
196
+
197
+ def score (self , X = None , Y = None ):
198
+ """Fake score.
199
+
125
200
Parameters
126
201
----------
127
202
X : array-like of shape (n_samples, n_features)
128
203
Input data, where n_samples is the number of samples and
129
204
n_features is the number of features.
130
205
131
- Y : array-like of shape (n_samples, n_output) or (n_samples,), optional
206
+ Y : array-like of shape (n_samples, n_output) or (n_samples,)
132
207
Target relative to X for classification or regression;
133
208
None for unsupervised learning.
209
+
210
+ Returns
211
+ -------
212
+ score : float
213
+ Either 0 or 1 depending of `foo_param` (i.e. `foo_param > 1 =>
214
+ score=1` otherwise `score=0`).
134
215
"""
135
216
if self .foo_param > 1 :
136
217
score = 1.
0 commit comments