8000 FIX temporary fix for sparse ridge with intercept fitting · scikit-learn/scikit-learn@58058cf · GitHub
[go: up one dir, main page]

Skip to content

Commit 58058cf

Browse files
committed
FIX temporary fix for sparse ridge with intercept fitting
1 parent e8d2b93 commit 58058cf

File tree

2 files changed

+52
-9
lines changed

2 files changed

+52
-9
lines changed

sklearn/linear_model/ridge.py

Lines changed: 36 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@ def _solve_svd(X, y, alpha):
194194

195195
def ridge_regression(X, y, alpha, sample_weight=None, solver='auto',
196196
max_iter=None, tol=1e-3, verbose=0, random_state=None,
197-
return_n_iter=False):
197+
return_n_iter=False, return_intercept=False):
198198
"""Solve the ridge equation by the method of normal equations.
199199
200200
Read more in the :ref:`User Guide <ridge_regression>`.
@@ -268,6 +268,11 @@ def ridge_regression(X, y, alpha, sample_weight=None, solver='auto',
268268
If True, the method also returns `n_iter`, the actual number of
269269
iteration performed by the solver.
270270
271+
return_intercept : boolean, default False
272+
If True, the method also returns the intercept, and the solver
273+
is automatically changed to 'sag'. This is only a temporary fix
274+
for fitting the intercept with sparse data.
275+
271276
Returns
272277
-------
273278
coef : array, shape = [n_features] or [n_targets, n_features]
@@ -281,6 +286,9 @@ def ridge_regression(X, y, alpha, sample_weight=None, solver='auto',
281286
-----
282287
This function won't compute the intercept.
283288
"""
289+
if return_intercept:
290+
solver = 'sag'
291+
284292
# SAG needs X and y columns to be C-contiguous and np.float64
285293
if solver == 'sag':
286294
X = check_array(X, accept_sparse=['csr'],
@@ -375,12 +383,18 @@ def ridge_regression(X, y, alpha, sample_weight=None, solver='auto',
375383

376384
coef = np.empty((y.shape[1], n_features))
377385
n_iter = np.empty(y.shape[1], dtype=np.int32)
386+
intercept = np.zeros((y.shape[1], ))
378387
for i, (alpha_i, target) in enumerate(zip(alpha, y.T)):
388+
start = {'coef': np.zeros(n_features + int(return_intercept))}
379389
coef_, n_iter_, _ = sag_solver(
380390
X, target.ravel(), sample_weight, 'squared', alpha_i,
381391
max_iter, tol, verbose, random_state, False, max_squared_sum,
382-
dict())
383-
coef[i] = coef_
392+
start)
393+
if return_intercept:
394+
coef[i] = coef_[:-1]
395+
intercept[i] = coef_[-1]
396+
else:
397+
coef[i] = coef_
384398
n_iter[i] = n_iter_
385399

386400
coef = np.asarray(coef)
@@ -395,7 +409,11 @@ def ridge_regression(X, y, alpha, sample_weight=None, solver='auto',
395409
# When y was passed as a 1d-array, we flatten the coefficients.
396410
coef = coef.ravel()
397411

398-
if return_n_iter:
412+
if return_n_iter and return_intercept:
413+
return coef, n_iter, intercept
414+
elif return_intercept:
415+
return coef, intercept
416+
elif return_n_iter:
399417
return coef, n_iter
400418
else:
401419
return coef
@@ -428,12 +446,21 @@ def fit(self, X, y, sample_weight=None):
428446
X, y, self.fit_intercept, self.normalize, self.copy_X,
429447
sample_weight=sample_weight)
430448

431-
self.coef_, self.n_iter_ = ridge_regression(
432-
X, y, alpha=self.alpha, sample_weight=sample_weight,
433-
max_iter=self.max_iter, tol=self.tol, solver=self.solver,
434-
random_state=self.random_state, return_n_iter=True)
449+
if sparse.issparse(X) and self.fit_intercept:
450+
self.coef_, self.n_iter_, self.intercept_ = ridge_regression(
451+
X, y, alpha=self.alpha, sample_weight=sample_weight,
452+
max_iter=self.max_iter, tol=self.tol, solver=self.solver,
453+
random_state=self.random_state, return_n_iter=True,
454+
return_intercept=True)
455+
self.intercept_ += y_mean
456+
else:
457+
self.coef_, self.n_iter_ = ridge_regression(
458+
X, y, alpha=self.alpha, sample_weight=sample_weight,
459+
max_iter=self.max_iter, tol=self.tol, solver=self.solver,
460+
random_state=self.random_state, return_n_iter=True,
461+
return_intercept=False)
462+
self._set_intercept(X_mean, y_mean, X_std)
435463

436-
self._set_intercept(X_mean, y_mean, X_std)
437464
return self
438465

439466

sklearn/linear_model/tests/test_ridge.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -694,3 +694,19 @@ def test_n_iter():
694694
reg = Ridge(solver=solver, max_iter=1, tol=1e-1)
695695
reg.fit(X, y_n)
696696
assert_equal(reg.n_iter_, None)
697+
698+
699+
def test_ridge_fit_intercept_sparse():
700+
r = np.random.RandomState(42)
701+
X = r.randn(1000, 2)
702+
w = r.randn(2)
703+
i = 10
704+
y = np.dot(X, w) + i
705+
X_csr = sp.csr_matrix(X)
706+
707+
dense = Ridge(alpha=1., tol=1.e-15, solver='sag', fit_intercept=True)
708+
sparse = Ridge(alpha=1., tol=1.e-15, solver='sag', fit_intercept=True)
709+
dense.fit(X, y)
710+
sparse.fit(X_csr, y)
711+
assert_almost_equal(dense.intercept_, sparse.intercept_)
712+
assert_array_almost_equal(dense.coef_, sparse.coef_)

0 commit comments

Comments
 (0)
0