8000 [MRG + 1] ElasticNetCV: raise ValueError if l1_ratio=0 by erikcs · Pull Request #7591 · scikit-learn/scikit-learn · GitHub
[go: up one dir, main page]

Skip to content

[MRG + 1] ElasticNetCV: raise ValueError if l1_ratio=0 #7591

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 13 commits into from
Oct 25, 2016
Merged

[MRG + 1] ElasticNetCV: raise ValueError if l1_ratio=0 #7591

merged 13 commits into from
Oct 25, 2016

Conversation

erikcs
Copy link
Contributor
@erikcs erikcs commented Oct 6, 2016

Reference Issue

Fixes #7551

What does this implement/fix? Explain your changes.

Before,

import numpy as np
from sklearn.linear_model import ElasticNetCV
X = np.array([[1, 2, 4, 5, 8], [3, 5, 7, 7, 8]]).T
y = np.array([12, 10, 11, 21, 5])

est = ElasticNetCV(l1_ratio=0).fit(X, y)

gives the runtime error UnboundLocalError: local variable 'best_l1_ratio' referenced before assignment

Now it returns ValueError: l1_ratio = 0 not supported

@agramfort
Copy link
Member

please add a test

@erikcs
Copy link
Contributor Author
erikcs commented Oct 7, 2016

Added a test to make sure ValueError is raised. Sorry about that.

@lesteve
Copy link
Member
lesteve commented Oct 7, 2016

Hmmm I am wondering whether this is the right fix. If you look at the ElasticNetCV docstring, it seems to indicate that l1_ratio = 0 is supported:

For l1_ratio = 0 the penalty is an L2 penalty.

Maybe you need to understand why you end up with the error UnboundLocalError: local variable 'best_l1_ratio' referenced before assignment.

Tip: you can add syntax-highlighting to your snippet by adding py after the first three initial backquotes (I edited your message with this change).

@erikcs
Copy link
Contributor Author
erikcs commented Oct 7, 2016

Yes, this is just a quick fix to disallow l1_ratio1=0 (and avoid the confusing error) as suggested by agramfort and amueller in issue #7551 (where I explain why the UnboundLocalError error is raised) (Thanks for the tip)

@lesteve
Copy link
Member
lesteve commented Oct 7, 2016

Yes, this is just a quick fix to disallow l1_ratio1=0 (and avoid the confusing error) as suggested by agramfort and amueller in issue #7551

My bad I missed the associated issue somehow, maybe you want to update the docstring accordingly then.

@@ -1063,6 +1063,8 @@ def fit(self, X, y):

if hasattr(self, 'l1_ratio'):
model_str = 'ElasticNet'
if self.l1_ratio == 0:
raise ValueError("l1_ratio = 0 not supported")
Copy link
Member

Choose a reason for hiding this comment

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

Maybe you could add a mention about L2 penalty and RidgeCV like you did in the docstring?

Just curious what happens if l1_ratio is a list which contains 0?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

Sorry, that was sloppy of me. If 0 was contained in the list, the code would have run without an error, but the mse_path_ on the estimator for that value, would all be nans. I.e. a user would think the ridge estimate was evaluated, when it was in fact not. I updated the error message.

clf = ElasticNetCV(l1_ratio=0)
clfl = ElasticNetCV(l1_ratio=[0, 0.5])
clfm = MultiTaskElasticNetCV(l1_ratio=0)
assert_raises(ValueError, clf.fit, X, y)
Copy link
Member

Choose a reason for hiding this comment

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

Can you use assert_raise_message to check the error message? Apart from that LGTM.

@amueller
Copy link
Member
amueller commented Oct 7, 2016

LGTM

@amueller amueller changed the title [MRG] ElasticNetCV: raise ValueError if l1_ratio=0 [MRG + 1] ElasticNetCV: raise ValueError if l1_ratio=0 Oct 7, 2016
@agramfort
Copy link
Member

solver should work but it's auto mode for alpha grid that breaks

@jnothman
Copy link
Member

@agramfort To confirm, you consider this the wrong fix?

@amueller
Copy link
Member

I'm confused.

@@ -712,3 +712,13 @@ def test_enet_float_precision():
assert_array_almost_equal(intercept[np.float32],
intercept[np.float64],
decimal=4)

def test_enet_l1_ratio():
Copy link
Member

Choose a reason for hiding this comment

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

too much indented

@agramfort
Copy link
Member

Estimator would work with l1_ratio=0. if use passes his own grid of alphas. The solver would manage. It's just the automatic alpha grid that breaks.

fix is good enough but maybe I would throw the error if alphas are not passed explicitly.

clear?

@erikcs
Copy link
Contributor Author
erikcs commented Oct 15, 2016

Sorry for any confusion, I thought I made it clear in #7551 that it is the grid generation in _alpha_grid that fails. Is there anything I else I should do here?

@agramfort
Copy link
Member
agramfort commented Oct 15, 2016

can you just make the grid generation fail. It should only be called if alphas=None

@erikcs
Copy link
Contributor Author
erikcs commented Oct 15, 2016

Ok, to be sure: revert everything in this commit, and just raise a ValueError if _alpha_grid is called with l1_ratio=0? It is currently only called if alphas=None. Should I update the docstring and add a test? Is the correct procedure for me to $git delete elnet-l1ratio, create a new branch with the same name, $git branch elnet-l1-ratio, then push to it? Or do I $git reset this branch? Thanks

@agramfort
Copy link
Member

Yes correct. Make sure error message is as explicit as possible 

On Sat, Oct 15, 2016 at 3:17 PM +0200, "nuffe" notifications@github.com wrote:

Ok, to be sure: revert everything in this commit, and just raise a ValueError if _alpha_grid is called with l1_ratio=0? It is currently only called if alphas=None. Should I update the docstring and add a test?


You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub, or mute the thread.

assert_raise_message(ValueError, msg,
ElasticNetCV(l1_ratio=0).fit, X, y)
assert_raise_message(ValueError, msg,
MultiTaskElasticNetCV(l1_ratio=0).fit, X, X)
Copy link
Member

Choose a reason for hiding this comment

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

test that is works with you pass some alphas

Copy link
Contributor Author

Choose a reason for hiding this comment

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

I am sorry for a possible stupid question, but this commit broke an unrelated test (Logistic regression) on AppVeyor:

======================================================================
FAIL: sklearn.linear_model.tests.test_logistic.test_logistic_regression_sample_weights
----------------------------------------------------------------------
Traceback (most recent call last):
  File "C:\Python27\lib\site-packages\nose\case.py", line 197, in runTest
    self.test(*self.arg)
  File "C:\Python27\lib\site-packages\sklearn\linear_model\tests\test_logistic.py", line 638, in test_logistic_regression_sample_weights
    assert_array_almost_equal(clf_cw.coef_, clf_sw.coef_, decimal=4)
  File "C:\Python27\lib\site-packages\numpy\testing\utils.py", line 842, in assert_array_almost_equal
    precision=decimal)
  File "C:\Python27\lib\site-packages\numpy\testing\utils.py", line 665, in assert_array_compare
    raise AssertionError(msg)
AssertionError: 
Arrays are not almost equal to 4 decimals
(mismatch 20.0%)
 x: array([[ 2.5404,  0.    ,  0.    , -0.3094, -0.4925]])
 y: array([[ 2.5405,  0.    ,  0.    , -0.3094, -0.4924]])
sklearn.decomposition.tests.test_dict_learning.test_dict_learning_reconstruction_parallel: 4.1117s

but the same tests pass on my computer and on Travis, how do I proceed here?

@agramfort
Copy link
Member

please another commit to restart appveyor. Just to see if bug is reproducible

@erikcs
Copy link
Contributor Author
erikcs commented Oct 17, 2016

It is still sklearn.linear_model.tests.test_logistic.test_logistic_regression_sample_weights that fails. Conceptually it should be impossible for the addition of test A to cause unit test B to fail?(commit 5171932 does not mutate any external state, and the test passes on Travis)

est = MultiTaskElasticNetCV(l1_ratio=0, alphas=alphas)
with ignore_warnings():
est.fit(X, X)
est_desired.fit(X, X)
Copy link
Member

Choose a reason for hiding this comment

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

calling fit(X, X) is weird. How about fit(X, y[:, None]) ?

@amueller
Copy link
Member

The failure means that we're unclean on fixing random states somewhere, I think. And windows can give numerically different results.

est.fit(X, y)
assert_array_almost_equal(est.coef_, est_desired.coef_, decimal=5)

est_desired = MultiTaskElasticNetCV(l1_ratio=0.00001, alphas=alphas)
Copy link
Member

Choose a reason for hiding this comment

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

set the random state explicitly

@amueller
Copy link
Member

Ideally we would explicitly pass random states everywhere in all tests. To fix the test failure, maybe fix the random states in the test that's failing. You can also add it in the test that you added.

@erikcs
Copy link
Contributor Author
erikcs commented Oct 24, 2016

Ah, thank you. Wouldn't it be easier to set the random state in every single estimator to something else than None by default, instead of changing every test?

@amueller
Copy link
Member

That would drastically change user code. We have our estimators be non-deterministic by default, which is a design choice. Changing that would be quite a severe change in API. It also requires us to be very explicit about randomness in our tests, which is A Good Thing (TM)

@agramfort agramfort merged commit 0dfc9a5 into scikit-learn:master Oct 25, 2016
@agramfort
Copy link
Member

thx @Nuffe

@erikcs erikcs deleted the elnet-l1ratio branch October 25, 2016 08:16
@GaelVaroquaux
Copy link
Member
GaelVaroquaux commented Oct 25, 2016 via email

amueller pushed a commit to amueller/scikit-learn that referenced this pull request Oct 25, 2016
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
amueller pushed a commit to amueller/scikit-learn that referenced this pull request Oct 27, 2016
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
sergeyf pushed a commit to sergeyf/scikit-learn that referenced this pull request Feb 28, 2017
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
Sundrique pushed a commit to Sundrique/scikit-learn that referenced this pull request Jun 14, 2017
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
paulha pushed a commit to paulha/scikit-learn that referenced this pull request Aug 19, 2017
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
maskani-moh pushed a commit to maskani-moh/scikit-learn that referenced this pull request Nov 15, 2017
…7591)

Raise ValueError if l1_ratio=0 in ElasticNetCV and alphas=None
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

_alpha_grid divide by zero when l1_ratio=0 (ElasticNetCV)
7 participants
0