Skip to main content

Non-negative matrix factorisation

Forbid negative entries in both factors and a factorisation turns into parts that only add up. Derive Lee and Seung’s multiplicative updates from gradient descent, run one by hand, and find sports and baking topics and pen strokes.
ML03.7.2L2 Intermediate25 min
In review (what this means)

The maths and code on this page are checked by automated tests on every change, but an independent reader has not signed it off yet. Spot a mistake or a confusing step? Tell us.

Before this lesson: ML03.7.1 Data as a product of two thin matrices ML01.5 Gradient descent from scratch

What you will be able to do
  • State the non-negative matrix factorisation problem and explain why non-negative factors read as additive parts.
  • Derive the multiplicative updates for the squared error as gradient descent with a step chosen for each entry.
  • Carry out one multiplicative update by hand and check that the error falls.
  • Fit NMF from scratch and with sklearn.decomposition.NMF, and explain why its factors are not unique.

The question

The last lesson’s factors said that a document is “all words, plus sports, minus baking”, and its rank-2 reconstruction claimed that d1 contains \({-0.12}\) of the word “oven”. Can we keep the idea of a thin matrix times a wide one but insist that documents are built only by adding parts, never by taking words away?

From the last lesson

1. What is the smallest squared error of a rank-2 product for the corpus, and where does it come from?

Show answer

5.692, the sum of the discarded squared singular values \({3.20 + 1.54 + 0.73 + 0.22 + 0}\) (Eckart and Young).

2. How is a new document placed in the LSA plane?

Show answer

By folding in: multiply its count vector by \(\mat{U}_2\T\), that is, take its dot product with the first two left singular vectors.

Intuition

Require every entry of \(\mat{W}\) and of \(\mat{H}\) to be zero or more. Then each column of \(\mat{W}\) is a set of words with non-negative weights: a part. Each document is a sum of parts with non-negative amounts, so a part can be switched on or left out, but never subtracted.

Left, titled Two parts: columns of W: horizontal bar pairs for the eight words. Solid blue bars, labelled sports, are long for team, ball, goal and match and nearly zero for the baking words; hatched sky-blue bars, labelled baking, are long for bake, flour, oven and sugar and nearly zero for the sports words. The axis reads share of the part's words. Right, titled Each document adds them: H: stacked bars for d1 to d7; d1, d2 and d3 are all solid blue at about 4, d4, d5 and d6 all hatched sky blue at about 4, and d7 is half solid and half hatched, labelled half and half. The axis reads words taken from each part.
ML03.7.2-F1

Non-negative factors of the corpus with rank 2. Each column of \(\mat{W}\) (scaled to sum to 1) is a part, here a sports part and a baking part. Each document takes some words from each part; d7 takes about 2.3 from each.

Nothing told the method which words go together. The constraint alone produced two parts that a person would name “sports” and “baking”. This is non-negative matrix factorisation (NMF), and the effect is called a parts-based representation: Lee and Seung contrasted it with PCA, which builds data from directions that cancel each other, and with clustering, where each example takes exactly one prototype.

Build it up

Step 1. The problem. Given a non-negative \({V \times D}\) matrix \(\mat{X}\) and a rank \(q\), solve

\[ \begin{aligned} \min_{\mat{W}, \mat{H}} \;& E = \norm{\mat{X} - \mat{W}\mat{H}}_F^2 \\ \text{subject to}\;& \mat{W} \ge 0,\; \mat{H} \ge 0 . \end{aligned} \]

Step 2. No formula, so iterate. The SVD answer of the last lesson breaks the constraint, and no closed form is known. For fixed \(\mat{W}\) the error is a convex bowl in \(\mat{H}\), and for fixed \(\mat{H}\) a bowl in \(\mat{W}\), but it is not convex in both at once. So we alternate: improve \(\mat{H}\) with \(\mat{W}\) fixed, then \(\mat{W}\) with \(\mat{H}\) fixed, and accept a local minimum.

Step 3. Plain gradient steps can cross zero. Take one document, d1, and fix \(\mat{W}\) to the two parts. The error is a bowl over the two amounts. Gradient descent with a fixed step walks downhill, but nothing stops a step from landing on a negative amount.

Two contour plots of the error for document d1 over the sports amount (horizontal, 0 to 6) and the baking amount (vertical, minus 2.6 to 3.6), with the region below zero tinted purple and labelled below zero: not allowed. Left, marked with a cross and titled Plain gradient steps: a green path starting at the ringed point (1, 3) zigzags down and across the zero line several times, labelled crosses zero and back. Right, marked with a tick and titled Multiplicative steps: a green path from the same start drops to about (3.5, 0.1) and then creeps along just above zero to about (4.05, 0), labelled shrinks towards zero, never past.
ML03.7.2-F2

The same bowl, two kinds of step from the same start. A fixed gradient step overshoots into negative amounts; the multiplicative step multiplies the amount by a positive factor, so it can shrink towards zero but never crosses it.

Step 4. Pick a step for each entry. A gradient step can use a different step size for every entry. Lee and Seung chose the one size that cancels the subtraction, so that the step becomes a multiplication by a positive factor. The derivation follows.

The formal statement

The gradient. Write \({\mat{R} = \mat{X} - \mat{W}\mat{H}}\). Changing \(\mat{H}\) by a small \({\delta\mat{H}}\) changes the product by \({\mat{W}\,\delta\mat{H}}\), so to first order

\[ \begin{aligned} \delta E &= -2\sum_{w,d} r_{wd}\,(\mat{W}\,\delta\mat{H})_{wd} \\ &= -2\sum_{k,d} (\mat{W}\T\mat{R})_{kd}\,\delta h_{kd} . \end{aligned} \]

So the gradient with respect to \(\mat{H}\) is

\[ \begin{aligned} \pd{E}{\mat{H}} &= -2\,\mat{W}\T(\mat{X} - \mat{W}\mat{H}) \\ &= 2\,\big(\mat{W}\T\mat{W}\mat{H} - \mat{W}\T\mat{X}\big) . \end{aligned} \]

Both \(\mat{W}\T\mat{W}\mat{H}\) and \(\mat{W}\T\mat{X}\) are non-negative: the gradient is a difference of two non-negative parts.

A step for each entry. Gradient descent with step \(\eta_{kd}\) on entry \(h_{kd}\) is

\[ \begin{aligned} h_{kd} \leftarrow h_{kd} - 2\eta_{kd}\big[&(\mat{W}\T\mat{W}\mat{H})_{kd} \\ - &(\mat{W}\T\mat{X})_{kd}\big]. \end{aligned} \]

Choose \({\eta_{kd} = h_{kd} / \big(2(\mat{W}\T\mat{W}\mat{H})_{kd}\big)}\). The first term in the bracket then cancels \(h_{kd}\) exactly:

\[ \begin{aligned} h_{kd} &\leftarrow h_{kd} - h_{kd} + h_{kd}\frac{(\mat{W}\T\mat{X})_{kd}}{(\mat{W}\T\mat{W}\mat{H})_{kd}} \\ &= h_{kd}\,\frac{\cgrad{(\mat{W}\T\mat{X})_{kd}}}{\cmodel{(\mat{W}\T\mat{W}\mat{H})_{kd}}} . \end{aligned} \]

NoteThe multiplicative updates (Lee and Seung)

With \(\circ\) and the fraction bar acting entry by entry,

\[ \begin{aligned} \mat{H} &\leftarrow \mat{H} \circ \frac{\mat{W}\T\mat{X}}{\mat{W}\T\mat{W}\mat{H}}, \\ \mat{W} &\leftarrow \mat{W} \circ \frac{\mat{X}\mat{H}\T}{\mat{W}\mat{H}\mat{H}\T} . \end{aligned} \]

Started from positive matrices, every entry stays non-negative, and the squared error never increases.

The update for \(\mat{W}\) is the twin: the same argument applied to \({\mat{X}\T \approx \mat{H}\T\mat{W}\T}\).

Read the factor as what the data asks for over what the model already gives. When the model under-supplies a part, the factor is above 1 and the amount grows; when it over-supplies, the factor is below 1 and the amount shrinks. The factor is never negative, so a positive entry stays positive. A zero stays zero for ever, which is why a start with zeros in it is a bad idea. If \({\mat{X} = \mat{W}\mat{H}}\) exactly, every factor is 1 and nothing moves.

A log-log plot of squared error against one plus the number of updates, from 1 (the random start) to 2001, for five random starts on the corpus with rank 2. All five reddish-purple curves start between about 22 and 30 at the random start, fall steeply within ten updates, and level off at 5.780. A dashed vermillion line just below them marks rank-2 SVD: 5.692, the lowest any rank-2 product can reach.
ML03.7.2-F3

Five random starts on the corpus. The error only falls, and every start settles at 5.780, just above the SVD’s 5.692. The constraint raises the error by 1.5 percent and buys readable parts.

Go deeper: why the error never rises: the auxiliary function

Lee and Seung’s proof works one column \(\vect{h}\) of \(\mat{H}\) at a time, with \({F(\vect{h}) = \tfrac12\norm{\vect{x} - \mat{W}\vect{h}}^2}\). A function \({G(\vect{h}, \vect{h}')}\) is an auxiliary function for \(F\) if \({G(\vect{h}, \vect{h}') \ge F(\vect{h})}\) for all \(\vect{h}\) and \({G(\vect{h}, \vect{h}) = F(\vect{h})}\). Then moving to the minimiser of \({G(\cdot, \vect{h}^t)}\) cannot raise \(F\):

\[ \begin{aligned} F(\vect{h}^{t+1}) &\le G(\vect{h}^{t+1}, \vect{h}^t) \\ &\le G(\vect{h}^t, \vect{h}^t) = F(\vect{h}^t) . \end{aligned} \]

\(F\) is exactly quadratic, with curvature matrix \(\mat{W}\T\mat{W}\). Replace that curvature by a diagonal matrix \(\mat{K}\) with \({K_{aa} = (\mat{W}\T\mat{W}\vect{h}^t)_a / h^t_a}\):

\[ \begin{aligned} G(\vect{h}, \vect{h}^t) = F(\vect{h}^t) &+ \vect{g}\T\nabla F(\vect{h}^t) \\ &+ \tfrac12\,\vect{g}\T\mat{K}\vect{g}, \end{aligned} \]

with \({\vect{g} = \vect{h} - \vect{h}^t}\).

\(G\) touches \(F\) at \({\vect{h} = \vect{h}^t}\). It lies above \(F\) everywhere if \({\mat{K} - \mat{W}\T\mat{W}}\) is positive semidefinite; rescaling it to \({M_{ab} = h^t_a (\mat{K} - \mat{W}\T\mat{W})_{ab} h^t_b}\) and expanding gives

\[ \begin{aligned} \vect{\nu}\T\mat{M}\vect{\nu} &= \tfrac12\sum_{a,b}(\mat{W}\T\mat{W})_{ab}h^t_a h^t_b \\ &\qquad \times (\nu_a - \nu_b)^2 \;\ge\; 0 . \end{aligned} \]

Because \(\mat{K}\) is diagonal, \(G\) is minimised entry by entry: setting its gradient to zero gives \({h_a = h^t_a - (\nabla F)_a / K_{aa}}\), which simplifies to the multiplicative update. The details are Lemmas 1 and 2 of the paper.

Worked example

One update of \(\mat{H}\) by hand. Use the small piece of the corpus: words ball, team, bake, flour (rows) in documents d2, d5, d7 (columns), with \({q = 2}\). Start from

\[ \mat{X} = \begin{bmatrix} 1 & 0 & 1 \\ 2 & 0 & 1 \\ 0 & 2 & 1 \\ 0 & 1 & 1 \end{bmatrix}, \quad \mat{W} = \begin{bmatrix} 2 & 1 \\ 2 & 1 \\ 1 & 2 \\ 1 & 2 \end{bmatrix}, \]

and \(\mat{H}\) all ones. Every entry of the starting product is \({2 + 1 = 3}\), so the starting error is the sum of \({(x - 3)^2}\) over the twelve cells, row by row:

\[ \begin{aligned} &(4 + 9 + 4) + (1 + 9 + 4) \\ &\quad + (9 + 1 + 4) + (9 + 4 + 4) = 62 . \end{aligned} \]

A worked trace. Left, the 4 by 3 data piece X with rows ball, team, bake, flour and columns d2, d5, d7: 1 0 1, 2 0 1, 0 2 1, 0 1 1. Next, the orange start W: 2 1, 2 1, 1 2, 1 2, with a note start H: all ones. Then a green grid W transpose X: 6 3 6 over 3 6 6, and below it a vermillion grid W transpose W H: all 18. An arrow leads to the new H: 6/18, 3/18, 6/18 over 3/18, 6/18, 6/18, and below it error 62 to 4.556, with the note every entry of the old WH was 3.
ML03.7.2-F4

One multiplicative update of \(\mat{H}\). Each new entry is the old one (1) times what the data asks for over what the model gives.

What the data asks for. Row 1 of \(\mat{W}\T\) is \({(2, 2, 1, 1)}\), so the first row of \(\mat{W}\T\mat{X}\) is \({(2 + 4,\; 2 + 1,\; 2 + 2 + 1 + 1)}\), which is \({(6, 3, 6)}\). Row 2, \({(1, 1, 2, 2)}\), gives \({(1 + 2,\; 4 + 2,\; 1 + 1 + 2 + 2)}\), which is \({(3, 6, 6)}\).

What the model gives. \({\mat{W}\T\mat{W}}\) has entries \({4 + 4 + 1 + 1 = 10}\) on the diagonal and \({2 + 2 + 2 + 2 = 8}\) off it. Times \(\mat{H}\) of ones, every entry is \({10 + 8 = 18}\).

The update. Each entry of \(\mat{H}\) becomes \({1 \times (\text{top}) / 18}\):

\[ \mat{H} = \begin{bmatrix} 1/3 & 1/6 & 1/3 \\ 1/6 & 1/3 & 1/3 \end{bmatrix} . \]

d2 now leans to part 1 and d5 to part 2, while d7 takes both equally.

The new error. The new product has rows \({(5/6, 2/3, 1)}\) for ball and team and \({(2/3, 5/6, 1)}\) for bake and flour. The squared errors are \({17/36}\) for ball, \({65/36}\) for team, \({65/36}\) for bake and \({17/36}\) for flour, in total \({164/36 = 4.556}\). One step took the error from 62 to 4.556. The matching update of \(\mat{W}\) takes it to 3.803, and 500 steps to 0.245.

Code

From scratch on the corpus, keeping the error after every pair of updates.

import numpy as np

docs = ["ball goal team goal", "team match ball team", "goal match team ball",
        "flour sugar bake oven", "bake oven flour bake", "sugar flour bake oven",
        "team bake ball flour"]
words = sorted({w for d in docs for w in d.split()})
X = np.array([[d.split().count(w) for d in docs] for w in words], dtype=float)

def nmf(X, q, steps, seed=0, eps=1e-12):
    rng = np.random.default_rng(seed)
    W = rng.uniform(0.1, 1.0, (X.shape[0], q))
    H = rng.uniform(0.1, 1.0, (q, X.shape[1]))
    errors = []
    for _ in range(steps):
        H *= (W.T @ X) / (W.T @ W @ H + eps)
        W *= (X @ H.T) / (W @ H @ H.T + eps)
        errors.append(((X - W @ H) ** 2).sum())
    return W, H, np.array(errors)

W, H, errors = nmf(X, 2, 2000)
scale = W.sum(axis=0)                      # make each part a set of shares ...
parts, amounts = W / scale, H * scale[:, None]   # ... and move the scale into H
svd_floor = (np.linalg.svd(X, compute_uv=False)[2:] ** 2).sum()
for k in range(2):
    top = [words[i] for i in np.argsort(-parts[:, k])[:4]]
    print(f"part {k + 1}: {top}")
print("d7 takes", amounts[:, 6].round(2), "words from the two parts")
print(f"error {errors[-1]:.3f} (SVD floor {svd_floor:.3f}); ever rose: {bool(np.any(np.diff(errors) > 1e-9))}")
part 1: ['team', 'ball', 'goal', 'match']
part 2: ['bake', 'flour', 'oven', 'sugar']
d7 takes [2.32 2.32] words from the two parts
error 5.780 (SVD floor 5.692); ever rose: False

The library. NMF takes examples as rows, so we pass \({\mat{X}\T}\): its fit_transform returns the document amounts and components_ the parts. The start init="nndsvda" comes from an SVD with zeros filled in, since multiplicative updates cannot move a zero. beta_loss="kullback-leibler" (with solver="mu") swaps the squared error for a divergence suited to counts; the next lesson shows what it means.

from sklearn.decomposition import NMF

model = NMF(n_components=2, init="nndsvda", max_iter=2000, tol=1e-10, random_state=0)
doc_amounts = model.fit_transform(X.T)                 # 7 x 2
print("squared error:", round(model.reconstruction_err_ ** 2, 3))

kl = NMF(n_components=2, init="nndsvda", beta_loss="kullback-leibler", solver="mu",
         max_iter=5000, tol=1e-12, random_state=0)
A = kl.fit_transform(X.T)
words_from_part = A * kl.components_.sum(axis=1)       # scale each part to sum to 1
print("KL loss, d7 takes", words_from_part[6].round(3), "words from each part")
squared error: 5.78
KL loss, d7 takes [2. 2.] words from each part

On images the same constraint finds strokes. Fitted to the 1797 digits of load_digits, each of 16 factors lights up a short piece of pen stroke, while PCA’s directions are patterns of light and dark that cancel.

from sklearn.datasets import load_digits

digits = load_digits().data                            # 1797 x 64, values 0 to 16
strokes = NMF(n_components=16, init="nndsvda", max_iter=500, random_state=0).fit(digits)
share_zero = (strokes.components_ < 1e-3).mean()
print(f"{share_zero:.0%} of the factor pixels are (nearly) zero")
75% of the factor pixels are (nearly) zero
Two blocks of eight small 8 by 8 pixel images. Left, marked with a cross and titled PCA directions: each image is a blotchy pattern of orange and purple pixels over most of the square, with the caption orange adds ink, purple takes it away. Right, marked with a tick and titled NMF factors: each image is mostly blank with a short orange stroke, such as a short vertical bar, a dot at the top or a curve at the bottom, with the caption only adds: pieces of strokes.
ML03.7.2-F6

Factors of the handwritten digits. PCA’s directions use cancellation; NMF’s factors are mostly blank, each holding one piece of a stroke, and a digit is a sum of a few of them.

Explore

ML03.7-X1

Factor explorer

The corpus’s 8 by 7 count matrix beside its two factors. Choose the rank and switch between the truncated SVD and NMF; for NMF, step the multiplicative updates or play them. Compare the error, the top words of each factor and the purple negative cells of the SVD.

The two non-negative parts of the corpus as word bars, a sports part and a baking part, and the seven documents as stacked bars showing how many words each takes from each part, with d7 half and half.

Pitfalls

Two panels of horizontal stacked bar pairs over the eight words, the upper bar of each pair from run A and the lower, faded bar from run B. Left, marked with a cross and titled Raw W: runs disagree: the bars of the two runs have different lengths, up to about 2.4 for team in run A, and the solid and hatched parts appear in a different order. Right, marked with a tick and titled Scaled and matched: after scaling each column to sum to 1 and matching the parts, every upper and lower bar is the same length.
ML03.7.2-F5

Wrong beside right. Two fits with different starts give different numbers in \(\mat{W}\). Scale each column to sum to 1 and match the parts, and they agree.

“Two runs gave different W, so one of them is wrong.”

For any diagonal matrix \(\mat{D}\) with positive entries, \({\mat{W}\mat{D}}\) and \({\mat{D}^{-1}\mat{H}}\) are non-negative and have the same product, and the parts can come out in any order. Fix the scale (each column of \(\mat{W}\) summing to 1) and match the parts before comparing. Beyond scaling and order, NMF can also stop at different local minima from different starts, so on real data compare several runs.

“NMF fits better than the SVD because it is cleverer.”

It cannot. The SVD gives the smallest error of any rank-\(q\) product; NMF searches a smaller set. On the corpus the costs are 5.692 against 5.780 at rank 2 and 2.495 against about 2.60 at rank 3. You give up a little fit to gain parts you can read.

“Start the updates from the SVD’s factors with the negatives set to zero.”

A zero entry is multiplied by a factor and stays zero, so every part that starts with zeros keeps them. That is why scikit-learn’s guide prefers "nndsvda", which fills those zeros with the mean of the data, when the multiplicative solver is used.

Check yourself

Recall

1. What does the non-negativity constraint change about how a document is built from parts?

Show answer

Parts can only be added in non-negative amounts, never subtracted, so each part reads as a group of words that appear together.

2. Write the multiplicative update for \(\mat{H}\).

Show answer

\({\mat{H} \leftarrow \mat{H} \circ (\mat{W}\T\mat{X}) / (\mat{W}\T\mat{W}\mat{H})}\), entry by entry.

3. Which step size turns gradient descent on \(h_{kd}\) into that update?

Show answer

\({\eta_{kd} = h_{kd} / \big(2(\mat{W}\T\mat{W}\mat{H})_{kd}\big)}\), which cancels the old value and leaves only the multiplication.

4. Why does an entry that starts at zero never move?

Show answer

Each update multiplies the entry by a factor, and zero times anything is zero.

5. On the corpus at rank 2, how do the NMF and SVD errors compare, and why can NMF not win?

Show answer

5.780 against 5.692. The SVD’s product is the best of all rank-2 products; NMF’s are a subset.

Exercises

1. ★ Continue the worked example. With the new \(\mat{H}\), the first row of \({\mat{X}\mat{H}\T}\) (ball) is \({(2/3, 1/2)}\) and the first row of \({\mat{W}\mat{H}\mat{H}\T}\) is \({(26/36, 25/36)}\). Find the new first row of \(\mat{W}\).

Show solution

Multiply the old row \({(2, 1)}\) by the ratios entry by entry:

\[ \begin{aligned} w_{11} &= 2 \times \frac{24/36}{26/36} = \frac{24}{13} = 1.846, \\ w_{12} &= 1 \times \frac{18/36}{25/36} = \frac{18}{25} = 0.72 . \end{aligned} \]

2. ★★ Show that for one column \({\vect{x} \ge 0}\) and one part \({\vect{w} \ge 0}\) (\({q = 1}\), \(\vect{w}\) fixed), a single multiplicative update from any \({h > 0}\) lands on the best non-negative \(h\).

Show solution

The update replaces \(h\) by \({h\,\vect{w}\T\vect{x} / (\vect{w}\T\vect{w}\,h)}\), which is \({\vect{w}\T\vect{x} / \vect{w}\T\vect{w}}\): the old \(h\) cancels. The error \({\norm{\vect{x} - h\vect{w}}^2}\) is a parabola in \(h\) with derivative \({2(h\,\vect{w}\T\vect{w} - \vect{w}\T\vect{x})}\), zero at that same value. It is non-negative because \(\vect{w}\) and \(\vect{x}\) are, so it is the best non-negative \(h\) too.

3. ★★★ Suppose \(\mat{W}\) and \(\mat{H}\) are positive and \({\mat{W}\mat{H} = \mat{X}}\) exactly. Show that both updates leave them unchanged. Then show that the converse fails: a fixed point of the updates need not have zero error.

Show solution

If \({\mat{W}\mat{H} = \mat{X}}\) then \({\mat{W}\T\mat{W}\mat{H} = \mat{W}\T\mat{X}}\), so every factor in the \(\mat{H}\) update is 1, and likewise \({\mat{W}\mat{H}\mat{H}\T = \mat{X}\mat{H}\T}\) for \(\mat{W}\). For the converse, run the updates on the corpus with \({q = 2}\): they stop changing at error 5.780, which is not zero (and cannot be, since no rank-2 product has error below 5.692). At such a point every positive entry has a zero gradient, which is a stationary point of the constrained problem, not an exact fit.

Summary card

Non-negative factors are parts that only add.

The anchor figure again: the sports and baking parts as word bars, and the seven documents as stacked bars of the amounts they take from each part, with d7 half and half.
ML03.7.2-F1

Sports and baking, found by the constraint.

  • Problem: minimise \({\norm{\mat{X} - \mat{W}\mat{H}}_F^2}\) with \({\mat{W}, \mat{H} \ge 0}\).
  • Updates: each entry of \(\mat{H}\) is multiplied by \({(\mat{W}\T\mat{X})}\) over \({(\mat{W}\T\mat{W}\mat{H})}\), and the twin for \(\mat{W}\).
  • Never unique: \({\mat{W}\mat{D}}\), \({\mat{D}^{-1}\mat{H}}\) fit as well; scale and match parts.

Sources and next steps

Sources. Each was opened and checked against this lesson on 15 November 2026.

  • D. D. Lee and H. S. Seung, Algorithms for Non-negative Matrix Factorization, NIPS 13 (2001). Section 1 contrasts PCA’s cancellations and clustering’s single prototypes with the parts representation of NMF; section 2 reads each column as a combination of the columns of \(\mat{W}\); Theorem 1 (equation 4) gives the updates; section 5 (equations 6 and 7) derives them as rescaled gradient descent; section 6 (Lemmas 1 and 2) gives the auxiliary-function proof.
  • scikit-learn, Non-negative matrix factorization, User Guide section 2.5.7: NNDSVDa fills zeros with the mean of the data and is preferred with the multiplicative solver, which cannot update zeros; that solver can minimise the Kullback-Leibler divergence.
  • scikit-learn, NMF: beta_loss is used only by the "mu" solver, and reconstruction_err_ is the Frobenius norm of \({\mat{X} - \mat{W}\mat{H}}\), not its square.

Next. ML03.7.3 Topics as mixtures: probabilistic LSA reads the factors as probabilities and fits them by EM.

This lesson unlocks

ML03.7.3 Topics as mixtures: probabilistic LSA

Your progress is saved in this browser only. No account, no tracking.
Back to top