8000 Added tests for expected output of init_raw_predictions · scikit-learn/scikit-learn@2c06512 · GitHub
[go: up one dir, main page]

Skip to content

Commit 2c06512

Browse files
committed
Added tests for expected output of init_raw_predictions
1 parent 34619c0 commit 2c06512

File tree

2 files changed

+127
-2
lines changed

2 files changed

+127
-2
lines changed

sklearn/ensemble/_gb_losses.py

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -866,7 +866,8 @@ def get_init_raw_predictions(self, X, estimator):
866866
eps = np.finfo(np.float32).eps
867867
proba_pos_class = np.clip(proba_pos_class, eps, 1 - eps)
868868
# according to The Elements of Statistical Learning sec. 10.5, the
869-
# minimizer of the exponential loss is .5 * log odds ratio.
869+
# minimizer of the exponential loss is .5 * log odds ratio. So this is
870+
# the equivalent to .5 * binomial_deviance.get_init_raw_predictions()
870871
raw_predictions = .5 * np.log(proba_pos_class / (1 - proba_pos_class))
871872
return raw_predictions.reshape(-1, 1).astype(np.float64)
872873

sklearn/ensemble/tests/test_gradient_boosting_loss_functions.py

Lines changed: 125 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,14 @@
99

1010
from sklearn.utils import check_random_state
1111
from sklearn.utils.stats import _weighted_percentile
12-
from sklearn.ensemble._gb_losses import BinomialDeviance
1312
from sklearn.ensemble._gb_losses import RegressionLossFunction
1413
from sklearn.ensemble._gb_losses import LeastSquaresError
14+
from sklearn.ensemble._gb_losses import LeastAbsoluteError
15+
from sklearn.ensemble._gb_losses import HuberLossFunction
1516
from sklearn.ensemble._gb_losses import QuantileLossFunction
17+
from sklearn.ensemble._gb_losses import BinomialDeviance
18+
from sklearn.ensemble._gb_losses import MultinomialDeviance
19+
from sklearn.ensemble._gb_losses import ExponentialLoss
1620
from sklearn.ensemble._gb_losses import LOSS_FUNCTIONS
1721

1822

@@ -170,3 +174,123 @@ def test_sample_weight_deviance():
170174
deviance_w_w = loss(y, p, sample_weight)
171175
deviance_wo_w = loss(y, p)
172176
assert deviance_wo_w == deviance_w_w
177+
178+
179+
def test_init_raw_predictions_shapes():
180+
# Make sure get_init_raw_predictions returns float64 arrays with shape
181+
# (n_samples, K) where K is 1 for binary classification and regression, and
182+
# K = n_classes for multiclass classification
183+
rng = np.random.RandomState(0)
184+
185+
n_samples = 100
186+
X = rng.normal(size=(n_samples, 5))
187+
y = rng.normal(size=n_samples)
188+
for loss in (LeastSquaresError(n_classes=1),
189+
LeastAbsoluteError(n_classes=1),
190+
QuantileLossFunction(n_classes=1),
191+
HuberLossFunction(n_classes=1)):
192+
init_estimator = loss.init_estimator().fit(X, y)
193+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
194+
assert raw_predictions.shape == (n_samples, 1)
195+
assert raw_predictions.dtype == np.float64
196+
197+
y = rng.randint(0, 2, size=n_samples)
198+
for loss in (BinomialDeviance(n_classes=2),
199+
ExponentialLoss(n_classes=2)):
200+
init_estimator = loss.init_estimator().fit(X, y)
201+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
202+
assert raw_predictions.shape == (n_samples, 1)
203+
assert raw_predictions.dtype == np.float64
204+
205+
for n_classes in range(3, 5):
206+
y = rng.randint(0, n_classes, size=n_samples)
207+
loss = MultinomialDeviance(n_classes=n_classes)
208+
init_estimator = loss.init_estimator().fit(X, y)
209+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
210+
assert raw_predictions.shape == (n_samples, n_classes)
211+
assert raw_predictions.dtype == np.float64
212+
213+
214+
def test_init_raw_predictions_values():
215+
# Make sure the get_init_raw_predictions() returns the expected values for
216+
# each loss.
217+
rng = np.random.RandomState 57AE (0)
218+
219+
n_samples = 100
220+
X = rng.normal(size=(n_samples, 5))
221+
y = rng.normal(size=n_samples)
222+
223+
# Least squares loss
224+
loss = LeastSquaresError(n_classes=1)
225+
init_estimator = loss.init_estimator().fit(X, y)
226+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
227+
# Make sure baseline prediction is the mean of all targets
228+
assert_almost_equal(raw_predictions, y.mean())
229+
230+
# Least absolute and huber loss
231+
for Loss in (LeastAbsoluteError, HuberLossFunction):
232+
loss = Loss(n_classes=1)
233+
init_estimator = loss.init_estimator().fit(X, y)
234+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
235+
# Make sure baseline prediction is the median of all targets
236+
assert_almost_equal(raw_predictions, np.median(y))
237+
238+
# Quantile loss
239+
for alpha in (.1, .5, .9):
240+
loss = QuantileLossFunction(n_classes=1, alpha=alpha)
241+
init_estimator = loss.init_estimator().fit(X, y)
242+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
243+
# Make sure baseline prediction is the alpha-quantile of all targets
244+
assert_almost_equal(raw_predictions, np.percentile(y, alpha * 100))
245+
246+
y = rng.randint(0, 2, size=n_samples)
247+
248+
# Binomial deviance
249+
loss = BinomialDeviance(n_classes=2)
250+
init_estimator = loss.init_estimator().fit(X, y)
251+
# Make sure baseline prediction is equal to link_function(p), where p
252+
# is the proba of the positive class. We want predict_proba() to return p,
253+
# and by definition
254+
# p = inverse_link_function(raw_prediction) = sigmoid(raw_prediction)
255+
# So we want raw_prediction = link_function(p) = log(p / (1 - p))
256+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
257+
p = y.mean()
258+
assert_almost_equal(raw_predictions, np.log(p / (1 - p)))
259+
260+
# FIXME: uncomment this and fix
261+
# for y_unstable in (np.zeros(shape=n_samples), np.ones(shape=n_samples)):
262+
# init_estimator = loss.init_estimator().fit(X, y_unstable)
263+
# raw_predictions = loss.get_init_raw_predictions(y_unstable,
264+
# init_estimator)
265+
# assert_all_finite(raw_predictions)
266+
267+
# Exponential loss
268+
loss = ExponentialLoss(n_classes=2)
269+
init_estimator = loss.init_estimator().fit(X, y)
270+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
271+
p = y.mean()
272+
assert_almost_equal(raw_predictions, .5 * np.log(p / (1 - p)))
273+
274+
# FIXME: uncomment this and fix
275+
# for y_unstable in (np.zeros(shape=n_samples), np.ones(shape=n_samples)):
276+
# init_estimator = loss.init_estimator().fit(X, y_unstable)
277+
# raw_predictions = loss.get_init_raw_predictions(y_unstable,
278+
# init_estimator)
279+
# assert_all_finite(raw_predictions)
280+
281+
# Multinomial deviance loss
282+
for n_classes in range(3, 5):
283+
y = rng.randint(0, n_classes, size=n_samples)
284+
loss = MultinomialDeviance(n_classes=n_classes)
285+
init_estimator = loss.init_estimator().fit(X, y)
286+
raw_predictions = loss.get_init_raw_predictions(y, init_estimator)
287+
for k in range(n_classes):
288+
p = (y == k).mean()
289+
assert_almost_equal(raw_predictions[:, k], np.log(p))
290+
291+
# FIXME: uncomment this and fix
292+
# for y_unstable in (np.zeros(shape=n_samples), np.ones(shape=n_samples)):
293+
# init_estimator = loss.init_estimator().fit(X, y_unstable)
294+
# raw_predictions = loss.get_init_raw_predictions(y_unstable,
295+
# init_estimator)
296+
# assert_all_finite(raw_predictions)

0 commit comments

Comments
 (0)
0