Index Ai Academy
Phase 2 · Math, when you need it · Probability & statistics

Maximum likelihood

Choose the parameters that make the data most probable.

About 25 minutes · A free account opens the whole lesson

Create a free account Try part of it here

Already have an account? Sign in to open this lesson

Why it matters

Every model has settings, and someone has to choose them. The most common way to choose, in statistics and in machine learning, is this: pick the settings that make the data you actually saw as probable as possible. That's called maximum likelihood. You already use it when you work out a conversion rate as conversions ÷ visitors. A language model trained on the internet uses it too. Its training goal, making the cross-entropy loss small, is maximum likelihood in disguise.

What you'll be able to do

  • Define the likelihood of data under a model's parameters
  • Find the maximum-likelihood estimate by searching and by formula
  • Work with log-likelihoods instead of likelihoods
  • Explain why training a language model is maximum likelihood

What it covers

  1. Which setting explains what you saw?
  2. Work with the log instead
  3. Worked example: an email click rate
  4. The same trick for other models
  5. Training a language model is maximum likelihood

Which setting explains what you saw?

A friend flips a coin 10 times and gets 8 heads. Is it a fair coin? It could be. A fair coin does land 8 heads out of 10 now and then, about 4 times in 100. But a coin weighted to land heads 80% of the time gets that result about 30 times in 100. So the weighted coin is the better explanation of what you saw.

That's the whole idea of this lesson. You have some data. You have a model with a setting you can turn, like a dial. For each position of the dial, you ask: how probable would this exact data be? Then you pick the position that makes it most probable.

A tiny shop

Four people visit your online shop. The first three buy something. The fourth leaves without buying. Call the true chance that a visitor buys pp, the conversion rate. You don't know pp. You only know what happened.

Try a few guesses for pp. Assume each visitor decides independently, so you can multiply their chances. Each buyer contributes pp. The visitor who left contributes 1−p1 - p, the chance of not buying.

  • If p=0.5p = 0.5: 0.5 × 0.5 × 0.5 × 0.5 = 0.0625
  • If p=0.75p = 0.75: 0.75 × 0.75 × 0.75 × 0.25 ≈ 0.105
  • If p=0.9p = 0.9: 0.9 × 0.9 × 0.9 × 0.1 ≈ 0.073

The guess 0.75 explains the data best. It's also 3 out of 4, the share of visitors who bought. That's no accident, as you'll see below.

Each number in that list is a likelihood. It says how probable your data would be if that guess were true. The guess with the highest likelihood is the maximum-likelihood estimate, or MLE for short.

for p in [0.5, 0.75, 0.9]:
    likelihood = p * p * p * (1 - p)
    print(p, round(likelihood, 4))
It runs right here in your browser, with nothing to install.

Notice which way around this goes. The data stays fixed. Only the guess changes. A likelihood is not the chance that the guess is right. It's the chance of the data, if the guess were right.

The same idea with real numbers

Now a bigger shop. You saw 64 conversions from 2,000 visitors. If the conversion rate were pp, the chance of seeing exactly this data is:

L(p)=p64(1−p)1936L(p) = p^{64}(1 - p)^{1936}

Here L(p)L(p) is the likelihood of the rate pp. The small raised 64 means "multiply pp by itself 64 times", once for each buyer. The 1,936 counts the visitors who didn't buy (2,000 − 64).

In plain words: multiply in the chance of "bought" once for every buyer. Multiply in the chance of "didn't buy" once for every visitor who left. The result says how well the rate pp explains your data.

A rate of 0.01 gives a tiny likelihood: at that rate, 64 sales would be very unlikely. A rate of 0.5 gives a far tinier one, since you'd expect around 1,000 sales, not 64. Somewhere in between, the likelihood reaches a peak. The rate at that peak is the MLE.

Try it now

Slide the guess to find the top of the curve. It always peaks exactly at opens ÷ emails.

Quick check
Two visitors buy, then a third leaves without buying. What does this likelihood calculation print?
p = 0.5
print(p * p * (1 - p))
  1. 0.5
  2. 0.375
  3. 0.25
  4. 0.125
Show the answer

0.125

Two buyers give 0.5 × 0.5, and the visitor who left gives 1 − 0.5 = 0.5. So 0.5 × 0.5 × 0.5 = 0.125.

Work with the log instead

With 2,000 visitors, the likelihood is a product of 2,000 numbers below 1. You saw the problem in the lesson on exponentials and logarithms. The answer gets so small that the computer rounds it to zero. That's called underflow.

The fix is to take the log. The log turns multiplying into adding, so nothing shrinks to zero. And the log always goes up when its input goes up. So the peak stays at the same pp.

ℓ(p)=log⁡L(p)=64log⁡p+1936log⁡(1−p)\ell(p) = \log L(p) = 64 \log p + 1936 \log(1 - p)

The curly letter ℓ\ell (read "ell") stands for the log-likelihood. Here "log" means the natural log, np.log or math.log in code.

In plain words: add up log⁡p\log p once for each buyer. Add log⁡(1−p)\log(1 - p) once for each visitor who didn't buy. The bigger the total, the better pp explains the data. The total is always negative, so "bigger" means closer to zero.

Back to the tiny shop, with 3 buyers, 1 visitor who left, and p=0.75p = 0.75:

  • 3 × log 0.75 ≈ 3 × (−0.288) ≈ −0.863
  • 1 × log 0.25 ≈ −1.386
  • total ≈ −2.249

That's the log of the likelihood you found before, 0.105. Same information, written as a sum.

import math

p = 0.75
log_lik = 3 * math.log(p) + 1 * math.log(1 - p)
print(round(log_lik, 4))
print(round(math.log(p * p * p * (1 - p)), 4))

Both lines print −2.2493. Now the full shop with 2,000 visitors. The code below tries 600 rates between 0.01 and 0.07. It works out the log-likelihood of each one and keeps the best. (np.argmax gives the position of the largest value in a list.)

import numpy as np
import matplotlib.pyplot as plt

conversions, visitors = 64, 2000
p = np.linspace(0.01, 0.07, 600)
log_lik = conversions * np.log(p) + (visitors - conversions) * np.log(1 - p)

best = p[np.argmax(log_lik)]
plt.plot(p, log_lik)
plt.axvline(best, linestyle="--", color="gray")
plt.xlabel("conversion rate p")
plt.ylabel("log-likelihood")
print(f"MLE by search: {best:.4f}   conversions / visitors: {conversions / visitors:.4f}")

The curve is a hill. Its top sits at 64/2000=0.03264 / 2000 = 0.032, which is conversions ÷ visitors. The same holds for any rate: the MLE is successes divided by trials. Your everyday guess was maximum likelihood all along.

Go deeper Why the peak is always successes ÷ trials

At the top of a hill, the slope is zero. So find the derivative of ℓ(p)\ell(p) and set it to zero. The derivative of log⁡p\log p is 1/p1/p. The derivative of log⁡(1−p)\log(1 - p) is −1/(1−p)-1/(1 - p). That gives:

64p−19361−p=0\frac{64}{p} - \frac{1936}{1 - p} = 0

Read it as: "the pull up from the buyers equals the pull down from the visitors who left." Multiply both sides by p(1−p)p(1 - p) to get 64(1−p)=1936p64(1 - p) = 1936p. That tidies up to 64=2000p64 = 2000p, so p=64/2000=0.032p = 64 / 2000 = 0.032. With kk successes in nn trials, the same steps give p=k/np = k / n.

Quick check
A grid search finds that the log-likelihood peaks at p = 0.032. Where does the plain likelihood L(p) peak?
  1. At a slightly larger p, because logs shrink numbers
  2. At log(0.032)
  3. At the same place, p = 0.032
  4. It has no peak, because it underflows
Show the answer

At the same place, p = 0.032

The log always rises when its input rises, so it never moves the peak. Taking logs only avoids underflow and turns products into sums.

Worked example

Worked example: an email click rate

You send an email to 20 people and 3 of them click the link. Try five possible click rates and find the one with the highest log-likelihood.

import math

clicks, sent = 3, 20     # 3 people clicked out of 20 emails sent

for p in [0.05, 0.10, 0.15, 0.20, 0.30]:
    log_lik = clicks * math.log(p) + (sent - clicks) * math.log(1 - p)
    print(p, round(log_lik, 3))
In the lesson you can change this and run it.

Each line adds log p once per click and log(1 − p) once per person who didn't click. The best total is −8.454, at p = 0.15. That's 3 ÷ 20, the share who clicked. Rates either side score worse: −8.699 at 0.1 and −8.622 at 0.2. The numbers rise to a peak and fall away again, like the hill in the chart above.

The same trick for other models

Every model below has its own setting to estimate. In each case, maximum likelihood gives an answer you may already have guessed. A small "hat" on a letter, as in p^\hat{p} (read "p-hat"), means "the estimate worked out from the data".

ModelDataMaximum-likelihood estimate
Bernoulli (convert or not)k successes in np^=k/n\hat{p} = k / n
Poisson (orders per hour)counts x1…xnx_1 \ldots x_nλ^\hat{\lambda} = their average
Normalvalues x1…xnx_1 \ldots x_nμ^\hat{\mu} = mean, σ^2\hat{\sigma}^2 = average squared deviation (divide by nn)
Linear regression with normal noise(x, y) pairsthe least-squares fit

Here's each row in plain words:

  • Bernoulli is one yes-or-no try per visitor, like the shop. The best rate is the share of yeses.
  • Poisson models counts in a fixed window, like orders per hour. Its setting is λ\lambda (lambda), the average rate. The best estimate is the plain average of your counts.
  • Normal is the bell curve. Its middle, μ\mu (mu), is estimated by the mean. Its spread, the variance σ2\sigma^2 (sigma squared), is estimated by the average squared distance from the mean. Maximum likelihood divides by nn, the number of values, not by n−1n - 1.
  • Linear regression draws the best straight line through a cloud of points. You'll meet it in Phase 3. "Least squares" means choosing the line that makes the squared misses as small as possible.
Quick check
A shop saw 30 buyers in 200 visits. What's the maximum-likelihood estimate of its buy rate?
print(30 / 200)
  1. 6.67
  2. 0.2
  3. 0.15
  4. 0.3
Show the answer

0.15

30 / 200 is 0.15. For yes-or-no data, the rate that best explains what you saw is the share of yeses.

That last row explains why least squares is the default for drawing a line. If the noise around the line follows a bell curve, the least-squares line is the maximum-likelihood line.

Go deeper Why least squares is maximum likelihood

Recall the height of the bell curve from the normal distribution lesson. Its main part is e−(x−μ)2/(2σ2)e^{-(x - \mu)^2 / (2\sigma^2)}. Take the log and that part becomes −(x−μ)2/(2σ2)-(x - \mu)^2 / (2\sigma^2), plus a number that doesn't depend on μ\mu. For a line, xx is a point's real value and μ\mu is the line's prediction for it. So x−μx - \mu is that point's miss.

Read it as: "the log-likelihood of one point is minus its squared miss, scaled down." Add this up over all points. Making the total as large as possible is the same as making the sum of squared misses as small as possible. That's least squares.

Quick check
A Poisson model for support tickets per day is fit to 5 days with 3, 5, 4, 6 and 2 tickets. What's the maximum-likelihood estimate of the daily rate?
  1. 4
  2. 20
  3. 6
  4. 5
Show the answer

4

For a Poisson model the MLE of λ is the average count: 20 / 5 = 4.

Training a language model is maximum likelihood

A language model reads text one token at a time. A token is a word or a piece of a word. At each position, the model gives a probability to every possible next token. Its parameters are all the numbers inside it that training adjusts. Together, they're written θ\theta (theta).

Think back to the shop. There, you multiplied one probability per visitor. Here, you multiply one probability per token: the probability the model gave to the token that actually came next. That product is the likelihood of the training text. Training looks for the θ\theta that makes it as large as possible. In logs, the goal is:

max⁡θ∑tlog⁡Pθ(tokent∣tokens before t)\max_\theta \sum_{t} \log P_\theta(\text{token}_t \mid \text{tokens before } t)

Take it one piece at a time:

  • Pθ(…)P_\theta(\ldots) is the probability the model, with parameters θ\theta, gives to the token at position tt. The bar ∣\mid reads "given", as in the conditional probability lesson.
  • ∑t\sum_t (a capital sigma) means "add up over every position tt".
  • max⁡θ\max_\theta means "find the parameters that make this total as large as possible".

In plain words: at every position in the training text, take the log of the probability the model gave to the token that really came next. Add them all up. Training adjusts the model to make that total as big as it can.

Now flip the sign and take the average instead of the total. You get the average negative log-likelihood, which is the training loss. The cross-entropy lesson, coming up soon, shows this is the same as cross-entropy loss. Gradient descent pushes the loss down. That's the same as pushing the likelihood up.

A small example. Say a model gives the real next tokens probabilities 0.5 and 0.25:

  • log-likelihood: log 0.5 + log 0.25 ≈ −0.693 + (−1.386) ≈ −2.079
  • average loss: flip the sign and divide by 2 tokens, ≈ 1.040

The code does the same for a five-token sentence and two models.

import numpy as np

# Probabilities a model gave to the tokens that actually came next in one sentence
probs_good = np.array([0.6, 0.8, 0.4, 0.7, 0.9])
probs_bad = np.array([0.1, 0.3, 0.05, 0.2, 0.4])
for name, p in [("good model", probs_good), ("weak model", probs_bad)]:
    print(f"{name}: log-likelihood {np.log(p).sum():.2f}, average loss {-np.log(p).mean():.3f}")

The good model scores a log-likelihood of −2.11 and an average loss of 0.422. The weak model scores −9.03 and 1.806. Higher likelihood, lower loss: they're the same statement made two ways.

Quick check
On the same text, model A has an average loss of 0.4 and model B has an average loss of 1.2. Which model gives the text the higher likelihood?
  1. Model A
  2. They're equal, because loss and likelihood measure different things
  3. Model B
  4. You can't tell without the gradients
Show the answer

Model A

The average loss is the average negative log-likelihood. Lower loss means the model gave the real next tokens higher probabilities, so higher likelihood.

Practice what you just read

  • 5 code examples you can edit and run
  • a practice exercise that checks your code
  • a 5-question quiz
  • 5 review cards for spaced repetition

Create a free account

Try a quiz question

What is the likelihood, in maximum likelihood estimation?

  1. The probability of the observed data, seen as a function of the parameters
  2. The probability that the parameters are correct, given the data you saw
  3. The number of observations that fit the model, out of all that you have
  4. The average of the data, weighted by how probable each observation is

Answer it at the end of the lesson to see if you're right, and why.

Before this lesson