diff --git a/scikits/learn/linear_model/least_angle.py b/scikits/learn/linear_model/least_angle.py index 6739451a2224ecd5cb33d959927e7748cfd64ab6..affb85fa6799cb670285664f97f347e6dfe03dc7 100644 --- a/scikits/learn/linear_model/least_angle.py +++ b/scikits/learn/linear_model/least_angle.py @@ -120,7 +120,17 @@ def lars_path(X, y, Xy=None, Gram=None, max_features=None, alphas[n_iter] = C / n_samples - if (C < alpha_min) or (n_active == max_features): + # Check for early stopping + if alphas[n_iter] < alpha_min: # interpolate + # interpolation factor 0 <= ss < 1 + ss = (alphas[n_iter-1] - alpha_min) / (alphas[n_iter-1] - + alphas[n_iter]) + coefs[n_iter] = coefs[n_iter-1] + ss*(coefs[n_iter] - + coefs[n_iter-1]) + alphas[n_iter] = alpha_min + break + + if n_active == max_features: break if not drop: @@ -270,13 +280,6 @@ def lars_path(X, y, Xy=None, Gram=None, max_features=None, if verbose: print "%s\t\t%s\t\t%s\t\t%s\t\t%s" % (n_iter, '', drop_idx, n_active, abs(temp)) - if alphas[n_iter] < alpha_min: # interpolate - # interpolation factor 0 <= ss < 1 - ss = (alphas[n_iter-1] - alpha_min) / (alphas[n_iter-1] - - alphas[n_iter]) - coefs[n_iter] = coefs[n_iter-1] + ss*(coefs[n_iter] - coefs[n_iter-1]) - alphas[n_iter] = alpha_min - # resize coefs in case of early stop alphas = alphas[:n_iter+1] diff --git a/scikits/learn/linear_model/tests/test_least_angle.py b/scikits/learn/linear_model/tests/test_least_angle.py index c9bf228ca43e48a69886920e01a5337f91fae077..4521dbbab5931b3c784856e4e40485f06611ba97 100644 --- a/scikits/learn/linear_model/tests/test_least_angle.py +++ b/scikits/learn/linear_model/tests/test_least_angle.py @@ -111,6 +111,22 @@ def test_lasso_lars_vs_lasso_cd(verbose=False): error = np.linalg.norm(c - lasso_cd.coef_) assert error < 0.01 +def test_lasso_lars_vs_lasso_cd_early_stopping(verbose=False): + """ + Test that LassoLars and Lasso using coordinate descent give the + same results when early stopping is used. + (test : before, in the middle, and in the last part of the path) + """ + alphas_min = [10, 0.9, 1e-4] + for alphas_min in alphas_min: + alphas, _, lasso_path = linear_model.lars_path(X, y, method='lasso', + alpha_min=0.9) + lasso_cd = linear_model.Lasso(fit_intercept=False) + lasso_cd.alpha = alphas[-1] + lasso_cd.fit(X, y, tol=1e-8) + error = np.linalg.norm(lasso_path[:,-1] - lasso_cd.coef_) + assert error < 0.01 + if __name__ == '__main__': import nose