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

Mean, variance and spread

Expected value, variance and standard deviation.

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

The expected value is the average you'd get over many tries. AI work is full of them: expected revenue per visitor, or expected reward in reinforcement learning, where a program learns by trial and error. Training a model means making its expected loss as small as possible. The loss is a score for how wrong the model is on one example. The expected loss is its average over many examples. Variance measures how far single results scatter around the average. It's what separates a steady channel from a lottery ticket, and a calm training run from a noisy one.

What you'll be able to do

  • Compute an expected value as a probability-weighted average
  • Measure spread with variance and standard deviation
  • Use the rules for scaling and adding random variables
  • Compare options with the same average but different risk

What it covers

  1. The average you'd expect
  2. Same average, very different ride
  3. Worked example: two channels with the same average
  4. From real data: sample mean and variance
  5. Shortcuts: shifting and scaling
  6. Adding random amounts together

The average you'd expect

Roll a die many times and write down each result. Then average them. You'll get close to 3.5.

Here's why. Each face from 1 to 6 comes up about one time in six. So the long-run average is (1 + 2 + 3 + 4 + 5 + 6) ÷ 6, which is 21 ÷ 6 = 3.5. No die ever shows 3.5. The average doesn't have to be a result that can actually happen.

This long-run average is called the expected value, or the mean. It works for any random variable: a number that comes out of a random process. You met these in the last lesson.

When outcomes aren't equally likely, you weight each one by its chance. Here's a shop example. A visitor to your online store buys something with probability 0.03, which is 3%. A buyer spends $80. Everyone else spends nothing. What is one visitor worth?

  • 3% of visitors spend $80: 0.03 × 80 = $2.40.
  • 97% spend $0: 0.97 × 0 = $0.
  • Add the two: $2.40 per visitor.

So 10,000 visitors are worth about $24,000. That also tells you the most you should pay for each visitor. Notice that no single visitor spends $2.40. Each one spends $80 or nothing.

In math, the recipe looks like this:

E[X]=∑xx⋅P(X=x)\mathbb{E}[X] = \sum_x x \cdot P(X = x)

Here is each piece:

  • XX is the random variable, such as "what one visitor spends".
  • E[X]\mathbb{E}[X] means "the expected value of X". The E stands for "expected".
  • Small xx stands for one particular value that X can take.
  • P(X=x)P(X = x) is the chance that X comes out as that value.
  • The big Greek letter ∑\sum (sigma) means "add up". The xx under it says "for every possible value".

In plain words: take each possible value, multiply it by its chance, and add up the results.

Here is the visitor example in that notation:

E[revenue per visitor]=0.03×80+0.97×0=$2.40\mathbb{E}[\text{revenue per visitor}] = 0.03 \times 80 + 0.97 \times 0 = \$2.40

In Python, the ∑\sum becomes a loop that adds as it goes:

values = [80, 0]      # what one visitor spends
probs = [0.03, 0.97]  # how likely each amount is
print(sum(v * p for v, p in zip(values, probs)))
It runs right here in your browser, with nothing to install.

It prints 2.4. zip pairs each value with its chance. Then sum adds up the products.

Quick check
What does this print?
outcomes = [(10, 0.2), (0, 0.8)]
print(sum(x * p for x, p in outcomes))
  1. 5.0
  2. 2.0
  3. 10
  4. 0.2
Show the answer

2.0

10 × 0.2 is 2.0 and 0 × 0.8 is 0, so the total is 2.0. Each outcome counts in proportion to its chance. You'd never see exactly 2, but that's the long-run average.

Quick check
A raffle ticket wins $50 with probability 0.1. Otherwise it wins nothing. What are the expected winnings per ticket?
  1. $5
  2. $50
  3. $0
  4. $45
Show the answer

$5

Multiply each prize by its chance and add: 0.1 × 50 + 0.9 × 0 = $5. No ticket ever wins exactly $5. It's the long-run average.

Same average, very different ride

Picture two ways to get to work. Both take 30 minutes on average. The bus takes 28 to 32 minutes every day. The car takes 15 minutes on a clear day and 60 in a jam. The averages match, but only one lets you plan your morning.

The average alone can't tell these apart. You need a second number that measures spread: how far single results tend to land from the average. The recipe has three steps.

  1. Find how far each value is from the mean. This gap is called the deviation.
  2. Square each gap, which means multiply it by itself. This makes every gap positive. Without it, gaps above and below the mean would cancel each other out.
  3. Take the weighted average of those squares, using the same chances as before.

The result is the variance. Because of the squaring, it's in odd units like "squared dollars". So you usually take its square root: the number that, times itself, gives the variance. For example, the square root of 25 is 5. That square root is the standard deviation. It's back in the original units, like dollars or minutes. Think of it as "the typical distance from the average".

Two more Greek letters help here. μ\mu (mu, said "mew") is the mean. σ\sigma (a small sigma) is the standard deviation. It's a different letter from the big ∑\sum that means "add up".

Var⁡(X)=E[(X−μ)2]σ=Var⁡(X)\operatorname{Var}(X) = \mathbb{E}\big[(X - \mu)^2\big] \qquad \sigma = \sqrt{\operatorname{Var}(X)}

In plain words: the variance is the average squared distance from the mean. The standard deviation is its square root, so it's in the same units as the data.

A worked example: a coin game pays $0 on tails and $10 on heads. The mean is $5. Both outcomes are $5 away from it. Squared, each gap is 25. The weighted average is 0.5 × 25 + 0.5 × 25 = 25. So the variance is 25, and the standard deviation is the square root of 25, which is $5. That matches your gut: every result is $5 from the average.

values = [0, 10]
probs = [0.5, 0.5]
mean = sum(v * p for v, p in zip(values, probs))
var = sum((v - mean) ** 2 * p for v, p in zip(values, probs))
print(mean, var, var ** 0.5)

It prints 5.0 25.0 5.0: the mean, the variance and the standard deviation. In Python, ** 0.5 takes a square root.

Now a real choice. You have two campaign options. "Steady" earns $9,000, $10,000 or $11,000, with chances 25%, 50% and 25%. "Moonshot" earns $0 (60% of the time), $10,000 (25%) or $40,000 (15%). The code below does the same three steps with NumPy. NumPy multiplies arrays item by item, so d["values"] * d["probs"] multiplies each value by its chance in one go.

import numpy as np

# Two campaign options: revenue outcomes and their probabilities
steady = {"values": np.array([9_000, 10_000, 11_000]), "probs": np.array([0.25, 0.5, 0.25])}
moonshot = {"values": np.array([0, 10_000, 40_000]), "probs": np.array([0.6, 0.25, 0.15])}

for name, d in [("steady", steady), ("moonshot", moonshot)]:
    mean = np.sum(d["values"] * d["probs"])
    var = np.sum((d["values"] - mean) ** 2 * d["probs"])
    print(f"{name:<9} expected = {mean:>8,.0f}   std = {np.sqrt(var):>8,.0f}")

Steady expects $10,000, with a standard deviation of about $707. Moonshot expects $8,500. That's close enough to be tempting. But its standard deviation is about $13,883, nearly twenty times larger. Most of the time it earns nothing. Whether that's acceptable is a business decision. The numbers make the trade-off plain to see.

Go deeper Why square the gaps?

You could drop the minus signs and average the plain distances instead. That measure exists. It's called the mean absolute deviation. Squaring is the standard choice for two reasons. First, it makes the rules later in this lesson come out neatly: for independent amounts, variances add. Second, it weighs big misses more than small ones. A miss of 10 counts as 100, while a miss of 2 counts as only 4.

Try it now

Same mean, different spread. Drag the standard deviation (σ) and draw samples. A larger σ means single results land farther from the average.

Quick check
Option A always pays $100. Option B pays $0 or $200, each with probability 0.5. Which statement is true?
  1. B has the higher mean
  2. They have the same mean and the same spread
  3. A has the bigger standard deviation
  4. They have the same mean, and B has the bigger standard deviation
Show the answer

They have the same mean, and B has the bigger standard deviation

Both average $100. A never moves, so its standard deviation is 0. B always lands $100 from the average, so its standard deviation is $100.

Worked example

Worked example: two channels with the same average

Two ad channels earn a monthly profit, in thousands of dollars. Channel A earns 4, 5 or 6. Channel B earns −3, 5 or 13. For both, the chances are 25%, 50% and 25%. Work out each one's mean and standard deviation.

def mean_and_sd(values, probs):
    mean = sum(v * p for v, p in zip(values, probs))
    var = sum((v - mean) ** 2 * p for v, p in zip(values, probs))
    return mean, var ** 0.5

probs = [0.25, 0.5, 0.25]
for name, values in [("A", [4, 5, 6]), ("B", [-3, 5, 13])]:
    mean, sd = mean_and_sd(values, probs)
    print(name, "mean", mean, "sd", round(sd, 2))
In the lesson you can change this and run it.

Both channels have a mean of 5, so both average $5,000 a month. Channel A's standard deviation is about 0.71 (roughly $710). Channel B's is about 5.66 (roughly $5,660), eight times bigger. In a bad month, B loses $3,000. If your business needs predictable months, A is the safer pick. The averages alone would have called it a tie.

From real data: sample mean and variance

So far you knew the chances in advance. Usually you don't. Instead you have a list of results, like last week's daily sales or the reply times of 50 support emails. Then every observation gets equal weight.

Call the number of observations nn. Write each observation as xix_i. The small ii counts through the list: x1x_1, x2x_2, and so on. The mean of the data is written xˉ\bar{x}, said "x bar". The sample variance is written s2s^2.

xˉ=1n∑ixis2=1n−1∑i(xi−xˉ)2\bar{x} = \frac{1}{n}\sum_i x_i \qquad s^2 = \frac{1}{n-1}\sum_i (x_i - \bar{x})^2

In plain words: the mean is the ordinary average: add the values and divide by how many there are. The sample variance adds up the squared distances from that mean. Then it divides by one less than the count, n−1n - 1, instead of by nn.

Why one less? Your mean was worked out from the same data. No other number sits closer to those points overall. The true mean, which you don't know, is almost always a bit farther away. So the squared distances from your mean come out a little too small. Dividing by a slightly smaller number nudges the answer back up.

A worked example with three values: 2, 4 and 6. The mean is 4. The distances from it are −2, 0 and 2. Squared, they're 4, 0 and 4, which add to 8. Divide by n−1=2n - 1 = 2 and the variance is

  1. The standard deviation is the square root of 4, which is 2. Dividing by n=3n = 3 instead

would give about 2.667.

In NumPy, you choose with ddof, the number taken off nn. Use np.var(x, ddof=1) and np.std(x, ddof=1) for the n−1n - 1 version. The default, ddof=0, divides by nn.

import numpy as np

data = np.array([2, 4, 6])
print(data.mean())
print(np.var(data, ddof=1), np.std(data, ddof=1))
print(round(float(np.var(data)), 3))

It prints 4.0, then 4.0 2.0, then 2.667. With large samples the difference is negligible. Dividing the sum of 1,000 squared distances by 999 or by 1,000 gives almost the same answer.

Go deeper What "unbiased" means

The n−1n - 1 version is called unbiased. Imagine taking many samples and working out s2s^2 for each one. The average of all those answers would land on the true variance. The divide-by-nn version would come out slightly low on average. This fix is known as Bessel's correction.

Quick check
You have 5 observations. What does np.var(x, ddof=1) divide the sum of squared distances by?
  1. 1
  2. 4
  3. 5
  4. 6
Show the answer

4

ddof=1 takes 1 off n, so it divides by 5 − 1 = 4. The default, ddof=0, would divide by 5.

Shortcuts: shifting and scaling

Picture a class photo where every kid stands on the same 20 cm step. The average height goes up by 20 cm. But the gap between the tallest and shortest kid doesn't change. Adding the same amount to everything moves the average and leaves the spread alone.

Now picture converting prices from dollars to cents: multiply everything by 100. The average becomes 100 times bigger. So does every distance from it. Multiplying stretches the spread too.

You can write both changes as aX+baX + b. Here aa is the number you multiply by. And bb is the number you add afterwards.

E[aX+b]=a E[X]+bVar⁡(aX+b)=a2Var⁡(X)\mathbb{E}[aX + b] = a\,\mathbb{E}[X] + b \qquad \operatorname{Var}(aX + b) = a^2 \operatorname{Var}(X)

In plain words: the new mean is the old mean, times aa, plus bb. Adding bb doesn't touch the spread. Multiplying by aa multiplies the variance by aa squared. So the standard deviation is multiplied by aa, ignoring any minus sign.

A worked example: two values, 4 and 6. Their mean is 5 and their standard deviation is 1. Double them and add 10, and you get 18 and 22. The new mean is 2 × 5 + 10 = 20. The new standard deviation is 2 × 1 = 2. The variance went from 1 to 4, which is 2 squared times 1.

import numpy as np

x = np.array([4.0, 6.0])
y = 2 * x + 10
print(x.mean(), x.std())
print(y.mean(), y.std())

It prints 5.0 1.0 and then 20.0 2.0.

Quick check
Revenue per order has mean $60 and standard deviation $20. You add a flat $5 shipping charge to every order. What are the new mean and standard deviation?
  1. $65 and $25
  2. $65 and $20
  3. $60 and $20
  4. $65 and $45
Show the answer

$65 and $20

Adding a constant shifts the mean up by $5 but doesn't change the spread, like everyone standing on the same step.

Adding random amounts together

Now add two random amounts, like the sales of two separate campaigns. Means always add. If one averages $3,000 and the other $5,000, together they average $8,000. This holds even when the two are linked.

Spread works differently. Variances add, but only when the two are independent: one doesn't affect the other. Standard deviations don't add.

Call the first amount XX. Call the second one YY, like the second campaign's sales.

E[X+Y]=E[X]+E[Y]Var⁡(X+Y)=Var⁡(X)+Var⁡(Y) (if independent)\mathbb{E}[X + Y] = \mathbb{E}[X] + \mathbb{E}[Y] \qquad \operatorname{Var}(X + Y) = \operatorname{Var}(X) + \operatorname{Var}(Y) \ \text{(if independent)}

In plain words: the average of a total is the total of the averages. For independent amounts, the variance of a total is the total of the variances. Add variances, then take the square root. Never add standard deviations.

A worked example: two independent campaigns each have a standard deviation of $3,000. Work in thousands to keep the numbers small. Each variance is 3 × 3 = 9. Together that's 9 + 9 = 18. The square root of 18 is about 4.24. So the total's standard deviation is about $4,240, not $6,000. It's smaller because good and bad weeks partly cancel. When one campaign has a bad week, the other often doesn't.

sd_one = 3
var_total = sd_one ** 2 + sd_one ** 2
print(var_total, round(var_total ** 0.5, 2))

It prints 18 4.24.

This rule explains why spreading your bets works, which is called diversification. Take nn independent campaigns with the same spread. The expected total grows nn times. The standard deviation grows only by the square root of nn, written n\sqrt{n}. With 4 campaigns, the total is 4 times bigger but only 2 times as spread out. With 100 campaigns, it's 100 times bigger but only 10 times as spread out. Compared with its size, the total gets steadier. The same n\sqrt{n} shows up in the next two lessons. It's the reason bigger samples give more precise estimates.

The code below checks this by simulation. rng.normal(10_000, 4_000, ...) draws random campaign results that average 10,000 with a standard deviation of 4,000. (That bell-shaped "normal" distribution gets its own lesson soon.) It draws 100,000 single campaigns, and 100,000 groups of twenty. The std/mean column compares the spread to the size.

import numpy as np

rng = np.random.default_rng(1)
one = rng.normal(10_000, 4_000, size=100_000)                      # one campaign
twenty = rng.normal(10_000, 4_000, size=(100_000, 20)).sum(axis=1)  # twenty independent ones
print("one:    mean", round(one.mean()), " std", round(one.std()), " std/mean", round(one.std() / one.mean(), 3))
print("twenty: mean", round(twenty.mean()), " std", round(twenty.std()), " std/mean", round(twenty.std() / twenty.mean(), 3))

For one campaign, the spread is about 40% of the mean (0.399). For twenty, the mean is about 200,000 and the standard deviation about 17,900. That's only about 9% of the mean (0.089). The total is 20 times bigger, but the spread is only about 4.5 times bigger. That matches 20\sqrt{20}, which is about 4.47.

Go deeper The square-root rule as a formula

Say each of nn independent amounts has standard deviation σ\sigma. Each variance is σ2\sigma^2, so the total's variance is nσ2n\sigma^2. Take the square root:

σtotal=σn\sigma_{\text{total}} = \sigma \sqrt{n}

Read it as: "the spread of the total is one item's spread times the square root of how many there are." Here that's 4,000 × 20\sqrt{20}, about 17,889. The simulation gave 17,899, very close.

Quick check
Two independent channels have standard deviations of $3k and $4k. What is the standard deviation of their combined total?
  1. $7k
  2. $25k
  3. $5k
  4. $12k
Show the answer

$5k

Add the variances, not the standard deviations: 9 + 16 = 25. The square root of 25 is 5, so about $5k.

Practice what you just read

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

Create a free account

Try a quiz question

Every order value is doubled (a price change). What happens to the standard deviation?

  1. It doubles
  2. It quadruples
  3. It stays the same
  4. It halves

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

Before this lesson