Skip to content
This repository was archived by the owner on Jul 24, 2024. It is now read-only.
This repository was archived by the owner on Jul 24, 2024. It is now read-only.

ElasticNet.fit raises ValueError when not converging instead of just issuing a warning #74

@mathurinm

Description

@mathurinm

Thank you for your package, and for making it available on conda.

If I set a max_iter which is too low, instead of getting a convergence warning as in sklearn behavior, it simply fails with an error. Can this be fixed easily? I'm trying to get the solution for a single lambda (and from what I understood, if I use a default apth, I have no guarantee that glmnet will go to the end of it, it may early stop, which I don't want).
Reproduce with:

from celer.datasets import make_correlated_data
from sklearn.linear_model import ElasticNet
import glmnet
from numpy.linalg import norm
import numpy as np

np.random.seed(0)
X = np.random.randn(100, 200)
X = np.asfortranarray(X)
y = np.random.randn(100)
alpha_max = norm(X.T @ y, ord=np.inf) / len(y)


clf2 = glmnet.ElasticNet(alpha=1, lambda_path=[
                         alpha_max, alpha_max/100], standardize=False, fit_intercept=False, tol=1e-10, max_iter=1).fit(X, y)

output:

/home/mathurin/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/errors.py:66: RuntimeWarning: Model did not converge for smaller values of lambda, returning solution for the largest 3 values.
  warnings.warn("Model did not converge for smaller values of lambda, "
/home/mathurin/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/errors.py:66: RuntimeWarning: Model did not converge for smaller values of lambda, returning solution for the largest 3 values.
  warnings.warn("Model did not converge for smaller values of lambda, "
/home/mathurin/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/util.py:202: RuntimeWarning: lambda_path has a single value, this may be an intercept-only model.
  warnings.warn("lambda_path has a single value, this may be an "
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-1-97963ff96fcf> in <module>
     10 
     11 
---> 12 clf2 = glmnet.ElasticNet(alpha=1, lambda_path=[
     13                          alpha_max, alpha_max/100], standardize=False, fit_intercept=False, tol=1e-10, max_iter=1).fit(X, y)

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/linear.py in fit(self, X, y, sample_weight, relative_penalties, groups)
    236                 self._cv = GroupKFold(n_splits=self.n_splits)
    237 
--> 238             cv_scores = _score_lambda_path(self, X, y, groups,
    239                                            sample_weight,
    240                                            relative_penalties,

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/util.py in _score_lambda_path(est, X, y, groups, sample_weight, relative_penalties, scoring, n_jobs, verbose)
     64         warnings.simplefilter(action, UndefinedMetricWarning)
     65 
---> 66         scores = Parallel(n_jobs=n_jobs, verbose=verbose, backend='threading')(
     67             delayed(_fit_and_score)(est, scorer, X, y, sample_weight, relative_penalties,
     68                                     est.lambda_path_, train_idx, test_idx)

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/parallel.py in __call__(self, iterable)
   1041             # remaining jobs.
   1042             self._iterating = False
-> 1043             if self.dispatch_one_batch(iterator):
   1044                 self._iterating = self._original_iterator is not None
   1045 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/parallel.py in dispatch_one_batch(self, iterator)
    859                 return False
    860             else:
--> 861                 self._dispatch(tasks)
    862                 return True
    863 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/parallel.py in _dispatch(self, batch)
    777         with self._lock:
    778             job_idx = len(self._jobs)
--> 779             job = self._backend.apply_async(batch, callback=cb)
    780             # A job can complete so quickly than its callback is
    781             # called before we get here, causing self._jobs to

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/_parallel_backends.py in apply_async(self, func, callback)
    206     def apply_async(self, func, callback=None):
    207         """Schedule a func to be run"""
--> 208         result = ImmediateResult(func)
    209         if callback:
    210             callback(result)

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/_parallel_backends.py in __init__(self, batch)
    570         # Don't delay the application, to avoid keeping the input
    571         # arguments in memory
--> 572         self.results = batch()
    573 
    574     def get(self):

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/parallel.py in __call__(self)
    260         # change the default number of processes to -1
    261         with parallel_backend(self._backend, n_jobs=self._n_jobs):
--> 262             return [func(*args, **kwargs)
    263                     for func, args, kwargs in self.items]
    264 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/joblib/parallel.py in <listcomp>(.0)
    260         # change the default number of processes to -1
    261         with parallel_backend(self._backend, n_jobs=self._n_jobs):
--> 262             return [func(*args, **kwargs)
    263                     for func, args, kwargs in self.items]
    264 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/util.py in _fit_and_score(est, scorer, X, y, sample_weight, relative_penalties, score_lambda_path, train_inx, test_inx)
    117 
    118     lamb = np.clip(score_lambda_path, m.lambda_path_[-1], m.lambda_path_[0])
--> 119     return scorer(m, X[test_inx, :], y[test_inx], lamb=lamb)
    120 
    121 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/scorer.py in _passthrough_scorer(estimator, *args, **kwargs)
    187 def _passthrough_scorer(estimator, *args, **kwargs):
    188     """Function that wraps estimator.score"""
--> 189     return estimator.score(*args, **kwargs)
    190 
    191 

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/linear.py in score(self, X, y, lamb)
    437 
    438         # pred will have shape (n_samples, n_lambda)
--> 439         pred = self.predict(X, lamb=lamb)
    440 
    441         # Reverse the args of the r2_score function from scikit-learn. The

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/linear.py in predict(self, X, lamb)
    414             Predicted response value for each sample given each value of lambda
    415         """
--> 416         return self.decision_function(X, lamb)
    417 
    418     def score(self, X, y, lamb=None):

~/anaconda3/envs/benchopt_lasso/lib/python3.8/site-packages/glmnet/linear.py in decision_function(self, X, lamb)
    392         # single value of lambda
    393         if lamb.shape[0] == 1:
--> 394             z = z.squeeze(axis=-1)
    395         return z
    396 

ValueError: cannot select an axis to squeeze out which has size not equal to one

ping @agramfort

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions