CoolFace
Apppublic

Aluode/PerceptionLabPortable

sourceHugging Faceupdated 9mo agoView on Hugging Face
0likes
test_isotonic.py709 linesDownload Raw Back to tests
1import copy
2import pickle
3import warnings
4
5import numpy as np
6import pytest
7from scipy.special import expit
8
9import sklearn
10from sklearn.datasets import make_regression
11from sklearn.isotonic import (
12    IsotonicRegression,
13    _make_unique,
14    check_increasing,
15    isotonic_regression,
16)
17from sklearn.utils import shuffle
18from sklearn.utils._testing import (
19    assert_allclose,
20    assert_array_almost_equal,
21    assert_array_equal,
22)
23from sklearn.utils.validation import check_array
24
25
26def test_permutation_invariance():
27    # check that fit is permutation invariant.
28    # regression test of missing sorting of sample-weights
29    ir = IsotonicRegression()
30    x = [1, 2, 3, 4, 5, 6, 7]
31    y = [1, 41, 51, 1, 2, 5, 24]
32    sample_weight = [1, 2, 3, 4, 5, 6, 7]
33    x_s, y_s, sample_weight_s = shuffle(x, y, sample_weight, random_state=0)
34    y_transformed = ir.fit_transform(x, y, sample_weight=sample_weight)
35    y_transformed_s = ir.fit(x_s, y_s, sample_weight=sample_weight_s).transform(x)
36
37    assert_array_equal(y_transformed, y_transformed_s)
38
39
40def test_check_increasing_small_number_of_samples():
41    x = [0, 1, 2]
42    y = [1, 1.1, 1.05]
43
44    with warnings.catch_warnings():
45        warnings.simplefilter("error", UserWarning)
46        is_increasing = check_increasing(x, y)
47
48    assert is_increasing
49
50
51def test_check_increasing_up():
52    x = [0, 1, 2, 3, 4, 5]
53    y = [0, 1.5, 2.77, 8.99, 8.99, 50]
54
55    # Check that we got increasing=True and no warnings
56    with warnings.catch_warnings():
57        warnings.simplefilter("error", UserWarning)
58        is_increasing = check_increasing(x, y)
59
60    assert is_increasing
61
62
63def test_check_increasing_up_extreme():
64    x = [0, 1, 2, 3, 4, 5]
65    y = [0, 1, 2, 3, 4, 5]
66
67    # Check that we got increasing=True and no warnings
68    with warnings.catch_warnings():
69        warnings.simplefilter("error", UserWarning)
70        is_increasing = check_increasing(x, y)
71
72    assert is_increasing
73
74
75def test_check_increasing_down():
76    x = [0, 1, 2, 3, 4, 5]
77    y = [0, -1.5, -2.77, -8.99, -8.99, -50]
78
79    # Check that we got increasing=False and no warnings
80    with warnings.catch_warnings():
81        warnings.simplefilter("error", UserWarning)
82        is_increasing = check_increasing(x, y)
83
84    assert not is_increasing
85
86
87def test_check_increasing_down_extreme():
88    x = [0, 1, 2, 3, 4, 5]
89    y = [0, -1, -2, -3, -4, -5]
90
91    # Check that we got increasing=False and no warnings
92    with warnings.catch_warnings():
93        warnings.simplefilter("error", UserWarning)
94        is_increasing = check_increasing(x, y)
95
96    assert not is_increasing
97
98
99def test_check_ci_warn():
100    x = [0, 1, 2, 3, 4, 5]
101    y = [0, -1, 2, -3, 4, -5]
102
103    # Check that we got increasing=False and CI interval warning
104    msg = "interval"
105    with pytest.warns(UserWarning, match=msg):
106        is_increasing = check_increasing(x, y)
107
108    assert not is_increasing
109
110
111def test_isotonic_regression():
112    y = np.array([3, 7, 5, 9, 8, 7, 10])
113    y_ = np.array([3, 6, 6, 8, 8, 8, 10])
114    assert_array_equal(y_, isotonic_regression(y))
115
116    y = np.array([10, 0, 2])
117    y_ = np.array([4, 4, 4])
118    assert_array_equal(y_, isotonic_regression(y))
119
120    x = np.arange(len(y))
121    ir = IsotonicRegression(y_min=0.0, y_max=1.0)
122    ir.fit(x, y)
123    assert_array_equal(ir.fit(x, y).transform(x), ir.fit_transform(x, y))
124    assert_array_equal(ir.transform(x), ir.predict(x))
125
126    # check that it is immune to permutation
127    perm = np.random.permutation(len(y))
128    ir = IsotonicRegression(y_min=0.0, y_max=1.0)
129    assert_array_equal(ir.fit_transform(x[perm], y[perm]), ir.fit_transform(x, y)[perm])
130    assert_array_equal(ir.transform(x[perm]), ir.transform(x)[perm])
131
132    # check we don't crash when all x are equal:
133    ir = IsotonicRegression()
134    assert_array_equal(ir.fit_transform(np.ones(len(x)), y), np.mean(y))
135
136
137def test_isotonic_regression_ties_min():
138    # Setup examples with ties on minimum
139    x = [1, 1, 2, 3, 4, 5]
140    y = [1, 2, 3, 4, 5, 6]
141    y_true = [1.5, 1.5, 3, 4, 5, 6]
142
143    # Check that we get identical results for fit/transform and fit_transform
144    ir = IsotonicRegression()
145    ir.fit(x, y)
146    assert_array_equal(ir.fit(x, y).transform(x), ir.fit_transform(x, y))
147    assert_array_equal(y_true, ir.fit_transform(x, y))
148
149
150def test_isotonic_regression_ties_max():
151    # Setup examples with ties on maximum
152    x = [1, 2, 3, 4, 5, 5]
153    y = [1, 2, 3, 4, 5, 6]
154    y_true = [1, 2, 3, 4, 5.5, 5.5]
155
156    # Check that we get identical results for fit/transform and fit_transform
157    ir = IsotonicRegression()
158    ir.fit(x, y)
159    assert_array_equal(ir.fit(x, y).transform(x), ir.fit_transform(x, y))
160    assert_array_equal(y_true, ir.fit_transform(x, y))
161
162
163def test_isotonic_regression_ties_secondary_():
164    """
165    Test isotonic regression fit, transform  and fit_transform
166    against the "secondary" ties method and "pituitary" data from R
167     "isotone" package, as detailed in: J. d. Leeuw, K. Hornik, P. Mair,
168     Isotone Optimization in R: Pool-Adjacent-Violators Algorithm
169    (PAVA) and Active Set Methods
170
171    Set values based on pituitary example and
172     the following R command detailed in the paper above:
173    > library("isotone")
174    > data("pituitary")
175    > res1 <- gpava(pituitary$age, pituitary$size, ties="secondary")
176    > res1$x
177
178    `isotone` version: 1.0-2, 2014-09-07
179    R version: R version 3.1.1 (2014-07-10)
180    """
181    x = [8, 8, 8, 10, 10, 10, 12, 12, 12, 14, 14]
182    y = [21, 23.5, 23, 24, 21, 25, 21.5, 22, 19, 23.5, 25]
183    y_true = [
184        22.22222,
185        22.22222,
186        22.22222,
187        22.22222,
188        22.22222,
189        22.22222,
190        22.22222,
191        22.22222,
192        22.22222,
193        24.25,
194        24.25,
195    ]
196
197    # Check fit, transform and fit_transform
198    ir = IsotonicRegression()
199    ir.fit(x, y)
200    assert_array_almost_equal(ir.transform(x), y_true, 4)
201    assert_array_almost_equal(ir.fit_transform(x, y), y_true, 4)
202
203
204def test_isotonic_regression_with_ties_in_differently_sized_groups():
205    """
206    Non-regression test to handle issue 9432:
207    https://github.com/scikit-learn/scikit-learn/issues/9432
208
209    Compare against output in R:
210    > library("isotone")
211    > x <- c(0, 1, 1, 2, 3, 4)
212    > y <- c(0, 0, 1, 0, 0, 1)
213    > res1 <- gpava(x, y, ties="secondary")
214    > res1$x
215
216    `isotone` version: 1.1-0, 2015-07-24
217    R version: R version 3.3.2 (2016-10-31)
218    """
219    x = np.array([0, 1, 1, 2, 3, 4])
220    y = np.array([0, 0, 1, 0, 0, 1])
221    y_true = np.array([0.0, 0.25, 0.25, 0.25, 0.25, 1.0])
222    ir = IsotonicRegression()
223    ir.fit(x, y)
224    assert_array_almost_equal(ir.transform(x), y_true)
225    assert_array_almost_equal(ir.fit_transform(x, y), y_true)
226
227
228def test_isotonic_regression_reversed():
229    y = np.array([10, 9, 10, 7, 6, 6.1, 5])
230    y_result = np.array([10, 9.5, 9.5, 7, 6.05, 6.05, 5])
231
232    y_iso = isotonic_regression(y, increasing=False)
233    assert_allclose(y_iso, y_result)
234
235    y_ = IsotonicRegression(increasing=False).fit_transform(np.arange(len(y)), y)
236    assert_allclose(y_, y_result)
237    assert_array_equal(np.ones(y_[:-1].shape), ((y_[:-1] - y_[1:]) >= 0))
238
239
240def test_isotonic_regression_auto_decreasing():
241    # Set y and x for decreasing
242    y = np.array([10, 9, 10, 7, 6, 6.1, 5])
243    x = np.arange(len(y))
244
245    # Create model and fit_transform
246    ir = IsotonicRegression(increasing="auto")
247    with warnings.catch_warnings(record=True) as w:
248        warnings.simplefilter("always")
249        y_ = ir.fit_transform(x, y)
250        # work-around for pearson divide warnings in scipy <= 0.17.0
251        assert all(["invalid value encountered in " in str(warn.message) for warn in w])
252
253    # Check that relationship decreases
254    is_increasing = y_[0] < y_[-1]
255    assert not is_increasing
256
257
258def test_isotonic_regression_auto_increasing():
259    # Set y and x for decreasing
260    y = np.array([5, 6.1, 6, 7, 10, 9, 10])
261    x = np.arange(len(y))
262
263    # Create model and fit_transform
264    ir = IsotonicRegression(increasing="auto")
265    with warnings.catch_warnings(record=True) as w:
266        warnings.simplefilter("always")
267        y_ = ir.fit_transform(x, y)
268        # work-around for pearson divide warnings in scipy <= 0.17.0
269        assert all(["invalid value encountered in " in str(warn.message) for warn in w])
270
271    # Check that relationship increases
272    is_increasing = y_[0] < y_[-1]
273    assert is_increasing
274
275
276def test_assert_raises_exceptions():
277    ir = IsotonicRegression()
278    rng = np.random.RandomState(42)
279
280    msg = "Found input variables with inconsistent numbers of samples"
281    with pytest.raises(ValueError, match=msg):
282        ir.fit([0, 1, 2], [5, 7, 3], [0.1, 0.6])
283
284    with pytest.raises(ValueError, match=msg):
285        ir.fit([0, 1, 2], [5, 7])
286
287    msg = "X should be a 1d array"
288    with pytest.raises(ValueError, match=msg):
289        ir.fit(rng.randn(3, 10), [0, 1, 2])
290
291    msg = "Isotonic regression input X should be a 1d array"
292    with pytest.raises(ValueError, match=msg):
293        ir.transform(rng.randn(3, 10))
294
295
296def test_isotonic_sample_weight_parameter_default_value():
297    # check if default value of sample_weight parameter is one
298    ir = IsotonicRegression()
299    # random test data
300    rng = np.random.RandomState(42)
301    n = 100
302    x = np.arange(n)
303    y = rng.randint(-50, 50, size=(n,)) + 50.0 * np.log(1 + np.arange(n))
304    # check if value is correctly used
305    weights = np.ones(n)
306    y_set_value = ir.fit_transform(x, y, sample_weight=weights)
307    y_default_value = ir.fit_transform(x, y)
308
309    assert_array_equal(y_set_value, y_default_value)
310
311
312def test_isotonic_min_max_boundaries():
313    # check if min value is used correctly
314    ir = IsotonicRegression(y_min=2, y_max=4)
315    n = 6
316    x = np.arange(n)
317    y = np.arange(n)
318    y_test = [2, 2, 2, 3, 4, 4]
319    y_result = np.round(ir.fit_transform(x, y))
320    assert_array_equal(y_result, y_test)
321
322
323def test_isotonic_sample_weight():
324    ir = IsotonicRegression()
325    x = [1, 2, 3, 4, 5, 6, 7]
326    y = [1, 41, 51, 1, 2, 5, 24]
327    sample_weight = [1, 2, 3, 4, 5, 6, 7]
328    expected_y = [1, 13.95, 13.95, 13.95, 13.95, 13.95, 24]
329    received_y = ir.fit_transform(x, y, sample_weight=sample_weight)
330
331    assert_array_equal(expected_y, received_y)
332
333
334def test_isotonic_regression_oob_raise():
335    # Set y and x
336    y = np.array([3, 7, 5, 9, 8, 7, 10])
337    x = np.arange(len(y))
338
339    # Create model and fit
340    ir = IsotonicRegression(increasing="auto", out_of_bounds="raise")
341    ir.fit(x, y)
342
343    # Check that an exception is thrown
344    msg = "in x_new is below the interpolation range"
345    with pytest.raises(ValueError, match=msg):
346        ir.predict([min(x) - 10, max(x) + 10])
347
348
349def test_isotonic_regression_oob_clip():
350    # Set y and x
351    y = np.array([3, 7, 5, 9, 8, 7, 10])
352    x = np.arange(len(y))
353
354    # Create model and fit
355    ir = IsotonicRegression(increasing="auto", out_of_bounds="clip")
356    ir.fit(x, y)
357
358    # Predict from  training and test x and check that min/max match.
359    y1 = ir.predict([min(x) - 10, max(x) + 10])
360    y2 = ir.predict(x)
361    assert max(y1) == max(y2)
362    assert min(y1) == min(y2)
363
364
365def test_isotonic_regression_oob_nan():
366    # Set y and x
367    y = np.array([3, 7, 5, 9, 8, 7, 10])
368    x = np.arange(len(y))
369
370    # Create model and fit
371    ir = IsotonicRegression(increasing="auto", out_of_bounds="nan")
372    ir.fit(x, y)
373
374    # Predict from  training and test x and check that we have two NaNs.
375    y1 = ir.predict([min(x) - 10, max(x) + 10])
376    assert sum(np.isnan(y1)) == 2
377
378
379def test_isotonic_regression_pickle():
380    y = np.array([3, 7, 5, 9, 8, 7, 10])
381    x = np.arange(len(y))
382
383    # Create model and fit
384    ir = IsotonicRegression(increasing="auto", out_of_bounds="clip")
385    ir.fit(x, y)
386
387    ir_ser = pickle.dumps(ir, pickle.HIGHEST_PROTOCOL)
388    ir2 = pickle.loads(ir_ser)
389    np.testing.assert_array_equal(ir.predict(x), ir2.predict(x))
390
391
392def test_isotonic_duplicate_min_entry():
393    x = [0, 0, 1]
394    y = [0, 0, 1]
395
396    ir = IsotonicRegression(increasing=True, out_of_bounds="clip")
397    ir.fit(x, y)
398    all_predictions_finite = np.all(np.isfinite(ir.predict(x)))
399    assert all_predictions_finite
400
401
402def test_isotonic_ymin_ymax():
403    # Test from @NelleV's issue:
404    # https://github.com/scikit-learn/scikit-learn/issues/6921
405    x = np.array(
406        [
407            1.263,
408            1.318,
409            -0.572,
410            0.307,
411            -0.707,
412            -0.176,
413            -1.599,
414            1.059,
415            1.396,
416            1.906,
417            0.210,
418            0.028,
419            -0.081,
420            0.444,
421            0.018,
422            -0.377,
423            -0.896,
424            -0.377,
425            -1.327,
426            0.180,
427        ]
428    )
429    y = isotonic_regression(x, y_min=0.0, y_max=0.1)
430
431    assert np.all(y >= 0)
432    assert np.all(y <= 0.1)
433
434    # Also test decreasing case since the logic there is different
435    y = isotonic_regression(x, y_min=0.0, y_max=0.1, increasing=False)
436
437    assert np.all(y >= 0)
438    assert np.all(y <= 0.1)
439
440    # Finally, test with only one bound
441    y = isotonic_regression(x, y_min=0.0, increasing=False)
442
443    assert np.all(y >= 0)
444
445
446def test_isotonic_zero_weight_loop():
447    # Test from @ogrisel's issue:
448    # https://github.com/scikit-learn/scikit-learn/issues/4297
449
450    # Get deterministic RNG with seed
451    rng = np.random.RandomState(42)
452
453    # Create regression and samples
454    regression = IsotonicRegression()
455    n_samples = 50
456    x = np.linspace(-3, 3, n_samples)
457    y = x + rng.uniform(size=n_samples)
458
459    # Get some random weights and zero out
460    w = rng.uniform(size=n_samples)
461    w[5:8] = 0
462    regression.fit(x, y, sample_weight=w)
463
464    # This will hang in failure case.
465    regression.fit(x, y, sample_weight=w)
466
467
468def test_fast_predict():
469    # test that the faster prediction change doesn't
470    # affect out-of-sample predictions:
471    # https://github.com/scikit-learn/scikit-learn/pull/6206
472    rng = np.random.RandomState(123)
473    n_samples = 10**3
474    # X values over the -10,10 range
475    X_train = 20.0 * rng.rand(n_samples) - 10
476    y_train = (
477        np.less(rng.rand(n_samples), expit(X_train)).astype("int64").astype("float64")
478    )
479
480    weights = rng.rand(n_samples)
481    # we also want to test that everything still works when some weights are 0
482    weights[rng.rand(n_samples) < 0.1] = 0
483
484    slow_model = IsotonicRegression(y_min=0, y_max=1, out_of_bounds="clip")
485    fast_model = IsotonicRegression(y_min=0, y_max=1, out_of_bounds="clip")
486
487    # Build interpolation function with ALL input data, not just the
488    # non-redundant subset. The following 2 lines are taken from the
489    # .fit() method, without removing unnecessary points
490    X_train_fit, y_train_fit = slow_model._build_y(
491        X_train, y_train, sample_weight=weights, trim_duplicates=False
492    )
493    slow_model._build_f(X_train_fit, y_train_fit)
494
495    # fit with just the necessary data
496    fast_model.fit(X_train, y_train, sample_weight=weights)
497
498    X_test = 20.0 * rng.rand(n_samples) - 10
499    y_pred_slow = slow_model.predict(X_test)
500    y_pred_fast = fast_model.predict(X_test)
501
502    assert_array_equal(y_pred_slow, y_pred_fast)
503
504
505def test_isotonic_copy_before_fit():
506    # https://github.com/scikit-learn/scikit-learn/issues/6628
507    ir = IsotonicRegression()
508    copy.copy(ir)
509
510
511@pytest.mark.parametrize("dtype", [np.int32, np.int64, np.float32, np.float64])
512def test_isotonic_dtype(dtype):
513    y = [2, 1, 4, 3, 5]
514    weights = np.array([0.9, 0.9, 0.9, 0.9, 0.9], dtype=np.float64)
515    reg = IsotonicRegression()
516
517    for sample_weight in (None, weights.astype(np.float32), weights):
518        y_np = np.array(y, dtype=dtype)
519        expected_dtype = check_array(
520            y_np, dtype=[np.float64, np.float32], ensure_2d=False
521        ).dtype
522
523        res = isotonic_regression(y_np, sample_weight=sample_weight)
524        assert res.dtype == expected_dtype
525
526        X = np.arange(len(y)).astype(dtype)
527        reg.fit(X, y_np, sample_weight=sample_weight)
528        res = reg.predict(X)
529        assert res.dtype == expected_dtype
530
531
532@pytest.mark.parametrize("y_dtype", [np.int32, np.int64, np.float32, np.float64])
533def test_isotonic_mismatched_dtype(y_dtype):
534    # regression test for #15004
535    # check that data are converted when X and y dtype differ
536    reg = IsotonicRegression()
537    y = np.array([2, 1, 4, 3, 5], dtype=y_dtype)
538    X = np.arange(len(y), dtype=np.float32)
539    reg.fit(X, y)
540    assert reg.predict(X).dtype == X.dtype
541
542
543def test_make_unique_dtype():
544    x_list = [2, 2, 2, 3, 5]
545    for dtype in (np.float32, np.float64):
546        x = np.array(x_list, dtype=dtype)
547        y = x.copy()
548        w = np.ones_like(x)
549        x, y, w = _make_unique(x, y, w)
550        assert_array_equal(x, [2, 3, 5])
551
552
553@pytest.mark.parametrize("dtype", [np.float64, np.float32])
554def test_make_unique_tolerance(dtype):
555    # Check that equality takes account of np.finfo tolerance
556    x = np.array([0, 1e-16, 1, 1 + 1e-14], dtype=dtype)
557    y = x.copy()
558    w = np.ones_like(x)
559    x, y, w = _make_unique(x, y, w)
560    if dtype == np.float64:
561        x_out = np.array([0, 1, 1 + 1e-14])
562    else:
563        x_out = np.array([0, 1])
564    assert_array_equal(x, x_out)
565
566
567def test_isotonic_make_unique_tolerance():
568    # Check that averaging of targets for duplicate X is done correctly,
569    # taking into account tolerance
570    X = np.array([0, 1, 1 + 1e-16, 2], dtype=np.float64)
571    y = np.array([0, 1, 2, 3], dtype=np.float64)
572    ireg = IsotonicRegression().fit(X, y)
573    y_pred = ireg.predict([0, 0.5, 1, 1.5, 2])
574
575    assert_array_equal(y_pred, np.array([0, 0.75, 1.5, 2.25, 3]))
576    assert_array_equal(ireg.X_thresholds_, np.array([0.0, 1.0, 2.0]))
577    assert_array_equal(ireg.y_thresholds_, np.array([0.0, 1.5, 3.0]))
578
579
580def test_isotonic_non_regression_inf_slope():
581    # Non-regression test to ensure that inf values are not returned
582    # see: https://github.com/scikit-learn/scikit-learn/issues/10903
583    X = np.array([0.0, 4.1e-320, 4.4e-314, 1.0])
584    y = np.array([0.42, 0.42, 0.44, 0.44])
585    ireg = IsotonicRegression().fit(X, y)
586    y_pred = ireg.predict(np.array([0, 2.1e-319, 5.4e-316, 1e-10]))
587    assert np.all(np.isfinite(y_pred))
588
589
590@pytest.mark.parametrize("increasing", [True, False])
591def test_isotonic_thresholds(increasing):
592    rng = np.random.RandomState(42)
593    n_samples = 30
594    X = rng.normal(size=n_samples)
595    y = rng.normal(size=n_samples)
596    ireg = IsotonicRegression(increasing=increasing).fit(X, y)
597    X_thresholds, y_thresholds = ireg.X_thresholds_, ireg.y_thresholds_
598    assert X_thresholds.shape == y_thresholds.shape
599
600    # Input thresholds are a strict subset of the training set (unless
601    # the data is already strictly monotonic which is not the case with
602    # this random data)
603    assert X_thresholds.shape[0] < X.shape[0]
604    assert np.isin(X_thresholds, X).all()
605
606    # Output thresholds lie in the range of the training set:
607    assert y_thresholds.max() <= y.max()
608    assert y_thresholds.min() >= y.min()
609
610    assert all(np.diff(X_thresholds) > 0)
611    if increasing:
612        assert all(np.diff(y_thresholds) >= 0)
613    else:
614        assert all(np.diff(y_thresholds) <= 0)
615
616
617def test_input_shape_validation():
618    # Test from #15012
619    # Check that IsotonicRegression can handle 2darray with only 1 feature
620    X = np.arange(10)
621    X_2d = X.reshape(-1, 1)
622    y = np.arange(10)
623
624    iso_reg = IsotonicRegression().fit(X, y)
625    iso_reg_2d = IsotonicRegression().fit(X_2d, y)
626
627    assert iso_reg.X_max_ == iso_reg_2d.X_max_
628    assert iso_reg.X_min_ == iso_reg_2d.X_min_
629    assert iso_reg.y_max == iso_reg_2d.y_max
630    assert iso_reg.y_min == iso_reg_2d.y_min
631    assert_array_equal(iso_reg.X_thresholds_, iso_reg_2d.X_thresholds_)
632    assert_array_equal(iso_reg.y_thresholds_, iso_reg_2d.y_thresholds_)
633
634    y_pred1 = iso_reg.predict(X)
635    y_pred2 = iso_reg_2d.predict(X_2d)
636    assert_allclose(y_pred1, y_pred2)
637
638
639def test_isotonic_2darray_more_than_1_feature():
640    # Ensure IsotonicRegression raises error if input has more than 1 feature
641    X = np.arange(10)
642    X_2d = np.c_[X, X]
643    y = np.arange(10)
644
645    msg = "should be a 1d array or 2d array with 1 feature"
646    with pytest.raises(ValueError, match=msg):
647        IsotonicRegression().fit(X_2d, y)
648
649    iso_reg = IsotonicRegression().fit(X, y)
650    with pytest.raises(ValueError, match=msg):
651        iso_reg.predict(X_2d)
652
653    with pytest.raises(ValueError, match=msg):
654        iso_reg.transform(X_2d)
655
656
657def test_isotonic_regression_sample_weight_not_overwritten():
658    """Check that calling fitting function of isotonic regression will not
659    overwrite `sample_weight`.
660    Non-regression test for:
661    https://github.com/scikit-learn/scikit-learn/issues/20508
662    """
663    X, y = make_regression(n_samples=10, n_features=1, random_state=41)
664    sample_weight_original = np.ones_like(y)
665    sample_weight_original[0] = 10
666    sample_weight_fit = sample_weight_original.copy()
667
668    isotonic_regression(y, sample_weight=sample_weight_fit)
669    assert_allclose(sample_weight_fit, sample_weight_original)
670
671    IsotonicRegression().fit(X, y, sample_weight=sample_weight_fit)
672    assert_allclose(sample_weight_fit, sample_weight_original)
673
674
675@pytest.mark.parametrize("shape", ["1d", "2d"])
676def test_get_feature_names_out(shape):
677    """Check `get_feature_names_out` for `IsotonicRegression`."""
678    X = np.arange(10)
679    if shape == "2d":
680        X = X.reshape(-1, 1)
681    y = np.arange(10)
682
683    iso = IsotonicRegression().fit(X, y)
684    names = iso.get_feature_names_out()
685    assert isinstance(names, np.ndarray)
686    assert names.dtype == object
687    assert_array_equal(["isotonicregression0"], names)
688
689
690def test_isotonic_regression_output_predict():
691    """Check that `predict` does return the expected output type.
692
693    We need to check that `transform` will output a DataFrame and a NumPy array
694    when we set `transform_output` to `pandas`.
695
696    Non-regression test for:
697    https://github.com/scikit-learn/scikit-learn/issues/25499
698    """
699    pd = pytest.importorskip("pandas")
700    X, y = make_regression(n_samples=10, n_features=1, random_state=42)
701    regressor = IsotonicRegression()
702    with sklearn.config_context(transform_output="pandas"):
703        regressor.fit(X, y)
704        X_trans = regressor.transform(X)
705        y_pred = regressor.predict(X)
706
707    assert isinstance(X_trans, pd.DataFrame)
708    assert isinstance(y_pred, np.ndarray)
709 
Aluode/PerceptionLabPortable · CoolFace