8000 Add option to restrict ElasticNet to positive-only coefficients; add … · jwchennlp/scikit-learn@d6e7e51 · GitHub
[go: up one dir, main page]

Skip to content

Commit d6e7e51

Browse files
bwignallagramfort
authored andcommitted
Add option to restrict ElasticNet to positive-only coefficients; add test for this case, and the same for LassoCV
1 parent 0b20feb commit d6e7e51

File tree

2 files changed

+36
-1
lines changed

2 files changed

+36
-1
lines changed

sklearn/linear_model/coordinate_descent.py

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1171,6 +1171,9 @@ class ElasticNetCV(LinearModelCV, RegressorMixin):
11711171
all the CPUs. Note that this is used only if multiple values for
11721172
l1_ratio are given.
11731173
1174+
positive: bool, optional
1175+
When set to ``True``, forces the coefficients to be positive.
1176+
11741177
Attributes
11751178
----------
11761179
``alpha_`` : float
@@ -1226,7 +1229,7 @@ class ElasticNetCV(LinearModelCV, RegressorMixin):
12261229
def __init__(self, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None,
12271230
fit_intercept=True, normalize=False, precompute='auto',
12281231
max_iter=1000, tol=1e-4, cv=None, copy_X=True,
1229-
verbose=0, n_jobs=1):
1232+
verbose=0, n_jobs=1, positive=False):
12301233
self.l1_ratio = l1_ratio
12311234
self.eps = eps
12321235
self.n_alphas = n_alphas
@@ -1240,6 +1243,7 @@ def __init__(self, l1_ratio=0.5, eps=1e-3, n_alphas=100, alphas=None,
12401243
self.copy_X = copy_X
12411244
self.verbose = verbose
12421245
self.n_jobs = n_jobs
1246+
self.positive = positive
12431247

12441248

12451249
###############################################################################

sklearn/linear_model/tests/test_coordinate_descent.py

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,22 @@ def test_lasso_cv():
179179
assert_greater(clf.score(X_test, y_test), 0.99)
180180

181181

182+
def test_lasso_cv_positive_constraint():
183+
X, y, X_test, y_test = build_dataset()
184+
max_iter = 1000
185+
186+
# Ensure the unconstrained fit has a negative coefficient
187+
clf_unconstrained = LassoCV(n_alphas=10, eps=1e-3, max_iter=max_iter)
188+
clf_unconstrained.fit(X, y)
189+
assert_true(min(clf_unconstrained.coef_) < 0)
190+
191+
# On same data, constrained fit has non-negative coefficients
192+
clf_constrained = LassoCV(n_alphas=10, eps=1e-3, max_iter=max_iter,
193+
positive=True)
194+
clf_constrained.fit(X, y)
195+
assert_true(min(clf_constrained.coef_) >= 0)
196+
197+
182198
def test_lasso_path_return_models_vs_new_return_gives_same_coefficients():
183199
# Test that lasso_path with lars_path style output gives the
184200
# same result
@@ -300,6 +316,21 @@ def test_enet_positive_constraint():
300316
assert_true(min(enet.coef_) >= 0)
301317

302318

319+
def test_enet_cv_positive_constraint():
320+
X, y, X_test, y_test = build_dataset()
321+
max_iter = 1500
322+
323+
# Ensure the unconstrained fit has a negative coefficient
324+
enetcv_unconstrained = ElasticNetCV(max_iter=max_iter)
325+
enetcv_unconstrained.fit(X, y)
326+
assert_true(min(enetcv_unconstrained.coef_) < 0)
327+
328+
# On same data, constrained fit has non-negative coefficients
329+
enetcv_constrained = ElasticNetCV(max_iter=max_iter, positive=True)
330+
enetcv_constrained.fit(X, y)
331+
assert_true(min(enetcv_constrained.coef_) >= 0)
332+
333+
303334
def test_multi_task_lasso_and_enet():
304335
X, y, X_test, y_test = build_dataset()
305336
Y = np.c_[y, y]

0 commit comments

Comments
 (0)
0