From a66b0e64c14413cb0b12f697d6c365482af5eeba Mon Sep 17 00:00:00 2001 From: Michael J Bommarito II Date: Wed, 22 Jun 2016 20:22:17 -0400 Subject: [PATCH 1/4] Adding test case from #6921 --- sklearn/tests/test_isotonic.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/sklearn/tests/test_isotonic.py b/sklearn/tests/test_isotonic.py index 36c570551e196..cfcc99795265d 100644 --- a/sklearn/tests/test_isotonic.py +++ b/sklearn/tests/test_isotonic.py @@ -338,6 +338,17 @@ def test_isotonic_duplicate_min_entry(): assert_true(all_predictions_finite) +def test_isotonic_ymin_ymax(): + # Test case as reported in Issue #6921 + x = np.array([1.26336413, 1.31853693, -0.57200917, 0.3072928, -0.70686507, + -0.17614937, -1.59943059, 1.05908504, 1.3958263, 1.90580318, + 0.20992272, 0.02836316, -0.08092235, 0.44438247, 0.01791253, + -0.3771914, -0.89577538, -0.37726249, -1.32687569, 0.18013201]) + y = isotonic_regression(x, y_min=0, y_max=0.1) + + assert(np.all(y > 0)) + assert(np.all(y < 0.1)) + def test_isotonic_zero_weight_loop(): # Test from @ogrisel's issue: # https://github.com/scikit-learn/scikit-learn/issues/4297 From 9bb7a4bc3fd267ac6b7e849b44016a71c0bb623f Mon Sep 17 00:00:00 2001 From: Michael J Bommarito II Date: Wed, 22 Jun 2016 20:50:53 -0400 Subject: [PATCH 2/4] Fixing test case to accept weak inequality --- sklearn/tests/test_isotonic.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sklearn/tests/test_isotonic.py b/sklearn/tests/test_isotonic.py index cfcc99795265d..66d4c7b6c8709 100644 --- a/sklearn/tests/test_isotonic.py +++ b/sklearn/tests/test_isotonic.py @@ -346,8 +346,8 @@ def test_isotonic_ymin_ymax(): -0.3771914, -0.89577538, -0.37726249, -1.32687569, 0.18013201]) y = isotonic_regression(x, y_min=0, y_max=0.1) - assert(np.all(y > 0)) - assert(np.all(y < 0.1)) + assert(np.all(y >= 0)) + assert(np.all(y <= 0.1)) def test_isotonic_zero_weight_loop(): # Test from @ogrisel's issue: From 29b06560e52198820264e6a3304840ae87db0796 Mon Sep 17 00:00:00 2001 From: Michael J Bommarito II Date: Wed, 22 Jun 2016 20:51:21 -0400 Subject: [PATCH 3/4] Fix for non-pre-sorted data with y_min/y_max in isotonic_regression re: issue #6921 --- sklearn/isotonic.py | 25 +++++++++++++++++-------- 1 file changed, 17 insertions(+), 8 deletions(-) diff --git a/sklearn/isotonic.py b/sklearn/isotonic.py index ad6800914074a..85164c8a6170d 100644 --- a/sklearn/isotonic.py +++ b/sklearn/isotonic.py @@ -77,7 +77,7 @@ def check_increasing(x, y): def isotonic_regression(y, sample_weight=None, y_min=None, y_max=None, - increasing=True): + increasing=True, pre_sorted=True): """Solve the isotonic regression model:: min sum w[i] (y[i] - y_[i]) ** 2 @@ -110,6 +110,9 @@ def isotonic_regression(y, sample_weight=None, y_min=None, y_max=None, Whether to compute ``y_`` is increasing (if set to True) or decreasing (if set to False) + pre_sorted : boolean, optional, default: True + Whether the input `y` is pre-sorted, e.g., from within a model class. + Returns ------- y_ : list of floating-point values @@ -129,17 +132,23 @@ def isotonic_regression(y, sample_weight=None, y_min=None, y_max=None, y = y[::-1] sample_weight = sample_weight[::-1] + # Ensure that sample is sorted if not pre_sort + if not pre_sorted: + _y_sort_index = np.argsort(y) + y = np.copy(y[_y_sort_index]) + sample_weight = np.copy(sample_weight[_y_sort_index]) + if y_min is not None or y_max is not None: - y = np.copy(y) - sample_weight = np.copy(sample_weight) + # Only create a copy if pre-sorted + if pre_sorted: + y = np.copy(y) + sample_weight = np.copy(sample_weight) + # upper bound on the cost function - C = np.dot(sample_weight, y * y) * 10 if y_min is not None: - y[0] = y_min - sample_weight[0] = C + y[y < y_min] = y_min if y_max is not None: - y[-1] = y_max - sample_weight[-1] = C + y[y > y_max] = y_max solution = np.empty(len(y)) y_ = _isotonic_regression(y, sample_weight, solution) From bef4f65073e3422846c5749afd51e03c19d17793 Mon Sep 17 00:00:00 2001 From: Michael J Bommarito II Date: Wed, 22 Jun 2016 20:57:47 -0400 Subject: [PATCH 4/4] Cosmit --- sklearn/tests/test_isotonic.py | 1 + 1 file changed, 1 insertion(+) diff --git a/sklearn/tests/test_isotonic.py b/sklearn/tests/test_isotonic.py index 66d4c7b6c8709..49ec872b4be06 100644 --- a/sklearn/tests/test_isotonic.py +++ b/sklearn/tests/test_isotonic.py @@ -349,6 +349,7 @@ def test_isotonic_ymin_ymax(): assert(np.all(y >= 0)) assert(np.all(y <= 0.1)) + def test_isotonic_zero_weight_loop(): # Test from @ogrisel's issue: # https://github.com/scikit-learn/scikit-learn/issues/4297