10000 Demystify magic values in NNLS implementation. · nullnotfound/scikit-learn@d3bc5ac · GitHub
[go: up one dir, main page]

Skip to content

Commit d3bc5ac

Browse files
committed
Demystify magic values in NNLS implementation.
1 parent 5ece0e1 commit d3bc5ac

File tree

1 file changed

+25
-6
lines changed

1 file changed

+25
-6
lines changed

sklearn/decomposition/nmf.py

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -154,7 +154,7 @@ def _initialize_nmf(X, n_components, variant=None, eps=1e-6,
154154
return W, H
155155

156156

157-
def _nls_subproblem(V, W, H_init, tol, max_iter):
157+
def _nls_subproblem(V, W, H_init, tol, max_iter, sigma=0.01, beta=0.1):
158158
"""Non-negative least square solver
159159
160160
Solves a non-negative least squares subproblem using the
@@ -175,6 +175,19 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
175175
max_iter : int
176176
Maximum number of iterations before timing out.
177177
178+
sigma : float
179+
Constant used in the sufficient decrease condition checked by the line
180+
search. Smaller values lead to a looser sufficient decrease condition,
181+
thus reducing the time taken by the line search, but potentially
182+
increasing the number of iterations of the projected gradient procedure.
183+
0.01 is a commonly used value in the optimization literature.
184+
185+
beta : float
186+
Factor by which the step size is decreased (resp. increased) until
187+
(resp. as long as) the sufficient decrease condition is satisfied.
188+
Larger values allow to find a better step size but lead to longer line
189+
search. 0.1 is a commonly used value in the optimization literature.
190+
178191
Returns
179192
-------
180193
H : array-like
@@ -186,6 +199,14 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
186199
n_iter : int
187200
The number of iterations done by the algorithm.
188201
202+
Reference
203+
---------
204+
205+
C.-J. Lin. Projected gradient methods
206+
for non-negative matrix factorization. FFFB Neural
207+
Computation, 19(2007), 2756-2779.
208+
http://www.csie.ntu.edu.tw/~cjlin/nmf/
209+
189210
"""
190211
if (H_init < 0).any():
191212
raise ValueError("Negative values in H_init passed to NLS solver.")
@@ -196,7 +217,6 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
196217

197218
# values justified in the paper
198219
alpha = 1
199-
beta = 0.1
200220
for n_iter in range(1, max_iter + 1):
201221
grad = np.dot(WtW, H) - WtV
202222
proj_gradient = norm(grad[np.logical_or(grad < 0, H > 0)])
@@ -211,8 +231,7 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
211231
d = Hn - H
212232
gradd = np.sum(grad * d)
213233
dQd = np.sum(np.dot(WtW, d) * d)
214-
# magic numbers whoa
215-
suff_decr = 0.99 * gradd + 0.5 * dQd < 0
234+
suff_decr = (1 - sigma) * gradd + 0.5 * dQd < 0
216235
if inner_iter == 1:
217236
decr_alpha = not suff_decr
218237
Hp = H
@@ -321,8 +340,8 @@ class ProjectedGradientNMF(BaseEstimator, TransformerMixin):
321340
>>> model.reconstruction_err_ #doctest: +ELLIPSIS
322341
0.513...
323342
324-
Notes
325-
-----
343+
References
344+
----------
326345
This implements
327346
328347
C.-J. Lin. Projected gradient methods

0 commit comments

Comments
 (0)
0