|
29 | 29 | from sklearn.linear_model._glm import _GeneralizedLinearRegressor |
30 | 30 | from sklearn.linear_model._linear_loss import LinearModelLoss |
31 | 31 | from sklearn.exceptions import ConvergenceWarning |
32 | | -from sklearn.metrics import d2_tweedie_score |
| 32 | +from sklearn.metrics import d2_tweedie_score, mean_poisson_deviance |
33 | 33 | from sklearn.model_selection import train_test_split |
34 | 34 |
|
35 | 35 |
|
@@ -1017,19 +1017,33 @@ def test_family_deprecation(est, family): |
1017 | 1017 | def test_linalg_warning_with_newton_solver(global_random_seed): |
1018 | 1018 | rng = np.random.RandomState(global_random_seed) |
1019 | 1019 | X_orig = rng.normal(size=(10, 3)) |
1020 | | - X_colinear = np.hstack([X_orig] * 10) # collinear design |
| 1020 | + X_collinear = np.hstack([X_orig] * 10) # collinear design |
1021 | 1021 | y = rng.normal(size=X_orig.shape[0]) |
1022 | 1022 | y[y < 0] = 0.0 |
1023 | 1023 |
|
| 1024 | + # No warning raised on well-conditioned design, even without regularization. |
1024 | 1025 | with warnings.catch_warnings(): |
1025 | 1026 | warnings.simplefilter("error") |
1026 | | - # No warning raised on well-conditioned design |
1027 | | - PoissonRegressor(solver="newton-cholesky", alpha=0.0).fit(X_orig, y) |
| 1027 | + reg = PoissonRegressor(solver="newton-cholesky", alpha=0.0).fit(X_orig, y) |
| 1028 | + reference_deviance = mean_poisson_deviance(y, reg.predict(X_orig)) |
1028 | 1029 |
|
| 1030 | + # Fitting on collinear data without regularization should raise an |
| 1031 | + # informative warning: |
1029 | 1032 | msg = ( |
1030 | 1033 | "The inner solver of CholeskyNewtonSolver stumbled upon a" |
1031 | | - " singular or very ill-conditioned hessian matrix. It will now try" |
1032 | | - " a simple gradient step." |
| 1034 | + " singular or very ill-conditioned hessian matrix" |
1033 | 1035 | ) |
1034 | 1036 | with pytest.warns(scipy.linalg.LinAlgWarning, match=msg): |
1035 | | - PoissonRegressor(solver="newton-cholesky", alpha=0.0).fit(X_colinear, y) |
| 1037 | + PoissonRegressor(solver="newton-cholesky", alpha=0.0).fit(X_collinear, y) |
| 1038 | + |
| 1039 | + msg = "Newton solver did not converge after.*iterations." |
| 1040 | + with pytest.warns(ConvergenceWarning, match=msg): |
| 1041 | + PoissonRegressor(solver="newton-cholesky", alpha=0.0).fit(X_collinear, y) |
| 1042 | + |
| 1043 | + # Increasing the regularization slightly should make the problem go away: |
| 1044 | + reg = PoissonRegressor(solver="newton-cholesky", alpha=1e-12).fit(X_collinear, y) |
| 1045 | + |
| 1046 | + # Since we use a small penalty, the deviance of the predictions should still |
| 1047 | + # be almost the same. |
| 1048 | + this_deviance = mean_poisson_deviance(y, reg.predict(X_collinear)) |
| 1049 | + assert this_deviance == pytest.approx(reference_deviance) |
0 commit comments