Skip to main content

Topics as mixtures: probabilistic LSA

Read a factorisation as probabilities: a document picks a topic, the topic picks a word. Fit both tables by EM exactly as for a Gaussian mixture, work two iterations by hand, and see why the model is NMF with the Kullback-Leibler loss.
ML03.7.3L2 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.2 Non-negative matrix factorisation ML03.4 Gaussian mixtures and the EM algorithm

What you will be able to do
  • Write the probabilistic LSA model P(w | d) as a sum over topics and as a product of two probability tables.
  • Derive the E-step responsibilities and the M-step updates from expected counts, with Lagrange multipliers.
  • Carry out two EM iterations by hand and confirm that the log-likelihood rises.
  • Show that maximising the pLSA likelihood is minimising NMF’s Kullback-Leibler divergence, and explain why pLSA overfits.

The question

NMF said that d7, “team bake ball flour”, takes about 2.3 words from a sports part and 2.3 from a baking part. But 2.3 of what, and how sure is it? If a topic is a probability distribution over words and a document a probability distribution over topics, the corpus gets a likelihood, and the whole toolkit of maximum likelihood and EM from the Gaussian mixtures of ML03.4 applies.

From the last lesson

1. Write the multiplicative update for \(\mat{H}\) in NMF and say why it keeps entries non-negative.

Show answer

\({\mat{H} \leftarrow \mat{H} \circ (\mat{W}\T\mat{X}) / (\mat{W}\T\mat{W}\mat{H})}\). Each entry is multiplied by a ratio of non-negative numbers, so it cannot change sign.

2. Two NMF runs give different \(\mat{W}\). Name two reasons that do not mean either is wrong.

Show answer

Scaling (\({\mat{W}\mat{D}}\) with \({\mat{D}^{-1}\mat{H}}\) has the same product) and the order of the parts. Different starts can also reach different local minima.

Intuition

Tell a story of how each word of a document was written. The document has its own topic shares, \({P(k \mid d)}\). For each word, it first picks a topic \(k\) with those shares, and the topic then picks a word \(w\) with its own word probabilities \({P(w \mid k)}\).

A tree diagram. A blue box document d7 on the left branches by two vermillion arrows, each labelled P(k | d7) = 0.5, to a blue box sports topic and a sky-blue box baking topic. From sports topic four thin blue arrows lead to the words team 5/14, ball 4/14, goal 3/14 and match 2/14; from baking topic four thin sky-blue arrows lead to bake 5/14, flour 4/14, oven 3/14 and sugar 2/14. The heading over the word probabilities reads P(w | k). On the right: P(team | d7) = 0.5 times 5/14 plus 0.5 times 0 = 0.179.
ML03.7.3-F1

How pLSA explains a word of d7. The document picks a topic, half and half, and the topic picks a word. These are the fitted values on the corpus.

This is probabilistic latent semantic analysis (pLSA), Hofmann’s aspect model. The topic is latent: we see the words, never the topic that chose them. To find the probability of one word in d7, add up the routes to it. “Team” can only come from the sports topic, so \(P(\text{team} \mid d_7) = {0.5 \times 5/14} + {0.5 \times 0} = 0.179\).

Build it up

Step 1. One word, two routes. By the rule of total probability, summing over the topic,

\[ \cmodel{P(w \mid d)} = \sum_{k=1}^{K} \cparam{P(k \mid d)}\; \cparam{P(w \mid k)} . \]

Step 2. It is a matrix product. Put the word probabilities of the topics into a \({V \times K}\) matrix and the topic shares of the documents into a \({K \times D}\) matrix. Then the table of \({P(w \mid d)}\) is their product, and every column of all three tables sums to 1. This is NMF with probability columns.

Two bar charts over the eight words bake, ball, flour, goal, match, oven, sugar, team. Left, titled Two topics: P(w | k): hatched sky-blue bars for the baking topic, tallest for bake at about 0.36, and solid blue bars for the sports topic, tallest for team at about 0.36. Right, titled d7: half of each: the same bars at half height stacked into one distribution, with short ink-coloured lines at 0.25 over bake, ball, flour and team, and the note short lines: d7's own shares, 1/4 each.
ML03.7.3-F2

\({P(w \mid d_7)}\) is half of each topic’s distribution. It cannot match d7’s own shares of 1/4 exactly, because both topics must also explain the other six documents.

Step 3. The likelihood. If word \(w\) occurs \({n(d, w)}\) times in document \(d\), the log-likelihood of the corpus is

\[ \begin{aligned} \ell = \sum_{d}\sum_{w} n(d, w)\, \ln \sum_{k} &P(k \mid d) \\ \times\, &P(w \mid k) . \end{aligned} \]

Step 4. A logarithm of a sum. Setting the derivatives of \(\ell\) to zero gives no closed form, for the same reason as in a Gaussian mixture: the logarithm sits outside the sum over the latent topic. EM gets round it. If we knew which topic wrote each word, counting would do; since we do not, we count with probabilities.

The formal statement

NoteEM for pLSA

E-step. For every document \(d\) and word \(w\) with \({n(d, w) > 0}\), the responsibility of topic \(k\) is

\[ r_{dwk} = \frac{P(k \mid d)\,P(w \mid k)}{\sum_{j} P(j \mid d)\,P(w \mid j)} . \]

M-step. With the expected counts \({n(d, w)\, r_{dwk}}\),

\[ \begin{aligned} P(w \mid k) &= \frac{\sum_d n(d, w)\, r_{dwk}}{\sum_{w'}\sum_d n(d, w')\, r_{dw'k}}, \\ P(k \mid d) &= \frac{\sum_w n(d, w)\, r_{dwk}}{n_d} , \end{aligned} \]

where \({n_d = \sum_w n(d, w)}\) is the length of document \(d\). Each iteration leaves \(\ell\) the same or higher.

The E-step is Bayes’ rule. Given that the word in \(d\) is \(w\), the probability that topic \(k\) wrote it is the prior share \({P(k \mid d)}\) times the likelihood \({P(w \mid k)}\), divided by the total \({P(w \mid d)}\).

The M-step, derived. Fix the responsibilities, and write \({c_{dwk} = n(d, w)\,r_{dwk}}\) for the expected number of times word \(w\) in document \(d\) was written by topic \(k\). EM maximises the expected log-likelihood of the words and their topics,

\[ \begin{aligned} Q = \sum_{d, w, k} c_{dwk}\,\big[&\ln P(k \mid d) \\ + &\ln P(w \mid k)\big], \end{aligned} \]

subject to \({\sum_w P(w \mid k) = 1}\) for each \(k\). Add a Lagrange multiplier \(\lambda_k\) for each constraint,

\[ \begin{aligned} \mathcal{L} = Q &- \sum_k \lambda_k \\ &\times \Big(\sum_{w'} P(w' \mid k) - 1\Big), \end{aligned} \]

and differentiate with respect to one word probability. Only the terms of \(Q\) that contain \({\ln P(w \mid k)}\) depend on it:

\[ \pd{\mathcal{L}}{P(w \mid k)} = \frac{\sum_d c_{dwk}}{P(w \mid k)} - \lambda_k . \]

Setting it to zero gives \({P(w \mid k) = \sum_d c_{dwk} / \lambda_k}\). Summing over \(w\) and using the constraint, \({\lambda_k = \sum_{w, d} c_{dwk}}\): the expected number of words written by topic \(k\). The same steps with the constraint \({\sum_k P(k \mid d) = 1}\) give a multiplier \(\sum_{k, w} c_{dwk} = n_d\), because the responsibilities of each word sum to 1. That the likelihood never falls is the general EM argument of ML03.4.3 (a lower bound that the E-step makes tight and the M-step raises).

The link to NMF. Lee and Seung’s second loss for NMF is the generalised Kullback-Leibler divergence

\[ \begin{aligned} D(\mat{X} \,\|\, \mat{W}\mat{H}) = \sum_{w,d} \Big(&x_{wd}\ln\frac{x_{wd}}{y_{wd}} \\ &- x_{wd} + y_{wd}\Big), \end{aligned} \]

where \({y_{wd} = (\mat{W}\mat{H})_{wd}}\).

Take \({w_{wk} = P(w \mid k)}\) and \({h_{kd} = n_d\,P(k \mid d)}\). Then \({(\mat{W}\mat{H})_{wd} = n_d\,P(w \mid d)}\), and since each \({P(\cdot \mid d)}\) sums to 1, the product’s entries add up to \({\sum_d n_d}\), the same total as \(\mat{X}\). The last two terms cancel, and

\[ \begin{aligned} D &= \sum_{w,d} x_{wd}\ln x_{wd} \\ &\quad - \sum_{w,d} x_{wd}\ln\big(n_d\,P(w \mid d)\big) \\ &= c - \ell , \end{aligned} \]

where \({c = \sum_{w,d} x_{wd}\ln x_{wd} - \sum_d n_d \ln n_d}\) is fixed by the data. (The second line splits the logarithm of a product, and \({\sum_w x_{wd} = n_d}\).)

So minimising the divergence over such factors is maximising the pLSA likelihood. On the corpus, the KL-loss NMF of the last lesson split d7 into 2 and 2 words; pLSA gives it shares 0.5 and 0.5.

Worked example

Two EM iterations on the small piece. Words ball, team, bake, flour; documents d2 = (1, 2, 0, 0), d5 = (0, 0, 2, 1) and d7 = (1, 1, 1, 1). Start with topic 1 leaning to sport, \({P(w \mid 1) = (0.4, 0.3, 0.2, 0.1)}\), topic 2 the reverse, \({(0.1, 0.2, 0.3, 0.4)}\), and every document at \({P(k \mid d) = 0.5}\). Then \({P(w \mid d) = 0.25}\) for every word, and \({\ell = 10\ln 0.25 = -13.863}\).

Three columns titled start, after 1 iteration, after 2 iterations. Top row: paired bars of P(w | k) for ball, team, bake, flour, solid for the sports topic and hatched for the baking topic: start 0.4, 0.3, 0.2, 0.1 and 0.1, 0.2, 0.3, 0.4; after one iteration 0.32, 0.36, 0.24, 0.08 and 0.08, 0.24, 0.36, 0.32; after two 0.34, 0.42, 0.18, 0.06 and the reverse. Bottom row: stacked bars of P(k | d) for d2, d5, d7: 0.50, 0.50, 0.50 at the start, then 0.67, 0.33, 0.50, then 0.80, 0.20, 0.50. Under each column the log-likelihood: minus 13.863, minus 13.039, minus 12.126.
ML03.7.3-F3

Two EM iterations. The topics sharpen, d2 and d5 move towards their own topic, d7 stays at one half, and the log-likelihood climbs.

Iteration 1, E-step. All shares are 0.5, so they cancel and the responsibility of topic 1 is \({P(w \mid 1) / (P(w \mid 1) + P(w \mid 2))}\): 0.8 for ball, 0.6 for team, 0.4 for bake, 0.2 for flour.

Iteration 1, M-step. Expected counts for topic 1: ball \({0.8 + 0.8 = 1.6}\) (once in d2, once in d7), team \({2(0.6) + 0.6 = 1.8}\), bake \({2(0.4) + 0.4 = 1.2}\), flour \({0.2 + 0.2 = 0.4}\), in all 5.0. So \({P(w \mid 1) = (0.32, 0.36, 0.24, 0.08)}\), and by the same counts with \({1 - r}\), \({P(w \mid 2) = (0.08, 0.24, 0.36, 0.32)}\). The shares are each document’s topic-1 count over its length:

\[ \begin{aligned} P(1 \mid d_2) &= \tfrac{0.8 + 1.2}{3} = 0.667, \\ P(1 \mid d_5) &= \tfrac{0.8 + 0.2}{3} = 0.333, \\ P(1 \mid d_7) &= \tfrac{0.8 + 0.6 + 0.4 + 0.2}{4} = 0.5 . \end{aligned} \]

The log-likelihood is now \(-13.039\).

Iteration 2, E-step. The shares no longer cancel. For ball in d2,

\[ \begin{aligned} r &= \frac{\tfrac23 (0.32)}{\tfrac23 (0.32) + \tfrac13 (0.08)} \\ &= \frac{0.2133}{0.24} = 0.889 , \end{aligned} \]

and in the same way 0.75 for team in d2, 0.25 for bake and 0.111 for flour in d5. In d7 the shares are still equal, so its responsibilities stay 0.8, 0.6, 0.4, 0.2.

Iteration 2, M-step. Topic 1’s counts are ball \({0.889 + 0.8 = 1.689}\), team \({2(0.75) + 0.6 = 2.1}\), bake \({2(0.25) + 0.4 = 0.9}\), flour \({0.111 + 0.2 = 0.311}\), again 5.0 in all, so \({P(w \mid 1) = (0.338, 0.42, 0.18, 0.062)}\). The shares become 0.796 for d2, 0.204 for d5 and still 0.5 for d7, and \({\ell = -12.126}\). Run on, the piece settles with d2 and d5 each in one topic and d7 shared equally, at \({\ell = -9.503}\).

Code

From scratch on the whole corpus: EM from several random starts.

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()})
N = np.array([[d.split().count(w) for d in docs] for w in words], dtype=float)   # n(d, w), words x docs

def plsa(N, K, steps, seed):
    rng = np.random.default_rng(seed)
    Pwk = rng.uniform(size=(N.shape[0], K))
    Pwk /= Pwk.sum(axis=0)                                  # P(w | k): columns sum to 1
    Pkd = np.full((K, N.shape[1]), 1 / K)                   # P(k | d): columns sum to 1
    for _ in range(steps):
        ratio = np.divide(N, Pwk @ Pkd, out=np.zeros_like(N), where=N > 0)
        counts = Pwk[:, :, None] * Pkd[None, :, :] * ratio[:, None, :]   # n(d,w) r_dwk
        Pwk = counts.sum(axis=2) / counts.sum(axis=(0, 2))
        Pkd = counts.sum(axis=0) / N.sum(axis=0)
    loglik = (N * np.log(np.where(N > 0, Pwk @ Pkd, 1))).sum()
    return Pwk, Pkd, loglik

runs = [plsa(N, 2, 500, seed) for seed in range(5)]
Pwk, Pkd, loglik = runs[0]
sport = int(np.argmax(Pwk[words.index("team")]))
print("log-likelihoods:", [round(float(r[2]), 3) for r in runs])
print("sports topic x 14:", {w: round(float(v), 2) for w, v in zip(words, 14 * Pwk[:, sport])})
print("d7's topic shares:", Pkd[:, 6].round(4))
log-likelihoods: [-40.117, -40.117, -40.117, -40.117, -40.117]
sports topic x 14: {'bake': 0.0, 'ball': 4.0, 'flour': 0.0, 'goal': 3.0, 'match': 2.0, 'oven': 0.0, 'sugar': 0.0, 'team': 5.0}
d7's topic shares: [0.5 0.5]
Two line charts against EM iterations 0 to 40 for six random starts. Left, titled Log-likelihood: six vermillion curves start between about minus 69 and minus 59, rise steeply in the first ten iterations and all level off at a dashed line labelled all reach minus 40.117. Right, titled d7's share of the sports topic: six curves start at 0.5, wander between about 0.1 and 0.7 in the first ten iterations and all settle at 0.5, labelled every start ends at 0.5.
ML03.7.3-F4

EM on the whole corpus from six random starts. The log-likelihood only rises and every start reaches the same maximum, where d7 is shared equally.

Each topic has 14 words’ worth of mass: the 12 words of its three documents plus two of d7’s four. The same answer comes from NMF with the Kullback-Leibler loss, once its parts are scaled to sum to 1:

from sklearn.decomposition import NMF

kl = NMF(n_components=2, init="nndsvda", beta_loss="kullback-leibler", solver="mu",
         max_iter=5000, tol=1e-12, random_state=0).fit(N.T)
parts = (kl.components_ / kl.components_.sum(axis=1, keepdims=True)).T   # words x 2
order = [int(np.argmax(parts[words.index("team")])), int(np.argmax(parts[words.index("bake")]))]
print("largest gap to pLSA's topics:",
      np.abs(parts[:, order] - Pwk[:, [sport, 1 - sport]]).max().round(4))
largest gap to pLSA's topics: 0.0

Explore

The module’s interactive, the factor explorer, sits in lesson ML03.7.2. Run NMF at rank 2 and compare its parts with the topics above: the same words lead each one.

Pitfalls

Two stacked bar charts of topic shares for documents d1 to d7, solid for sports and hatched for baking. Left, marked with a cross and titled One topic per document: d1, d2, d3 and d7 are all sports and d4, d5, d6 all baking, with log-likelihood minus 42.383 below. Right, marked with a tick and titled A mix per document: the same, except that d7 is half sports and half baking, with log-likelihood minus 40.117 below.
ML03.7.3-F5

Wrong beside right. If each document must come from one topic, d7’s baking words have to be explained by the sports topic. Letting each document mix topics fits better.

“A topic model is a clustering of documents.”

A clustering gives each document one group, so all its words come from one distribution. pLSA gives each word its own topic, and a document a mixture. Hofmann draws exactly this line between his aspect model and clustering models. On the corpus the best one-topic-per-document fit has log-likelihood \(-42.383\); the mixture reaches \(-40.117\) (it also has seven more parameters, the shares).

“pLSA can score a new document.”

\({P(k \mid d)}\) exists only for the documents it was trained on: \(d\) is an index into the training set. Blei, Ng and Jordan point out that pLSA is therefore not a generative model of documents, and that its \({KV + KD}\) parameters grow with the number of documents, which invites overfitting. To use it on a new document one must fit that document’s shares with the topics frozen, on the very words one wanted to score. The next lesson repairs this with a prior on the shares.

“EM found the topics, so they are the best ones.”

EM climbs to a local maximum. On this tiny corpus every start reaches \(-40.117\), but on real text different starts give different topics; run several and keep the highest likelihood.

Check yourself

Recall

1. Write \({P(w \mid d)}\) for pLSA.

Show answer

\({P(w \mid d) = \sum_k P(k \mid d)\,P(w \mid k)}\).

2. What is the E-step responsibility \({r_{dwk}}\)?

Show answer

Bayes’ rule for the topic of word \(w\) in \(d\):

\[ r_{dwk} = \frac{P(k \mid d)\,P(w \mid k)}{\sum_j P(j \mid d)\,P(w \mid j)} . \]

3. How does the M-step re-estimate \({P(k \mid d)}\)?

Show answer

As the expected number of words of \(d\) written by topic \(k\), \({\sum_w n(d, w)\,r_{dwk}}\), divided by the length \(n_d\).

4. Which NMF loss matches the pLSA likelihood, and how are the factors related?

Show answer

The generalised Kullback-Leibler divergence, with \({w_{wk} = P(w \mid k)}\) and \({h_{kd} = n_d\,P(k \mid d)}\).

5. What are the fitted topic shares of d7 on the corpus, and why?

Show answer

0.5 and 0.5. Two of its four words (team, ball) only occur in the sports topic and two (bake, flour) only in the baking topic.

Exercises

1. ★ With the fitted corpus model (d1 entirely sports; sports topic ball 4/14, goal 3/14, match 2/14, team 5/14), find \({P(w \mid d_1)}\) for each of d1’s words and the log-likelihood of d1, “ball goal team goal”.

Show solution

\({P(\text{ball} \mid d_1) = 4/14}\), \({P(\text{goal} \mid d_1) = 3/14}\), \({P(\text{team} \mid d_1) = 5/14}\). The log-likelihood is

\[ \begin{aligned} &\ln\tfrac{4}{14} + 2\ln\tfrac{3}{14} + \ln\tfrac{5}{14} \\ &\quad= -1.253 - 3.081 - 1.030 \\ &\quad= -5.363 . \end{aligned} \]

2. ★★ In the worked example after iteration 1, compute the responsibility of topic 1 for “team” in d2 and for “bake” in d5 (the values 0.75 and 0.25 used in iteration 2).

Show solution

In d2 the shares are \({(2/3, 1/3)}\) and team has \({P(\text{team} \mid k) = (0.36, 0.24)}\):

\[ \begin{aligned} r &= \frac{\tfrac23(0.36)}{\tfrac23(0.36) + \tfrac13(0.24)} \\ &= \frac{0.24}{0.32} = 0.75 . \end{aligned} \]

In d5 the shares are \({(1/3, 2/3)}\) and bake has \({(0.24, 0.36)}\): \({r = 0.08/(0.08 + 0.24) = 0.25}\).

3. ★★★ Count the free parameters of pLSA with \(K\) topics, \(V\) words and \(D\) documents, and evaluate it for the corpus with \({K = 2}\). Compare with the number of words in the corpus.

Show solution

Each topic is a distribution over \(V\) words, with \({V - 1}\) free numbers; each document’s shares have \({K - 1}\). In all \({K(V - 1) + D(K - 1)}\). For the corpus, \({2 \times 7 + 7 \times 1 = 21}\) parameters for only 28 words. The second term grows with every new document, which is the overfitting that Blei, Ng and Jordan describe (they count \({KV + KD}\), without removing the sum-to-one constraints).

Summary card

A document picks a topic, the topic picks a word.

The anchor figure again: document d7 branching with probability 0.5 to a sports topic and a baking topic, each branching to its four words with probabilities in fourteenths, and P(team | d7) = 0.179.
ML03.7.3-F1

Shares times word probabilities.

  • Model: \(P(w \mid d) = \sum_k {P(k \mid d)\,P(w \mid k)}\).
  • E-step: \({r_{dwk} \propto P(k \mid d)\,P(w \mid k)}\). M-step: re-normalise the expected counts \({n(d, w)\,r_{dwk}}\).
  • Same as NMF with the Kullback-Leibler loss; but no shares for unseen documents.

Sources and next steps

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

  • T. Hofmann, Probabilistic Latent Semantic Analysis, UAI 1999. Section 3.1, equation 1: \({P(w \mid d) = \sum_z P(w \mid z) P(z \mid d)}\); section 3.2, equations 3 to 6: the E-step and the M-step proportional to expected counts (written there for the equivalent form \({P(z)\,P(d \mid z)\,P(w \mid z)}\), eq. 2); section 3.3: pLSA as a matrix product compared with LSA; section 3.5: aspects against clusters.
  • D. M. Blei, A. Y. Ng and M. I. Jordan, Latent Dirichlet Allocation, JMLR 3 (2003), 993 to 1022. Section 4.3: \(d\) is a dummy index into the training set, so pLSI is not a well-defined generative model of documents, and its \({kV + kM}\) parameters grow linearly with the number of documents.
  • D. D. Lee and H. S. Seung, Algorithms for Non-negative Matrix Factorization, NIPS 13 (2001). Equation 3 defines the divergence \({D(A \| B)}\) used above.

Next. ML03.7.4 Latent Dirichlet allocation puts a Dirichlet prior on the topic shares, so that every document, old or new, is generated by the model.

This lesson unlocks

ML03.7.4 Latent Dirichlet allocation

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