@@ -154,7 +154,7 @@ def _initialize_nmf(X, n_components, variant=None, eps=1e-6,
154
154
return W , H
155
155
156
156
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 ):
158
158
"""Non-negative least square solver
159
159
160
160
Solves a non-negative least squares subproblem using the
@@ -175,6 +175,19 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
175
175
max_iter : int
176
176
Maximum number of iterations before timing out.
177
177
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
+
178
191
Returns
179
192
-------
180
193
H : array-like
@@ -186,6 +199,14 @@ def _nls_subproblem(V, W, H_init, tol, max_iter):
186
199
n_iter : int
187
200
The number of iterations done by the algorithm.
188
201
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
+
189
210
"""
190
211
if (H_init < 0 ).any ():
191
212
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):
196
217
197
218
# values justified in the paper
198
219
alpha = 1
199
- beta = 0.1
200
220
for n_iter in range (1 , max_iter + 1 ):
201
221
grad = np .dot (WtW , H ) - WtV
202
222
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):
211
231
d = Hn - H
212
232
gradd = np .sum (grad * d )
213
233
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
216
235
if inner_iter == 1 :
217
236
decr_alpha = not suff_decr
218
237
Hp = H
@@ -321,8 +340,8 @@ class ProjectedGradientNMF(BaseEstimator, TransformerMixin):
321
340
>>> model.reconstruction_err_ #doctest: +ELLIPSIS
322
341
0.513...
323
342
324
- Notes
325
- -----
343
+ References
344
+ ----------
326
345
This implements
327
346
328
347
C.-J. Lin. Projected gradient methods
0 commit comments