Hot-keys on this page
r m x p toggle line displays
j k next/prev highlighted chunk
0 (zero) top of page
1 (one) first highlighted chunk
1"""
2@file
3@brief Implements a slightly different
4version of the :epkg:`sklearn:compose:TransformedTargetRegressor`.
5"""
6from sklearn.base import BaseEstimator, RegressorMixin, ClassifierMixin, clone
7from sklearn.exceptions import NotFittedError
8from sklearn.linear_model import LinearRegression, LogisticRegression
9from sklearn.metrics import r2_score, accuracy_score
10from .sklearn_transform_inv import BaseReciprocalTransformer
11from .sklearn_transform_inv_fct import FunctionReciprocalTransformer, PermutationReciprocalTransformer
14def _common_get_transform(transformer, is_regression):
15 if isinstance(transformer, str):
16 closest = is_regression
17 if transformer == 'permute':
18 return PermutationReciprocalTransformer(closest=closest)
19 else:
20 return FunctionReciprocalTransformer(transformer)
21 elif isinstance(transformer, BaseReciprocalTransformer):
22 return clone(transformer)
23 raise TypeError("Transformer {} must be a string or on object of type "
24 "BaseReciprocalTransformer.".format(type(transformer)))
27class TransformedTargetRegressor2(BaseEstimator, RegressorMixin):
28 """
29 Meta-estimator to regress on a transformed target.
30 Useful for applying a non-linear transformation in regression
31 problems.
33 Parameters
34 ----------
35 regressor : object, default=LinearRegression()
36 Regressor object such as derived from ``RegressorMixin``. This
37 regressor will automatically be cloned each time prior to fitting.
38 transformer : str or object of type @see cl BaseReciprocalTransformer
40 Attributes
41 ----------
42 regressor_ : object
43 Fitted regressor.
44 transformer_ : object
45 Transformer used in ``fit`` and ``predict``.
47 Examples
48 --------
50 .. runpython::
51 :showcode:
53 import numpy
54 from sklearn.linear_model import LinearRegression
55 from mlinsights.mlmodel import TransformedTargetRegressor2
57 tt = TransformedTargetRegressor2(regressor=LinearRegression(),
58 transformer='log')
59 X = numpy.arange(4).reshape(-1, 1)
60 y = numpy.exp(2 * X).ravel()
61 print(tt.fit(X, y))
62 print(tt.score(X, y))
63 print(tt.regressor_.coef_)
65 See notebook :ref:`sklearntransformedtargetrst` for a more complete example.
66 """
68 def __init__(self, regressor=None, transformer=None):
69 self.regressor = regressor
70 self.transformer = transformer
72 def fit(self, X, y, sample_weight=None):
73 """
74 Fits the model according to the given training data.
76 :param X: {array-like, sparse matrix}, shape (n_samples, n_features)
77 Training vector, where n_samples is the number of samples and
78 n_features is the number of features.
79 :param y: array-like, shape (n_samples,)
80 Target values.
81 :param sample_weight: array-like, shape (n_samples,) optional
82 Array of weights that are assigned to individual samples.
83 If not provided, then each sample is given unit weight.
84 :return: self, object
85 """
86 self.transformer_ = _common_get_transform(self.transformer, True)
87 self.transformer_.fit(X, y, sample_weight=sample_weight)
88 X_trans, y_trans = self.transformer_.transform(X, y)
90 if self.regressor is None:
91 self.regressor_ = LinearRegression()
92 else:
93 self.regressor_ = clone(self.regressor)
95 if sample_weight is None:
96 self.regressor_.fit(X_trans, y_trans)
97 else:
98 self.regressor_.fit(X_trans, y_trans, sample_weight=sample_weight)
100 return self
102 def predict(self, X):
103 """
104 Predicts using the base regressor, applying inverse.
106 :param X: {array-like, sparse matrix}, shape = (n_samples, n_features)
107 Samples.
108 :return: y_hat : array, shape = (n_samples,)
109 Predicted values.
110 """
111 if not hasattr(self, 'regressor_'):
112 raise NotFittedError( # pragma: no cover
113 "This instance {} is not fitted yet. Call 'fit' with "
114 "appropriate arguments before using this method.".format(
115 type(self)))
116 X_trans, _ = self.transformer_.transform(X, None)
117 pred = self.regressor_.predict(X_trans)
119 inv = self.transformer_.get_fct_inv()
120 _, pred_inv = inv.transform(X_trans, pred)
121 return pred_inv
123 def score(self, X, y, sample_weight=None):
124 """
125 Scores the model with
126 :epkg:`sklearn:metrics:r2_score`.
127 """
128 yp = self.predict(X)
129 return r2_score(y, yp, sample_weight=sample_weight)
131 def _more_tags(self):
132 return {'poor_score': True, 'no_validation': True}
135class TransformedTargetClassifier2(BaseEstimator, ClassifierMixin):
136 """
137 Meta-estimator to classify on a transformed target.
138 Useful for applying permutation transformation in classification
139 problems.
141 Parameters
142 ----------
143 classifier : object, default=LogisticRegression()
144 Classifier object such as derived from ``ClassifierMixin``. This
145 classifier will automatically be cloned each time prior to fitting.
146 transformer : str or object of type @see cl BaseReciprocalTransformer
148 Attributes
149 ----------
150 classifier_ : object
151 Fitted classifier.
152 transformer_ : object
153 Transformer used in ``fit``, ``predict``, ``decision_function``,
154 ``predict_proba``.
156 Examples
157 --------
159 .. runpython::
160 :showcode:
162 import numpy
163 from sklearn.linear_model import LogisticRegression
164 from mlinsights.mlmodel import TransformedTargetClassifier2
166 tt = TransformedTargetClassifier2(classifier=LogisticRegression(),
167 transformer='permute')
168 X = numpy.arange(4).reshape(-1, 1)
169 y = numpy.array([0, 1, 0, 1])
170 print(tt.fit(X, y))
171 print(tt.score(X, y))
172 print(tt.classifier_.coef_)
174 See notebook :ref:`sklearntransformedtargetrst` for a more complete example.
175 """
177 def __init__(self, classifier=None, transformer=None):
178 self.classifier = classifier
179 self.transformer = transformer
181 def fit(self, X, y, sample_weight=None):
182 """
183 Fits the model according to the given training data.
185 :param X: {array-like, sparse matrix}, shape (n_samples, n_features)
186 Training vector, where n_samples is the number of samples and
187 n_features is the number of features.
188 :param y: array-like, shape (n_samples,)
189 Target values.
190 :param sample_weight: array-like, shape (n_samples,) optional
191 Array of weights that are assigned to individual samples.
192 If not provided, then each sample is given unit weight.
193 :return: self, object
194 """
195 self.transformer_ = _common_get_transform(self.transformer, False)
196 self.transformer_.fit(X, y, sample_weight=sample_weight)
197 X_trans, y_trans = self.transformer_.transform(X, y)
199 if self.classifier is None:
200 self.classifier_ = LogisticRegression()
201 else:
202 self.classifier_ = clone(self.classifier)
204 if sample_weight is None:
205 self.classifier_.fit(X_trans, y_trans)
206 else:
207 self.classifier_.fit(X_trans, y_trans, sample_weight=sample_weight)
209 return self
211 def _check_is_fitted(self):
212 if not hasattr(self, 'classifier_'):
213 raise NotFittedError(
214 "This instance {} is not fitted yet. Call 'fit' with "
215 "appropriate arguments before using this method.".format(
216 type(self)))
218 @property
219 def classes_(self):
220 """
221 Returns the classes.
222 """
223 self._check_is_fitted()
224 inv = self.transformer_.get_fct_inv()
225 _, pred_inv = inv.transform(None, self.classifier_.classes_)
226 return pred_inv
228 def _apply(self, X, method):
229 """
230 Calls *predict*, *predict_proba* or *decision_function*
231 using the base classifier, applying inverse.
233 :param X: {array-like, sparse matrix}, shape = (n_samples, n_features)
234 Samples.
235 :return: y_hat, array, shape = (n_samples,)
236 Predicted values.
237 """
238 self._check_is_fitted()
239 if not hasattr(self.classifier_, method):
240 raise RuntimeError("Unable to find method '{}' in model {}.".format(
241 method, type(self.classifier_)))
242 meth = getattr(self.classifier_, method)
243 X_trans, _ = self.transformer_.transform(X, None)
244 pred = meth(X_trans)
245 inv = self.transformer_.get_fct_inv()
246 _, pred_inv = inv.transform(X_trans, pred)
247 return pred_inv
249 def predict(self, X):
250 """
251 Predicts using the base classifier, applying inverse.
253 :param X: {array-like, sparse matrix}, shape = (n_samples, n_features)
254 Samples.
255 :return: y_hat, array, shape = (n_samples,)
256 Predicted values.
257 """
258 return self._apply(X, 'predict')
260 def predict_proba(self, X):
261 """
262 Predicts using the base classifier, applying inverse.
264 :param X: {array-like, sparse matrix}, shape = (n_samples, n_features)
265 Samples.
266 :return: predict probabilities, array, shape = (n_samples, n_classes)
267 Predicted values.
268 """
269 return self._apply(X, 'predict_proba')
271 def decision_function(self, X):
272 """
273 Predicts using the base classifier, applying inverse.
275 :param X: {array-like, sparse matrix}, shape = (n_samples, n_features)
276 Samples.
277 :return: raw score : array, shape = (n_samples, ?)
278 """
279 return self._apply(X, 'decision_function')
281 def score(self, X, y, sample_weight=None):
282 """
283 Scores the model with
284 :epkg:`sklearn:metrics:accuracy_score`.
285 """
286 yp = self.predict(X)
287 return accuracy_score(y, yp, sample_weight=sample_weight)
289 def _more_tags(self):
290 return {'poor_score': True, 'no_validation': True}