From d33d4103d7f0db18c2e32d746bd39c4af8a3b112 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Tue, 21 May 2019 09:47:02 +0200 Subject: [PATCH 1/6] add test to check that all ridge solver give the same results --- sklearn/linear_model/tests/test_ridge.py | 33 ++++++++++++++++++++++++ 1 file changed, 33 insertions(+) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index e795351bfa329..b110bf4284aac 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -393,6 +393,39 @@ def _make_sparse_offset_regression( return X, y +@pytest.mark.parametrize( + 'solver', ['svd', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv']) +@pytest.mark.parametrize( + 'n_samples,dtype,p', + [(20, 'float32', .1), (40, 'float32', 1.), (20, 'float64', .2)]) +@pytest.mark.parametrize('sparse_X', [True, False]) +@pytest.mark.parametrize('seed', np.arange(3)) +def test_solver_consistency(solver, p, n_samples, dtype, sparse_X, seed): + accept_sparse = ['sparse_cg', 'ridgecv'] + if sparse_X and solver not in accept_sparse: + pytest.skip() + alpha = 1. + noise = 50. if p > .9 else 500. + X, y = _make_sparse_offset_regression( + bias=10, n_features=30, proportion_nonzero=p, noise=noise, + random_state=seed, n_samples=n_samples) + cholesky_ridge = Ridge( + solver='cholesky', normalize=True, alpha=alpha).fit(X, y) + X = X.astype(dtype) + y = y.astype(dtype) + if sparse_X: + X = sp.csr_matrix(X) + if solver == 'ridgecv': + ridge = RidgeCV(alphas=[alpha], normalize=True) + else: + ridge = Ridge(solver=solver, tol=1e-10, normalize=True, alpha=alpha) + ridge.fit(X, y) + assert_allclose( + ridge.coef_, cholesky_ridge.coef_, atol=1e-3, rtol=1e-3) + assert_allclose( + ridge.intercept_, cholesky_ridge.intercept_, atol=1e-3, rtol=1e-3) + + @pytest.mark.parametrize('gcv_mode', ['svd', 'eigen']) @pytest.mark.parametrize('X_constructor', [np.asarray, sp.csr_matrix]) @pytest.mark.parametrize('X_shape', [(11, 8), (11, 20)]) From 294db9974aa20233864e77ba7e22465df50c6461 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Tue, 28 May 2019 21:45:37 +0200 Subject: [PATCH 2/6] p -> proportion_nonzero --- sklearn/linear_model/tests/test_ridge.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index 9c844413bd7c9..45711124202ad 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -396,19 +396,20 @@ def _make_sparse_offset_regression( @pytest.mark.parametrize( 'solver', ['svd', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv']) @pytest.mark.parametrize( - 'n_samples,dtype,p', + 'n_samples,dtype,proportion_nonzero', [(20, 'float32', .1), (40, 'float32', 1.), (20, 'float64', .2)]) @pytest.mark.parametrize('sparse_X', [True, False]) @pytest.mark.parametrize('seed', np.arange(3)) -def test_solver_consistency(solver, p, n_samples, dtype, sparse_X, seed): +def test_solver_consistency( + solver, proportion_nonzero, n_samples, dtype, sparse_X, seed): accept_sparse = ['sparse_cg', 'ridgecv'] if sparse_X and solver not in accept_sparse: pytest.skip() alpha = 1. - noise = 50. if p > .9 else 500. + noise = 50. if proportion_nonzero > .9 else 500. X, y = _make_sparse_offset_regression( - bias=10, n_features=30, proportion_nonzero=p, noise=noise, - random_state=seed, n_samples=n_samples) + bias=10, n_features=30, proportion_nonzero=proportion_nonzero, + noise=noise, random_state=seed, n_samples=n_samples) cholesky_ridge = Ridge( solver='cholesky', normalize=True, alpha=alpha).fit(X, y) X = X.astype(dtype) From 3f308ba342ba9fb9a767408985f5d5d398947987 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Tue, 28 May 2019 22:32:04 +0200 Subject: [PATCH 3/6] use svd solver as reference Ridge docstring says it is more stable than cholesky --- sklearn/linear_model/tests/test_ridge.py | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index 45711124202ad..918314b192e9b 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -394,12 +394,12 @@ def _make_sparse_offset_regression( @pytest.mark.parametrize( - 'solver', ['svd', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv']) + 'solver', ['cholesky', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv']) @pytest.mark.parametrize( 'n_samples,dtype,proportion_nonzero', [(20, 'float32', .1), (40, 'float32', 1.), (20, 'float64', .2)]) @pytest.mark.parametrize('sparse_X', [True, False]) -@pytest.mark.parametrize('seed', np.arange(3)) +@pytest.mark.parametrize('seed', np.arange(300)) def test_solver_consistency( solver, proportion_nonzero, n_samples, dtype, sparse_X, seed): accept_sparse = ['sparse_cg', 'ridgecv'] @@ -410,8 +410,8 @@ def test_solver_consistency( X, y = _make_sparse_offset_regression( bias=10, n_features=30, proportion_nonzero=proportion_nonzero, noise=noise, random_state=seed, n_samples=n_samples) - cholesky_ridge = Ridge( - solver='cholesky', normalize=True, alpha=alpha).fit(X, y) + svd_ridge = Ridge( + solver='svd', normalize=True, alpha=alpha).fit(X, y) X = X.astype(dtype) y = y.astype(dtype) if sparse_X: @@ -422,9 +422,9 @@ def test_solver_consistency( ridge = Ridge(solver=solver, tol=1e-10, normalize=True, alpha=alpha) ridge.fit(X, y) assert_allclose( - ridge.coef_, cholesky_ridge.coef_, atol=1e-3, rtol=1e-3) + ridge.coef_, svd_ridge.coef_, atol=1e-3, rtol=1e-3) assert_allclose( - ridge.intercept_, cholesky_ridge.intercept_, atol=1e-3, rtol=1e-3) + ridge.intercept_, svd_ridge.intercept_, atol=1e-3, rtol=1e-3) @pytest.mark.parametrize('gcv_mode', ['svd', 'eigen']) From af88bcc8900e66f147757dfce809ca93c9f20fe8 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Mon, 10 Jun 2019 09:17:17 +0200 Subject: [PATCH 4/6] reduce number of seeds in ridge test --- sklearn/linear_model/tests/test_ridge.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index 918314b192e9b..56c0e78f6c2ce 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -399,7 +399,7 @@ def _make_sparse_offset_regression( 'n_samples,dtype,proportion_nonzero', [(20, 'float32', .1), (40, 'float32', 1.), (20, 'float64', .2)]) @pytest.mark.parametrize('sparse_X', [True, False]) -@pytest.mark.parametrize('seed', np.arange(300)) +@pytest.mark.parametrize('seed', np.arange(3)) def test_solver_consistency( solver, proportion_nonzero, n_samples, dtype, sparse_X, seed): accept_sparse = ['sparse_cg', 'ridgecv'] From 0f08cbcb4bb78e61b4978362c77b13a05cbff8b2 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Tue, 11 Jun 2019 11:39:42 +0200 Subject: [PATCH 5/6] avoid unnecessary copies in test --- sklearn/linear_model/tests/test_ridge.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index 56c0e78f6c2ce..1146879c0f009 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -412,8 +412,8 @@ def test_solver_consistency( noise=noise, random_state=seed, n_samples=n_samples) svd_ridge = Ridge( solver='svd', normalize=True, alpha=alpha).fit(X, y) - X = X.astype(dtype) - y = y.astype(dtype) + X = X.astype(dtype, copy=False) + y = y.astype(dtype, copy=False) if sparse_X: X = sp.csr_matrix(X) if solver == 'ridgecv': From 762fe5d8c50d3644c741e4926c37a3a2a65988b4 Mon Sep 17 00:00:00 2001 From: Jerome Dockes Date: Tue, 11 Jun 2019 11:46:20 +0200 Subject: [PATCH 6/6] avoid skipping tests --- sklearn/linear_model/tests/test_ridge.py | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/sklearn/linear_model/tests/test_ridge.py b/sklearn/linear_model/tests/test_ridge.py index 1146879c0f009..10e7871a3fe00 100644 --- a/sklearn/linear_model/tests/test_ridge.py +++ b/sklearn/linear_model/tests/test_ridge.py @@ -394,17 +394,18 @@ def _make_sparse_offset_regression( @pytest.mark.parametrize( - 'solver', ['cholesky', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv']) + 'solver, sparse_X', + ((solver, sparse_X) for + (solver, sparse_X) in product( + ['cholesky', 'sag', 'sparse_cg', 'lsqr', 'saga', 'ridgecv'], + [False, True]) + if not (sparse_X and solver not in ['sparse_cg', 'ridgecv']))) @pytest.mark.parametrize( 'n_samples,dtype,proportion_nonzero', [(20, 'float32', .1), (40, 'float32', 1.), (20, 'float64', .2)]) -@pytest.mark.parametrize('sparse_X', [True, False]) @pytest.mark.parametrize('seed', np.arange(3)) def test_solver_consistency( solver, proportion_nonzero, n_samples, dtype, sparse_X, seed): - accept_sparse = ['sparse_cg', 'ridgecv'] - if sparse_X and solver not in accept_sparse: - pytest.skip() alpha = 1. noise = 50. if proportion_nonzero > .9 else 500. X, y = _make_sparse_offset_regression(