Skip to content

TST suppress convergence warnings in coordinate descent #20144

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 10 commits into from
Jun 6, 2024

Conversation

norbusan
Copy link
Member

@norbusan norbusan commented May 27, 2021

Reference Issues/PRs

closes #4780

What does this implement/fix? Explain your changes.

These warnings have been fixed by either increasing the number of
iterations of fitting, or by suppressing the warnings with pytest.warns

For parametrized tests a check is done so that only the failing tests
get the pytest.warns context manager, all other get a dummy context
manager that doesn't do anything.

Any other comments?

There is one instance where the warning does not disappear in
test_linear_model_sample_weights_normalize_in_pipeline
(second context manager call), but I don't know why ...

These warnings have been fixed by either increasing the number of
iterations of fitting, or by suppressing the warnings with pytest.warns

For parametrized tests a check is done so that only the failing tests
get the pytest.warns context manager, all other get a dummy context
manager that doesn't do anything.

There is one instance where the warning does not disappear in
   test_linear_model_sample_weights_normalize_in_pipeline
(second context manager call), but I don't know why ...
@glemaitre glemaitre changed the title Fix coordinate descent convergence warnings (Fixes #4780) TST suppress convergence warnings in coordinate descent May 27, 2021
@norbusan
Copy link
Member Author

I just saw that other tests use the following style to suppress warnings:

with ignore_warnings(category=ConvergenceWarning):

Is there a preference for the one or the other?

norbusan added 3 commits May 27, 2021 18:38
- use ignore_warnings instead of pytest.warns since depending on
  the used Python system the warning might not be issued
- deal with multiple warnings in a single statement
- use nullcontext() instead of suppress() since we have moved to
  Python 3.7 as dependency and CI testing system
Copy link
Member

@glemaitre glemaitre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think that sometimes, we could use pytest.mark.filterwarning instead of ignore_warning.

@@ -724,14 +780,18 @@ def test_uniform_targets():
for model in models_single_task:
for y_values in (0, 5):
y1.fill(y_values)
assert_array_equal(model.fit(X_train, y1).predict(X_test), y1)
with ignore_warnings(category=ConvergenceWarning):
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we ignore the warning all the time, we could decorate the test function as well.

@@ -111,7 +113,10 @@ def test_lasso_zero():
# Check that the lasso can handle zero data without crashing
X = [[0], [0], [0]]
y = [0, 0, 0]
clf = Lasso(alpha=0.1).fit(X, y)
# _cd_fast.pyx tests for gap < tol, but here we get 0.0 < 0.0
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actually I do not understand why it would be the case in this test. By default the tolerance is 1e-4:

>>> from sklearn.linear_model import Lasso
>>> Lasso().tol
0.0001

This test does not override the default. The same is true for MultiTaskLasso.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah ok I understand, this is because we rescale the tolerance by a data dependent quantity which is 0 in this case.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is indeed sub-optimal - y == 0 are valid options. What about the following change to keep tol as is if it would become 0 (similar code for all the different coordinate descent function instances):

--- a/sklearn/linear_model/_cd_fast.pyx
+++ b/sklearn/linear_model/_cd_fast.pyx
@@ -672,6 +672,7 @@ def enet_coordinate_descent_multi_task(
     cdef floating W_ii_abs_max
     cdef floating gap = tol + 1.0
     cdef floating d_w_tol = tol
+    cdef floating temp_tol = tol
     cdef floating R_norm
     cdef floating w_norm
     cdef floating ry_sum
@@ -704,7 +705,9 @@ def enet_coordinate_descent_multi_task(
                           &R[0, jj], 1)
 
         # tol = tol * linalg.norm(Y, ord='fro') ** 2
-        tol = tol * _nrm2(n_samples * n_tasks, Y_ptr, 1) ** 2
+        temp_tol = tol * _nrm2(n_samples * n_tasks, Y_ptr, 1) ** 2
+        if temp_tol > 0:
+            tol = temp_tol
 
         for n_iter in range(max_iter):
             w_max = 0.0
@@ -819,7 +822,7 @@ def enet_coordinate_descent_multi_task(
                 gap += l1_reg * l21_norm - const * ry_sum + \
                      0.5 * l2_reg * (1 + const ** 2) * (w_norm ** 2)
 
-                if gap <= tol:
+                if gap < tol:
                     # return if we reached desired tolerance
                     break
         else:

Then we could also return to the previous (gap < tol).

@github-actions github-actions bot added the cython label Jun 1, 2021
@cmarmo
Copy link
Contributor

cmarmo commented Sep 9, 2022

Hi @norbusan, thank you for your work so far! Are you still interested in finalizing this pull request? The list of the tests with convergence issues slightly changed.

@adrinjalali
Copy link
Member

I gave this a fresh start @ogrisel @glemaitre . Had to remove the MultiTaskLasso test case for convergence warning since I couldn't create a warning with this PR.

Copy link

✔️ Linting Passed

All linting checks passed. Your pull request is in excellent shape! ☀️

Generated for commit: 334138a. Link to the linter CI: here

Copy link
Member

@glemaitre glemaitre left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@adrinjalali adrinjalali merged commit d36039a into scikit-learn:main Jun 6, 2024
30 checks passed
@jeremiedbb jeremiedbb mentioned this pull request Jul 2, 2024
11 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Coordinate descent convergence warnings
5 participants