Index Ai Academy
Phase 2 · Math, when you need it · Calculus

Exponentials and logarithms

Growth, decay, and why logs turn products into sums.

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

Some things grow by building on themselves. A savings account earns interest on its interest. A shared post reaches people who share it again. That kind of growth is called exponential, and it shows up inside AI too, in the scores that softmax turns into probabilities. Logarithms ("logs") run it backwards. They have one property that language models rely on: they turn multiplying into adding. A model's training loss is a log. Perplexity, a common score for language models, is an exponential. And any probability over a long piece of text is worked out in logs, because the raw number is too small for a computer to store.

What you'll be able to do

  • Model compounding growth and decay with exponentials
  • Use logarithms as the inverse: 'what power gives this number?'
  • Apply the log rules, especially log of a product = sum of logs
  • Explain why models add log-probabilities instead of multiplying probabilities

What it covers

  1. Growth that builds on itself
  2. Logarithms answer "what power?"
  3. How long until it doubles?
  4. Worked example: when does the list double?
  5. The rule that matters most: products become sums
  6. Going back: exponentials undo logs

Growth that builds on itself

Say your email list has 1,000 subscribers and grows 5% a month. After one month you have 1,000 × 1.05 = 1,050. After two months you grow the new total by 5%: 1,050 × 1.05 = 1,102.5. Each month you multiply by 1.05 again.

So the growth gets bigger every month, because 5% of a bigger list is more people. That is exponential growth. The increase depends on how big you already are.

Here is the rule written as a formula. tt is the number of months. N0N_0 (say "N nought") is the size you start with. N(t)N(t) is the size after tt months.

N(t)=N0⋅1.05 tN(t) = N_0 \cdot 1.05^{\,t}

In plain words: start with your list, then multiply by 1.05 once for every month that passes. The small raised tt means "multiply by 1.05, tt times".

A worked example with small numbers: 100 people growing 10% a month for 2 months gives 100 × 1.1 × 1.1 = 121.

If the multiplier is below 1, the number shrinks instead. Multiplying by 0.9 each month means you lose 10% each month. That is exponential decay, like interest in an old campaign fading away.

The code below grows a list of 10,000 at 5% a month and prints it every 6 months for 3 years. In Python, ** means "raise to the power", so 1.05 ** months is 1.05 multiplied by itself months times.

import numpy as np

months = np.arange(0, 37, 6)
print("months:", months)
print("list:  ", np.round(10000 * 1.05 ** months).astype(int))
It runs right here in your browser, with nothing to install.

The list grows by about 3,400 in the first six months, and by about 14,700 in the last six. Same rate, bigger jumps.

The special number e

One number appears as the base far more than any other. It is called ee, and it is about 2.718. In NumPy, exe^x (e raised to the power xx) is written np.exp(x). You will see it inside sigmoid and softmax later in the course. You don't need to know why it is special to use it.

Go deeper Why e?

Imagine interest that is added not once a year, or once a day, but every instant. That is called continuous compounding, and ee is the number it produces. It has a tidy property too: the graph of exe^x is exactly as steep at each point as its own height there. That makes the calculus around it very clean, which is why AI formulas use it.

Quick check
A list of 200 people grows 10% a month. How big is it after 2 months?
  1. 240
  2. 242
  3. 400
  4. 220
Show the answer

242

200 × 1.1 = 220 after one month, then 220 × 1.1 = 242. The second month grows the new total, not the original 200.

Logarithms answer "what power?"

Start with 1 and keep doubling: 2, 4, 8. How many doublings did it take to reach 8? Three. That count is a logarithm. It answers the question "how many times do I multiply to get here?"

In symbols, the log has a small number underneath called the base: the number you keep multiplying by. log⁡2(8)\log_2(8) reads "log base 2 of 8". It is the power you raise 2 to in order to get 8.

log⁡2(8)=3 because 23=8ln⁡(x)=log⁡e(x)\log_2(8) = 3 \ \text{because}\ 2^3 = 8 \qquad \ln(x) = \log_e(x)

In plain words: log⁡2(8)=3\log_2(8) = 3 because 2 × 2 × 2 = 8. The log is the number of times you multiply the base. ln⁡\ln (say "L N", the natural log) is the log whose base is ee.

Each base has its own NumPy function. np.log is the natural log. np.log2 and np.log10 use bases 2 and 10.

import numpy as np

print(np.log2(8), np.log10(1_000_000), np.log(np.e))

This prints 3.0 6.0 1.0. Three 2s make 8. Six 10s make a million. And one e makes e.

Notice how slowly logs grow. A million turns into 6. That is why logs are used for lopsided data, like spend per customer or follower counts, where a few huge values sit far above the rest.

Quick check
What does this print?
import math
print(round(math.log(1000, 10)))
  1. 100
  2. 10
  3. 1000
  4. 3
Show the answer

3

A logarithm answers: what power of 10 gives 1,000? The answer is 3.

Try it now

eˣ and ln x are mirror images across the diagonal line: each one undoes the other. Notice eˣ is always above zero, and ln x only exists for x above zero.

Quick check
What does np.log10(1000) print?
  1. 1000.0
  2. 30.0
  3. 3.0
  4. 100.0
Show the answer

3.0

10 × 10 × 10 = 1000. You multiply three 10s, so the log base 10 is 3.

How long until it doubles?

Logs let you run growth backwards. Your list grows 5% a month. How many months until it doubles? You need the tt where 1.05t=21.05^t = 2. Taking the log of both sides brings tt down where you can reach it:

t=ln⁡2ln⁡1.05≈14.2 monthst = \frac{\ln 2}{\ln 1.05} \approx 14.2 \text{ months}

In plain words: divide the log of 2 (the "doubling") by the log of 1.05 (one month of growth). The answer is how many months of growth fit into one doubling.

With small numbers: ln⁡2\ln 2 is about 0.693 and ln⁡1.05\ln 1.05 is about 0.0488. Divide them and you get about 14.2. The worked example below checks it in code.

Worked example

Worked example: when does the list double?

Your email list grows 5% a month. Find the doubling time with logs, then check it by growing 1,000 subscribers for 14 and 15 months.

import math

rate = 0.05
t = math.log(2) / math.log(1 + rate)
print(round(t, 1))
print(round(1000 * 1.05 ** 14), round(1000 * 1.05 ** 15))
In the lesson you can change this and run it.

The log formula says about 14.2 months. The check agrees: after 14 months 1,000 has grown to 1,980, just short of double. After 15 months it is 2,079, just past it. math.log is Python's built-in natural log, the same as np.log for a single number.

The rule that matters most: products become sums

Logs follow three rules. In them, aa is any positive number. bb is another positive number. kk is any power.

ln⁡(ab)=ln⁡a+ln⁡bln⁡ ⁣(ab)=ln⁡a−ln⁡bln⁡(ak)=kln⁡a\ln(ab) = \ln a + \ln b \qquad \ln\!\left(\frac{a}{b}\right) = \ln a - \ln b \qquad \ln(a^k) = k \ln a

In plain words: the log of a product is the sum of the logs. The log of a division is the difference of the logs. And the log of a power is the power times the log.

With small numbers, ln⁡2\ln 2 is about 0.693 and ln⁡3\ln 3 is about 1.099. Add them and you get 1.792, which is ln⁡6\ln 6. The code checks all three rules with a = 2, b = 3 and a power of 4.

import math

a, b = 2, 3
print(round(math.log(a * b), 4), round(math.log(a) + math.log(b), 4))
print(round(math.log(a / b), 4), round(math.log(a) - math.log(b), 4))
print(round(math.log(a ** 4), 4), round(4 * math.log(a), 4))

Each line prints two equal numbers: 1.7918, then -0.4055, then 2.7726.

Why language models need the first rule

A language model gives each word in a sentence a probability. The chance of the whole sentence is all those probabilities multiplied together. They are small numbers, so the product shrinks fast.

Think of a calculator with a limited screen. Show it a number with too many zeros after the decimal point and it gives up and shows 0. A computer does the same. When a number gets too small to store, it underflows: it becomes exactly zero, and the information is gone.

Adding logs avoids this. Each small probability turns into an ordinary negative number, and you add those up instead.

import numpy as np

probs = np.full(1000, 0.01)          # 1,000 words, each given probability 0.01
print("product:", np.prod(probs))    # underflows to 0.0
print("sum of logs:", np.sum(np.log(probs)))
print("as a power of 10:", np.sum(np.log10(probs)))

The product prints 0.0. The sum of logs is about −4605.17, a normal number to store. The last line says the true product is 10−200010^{-2000}: a 1 that sits 2,000 places after the decimal point. A computer's usual floor is roughly 10−30810^{-308}, so the product drops far below it. The log version keeps all the information. That is why models report log-probabilities, and why the standard training loss is a negative log (you'll meet it in the cross-entropy lesson).

Quick check
Why do language models add up log-probabilities instead of multiplying probabilities?
  1. Logs are faster to type
  2. Multiplying many small probabilities underflows to zero; adding their logs doesn't
  3. Probabilities can't be multiplied
  4. Adding makes the probabilities larger
Show the answer

Multiplying many small probabilities underflows to zero; adding their logs doesn't

ln(ab) = ln a + ln b, so the sum of logs holds the same information as the product, in a range a computer can store.

Going back: exponentials undo logs

A log and an exponential cancel each other out, like walking 10 steps forward and 10 steps back.

eln⁡x=xe^{\ln x} = x

In plain words: take the log of a number, raise ee to that result, and you are back where you started.

For example, ln⁡7\ln 7 is about 1.9459. Raise ee to 1.9459 and you get 7 again.

import math

x = 7
print(round(math.log(x), 4))
print(round(math.exp(math.log(x)), 6))

This prints 1.9459 and then 7.0. So you can do all the arithmetic in "log land", where nothing underflows, and step back with exp only at the end. Perplexity, a score you'll meet in Phase 5, works this way: it is the exponential of an average negative log-probability.

Go deeper A tiny perplexity example

Suppose a model gives every word in a text a probability of 0.25. The natural log of 0.25 is about −1.386, so the average negative log-probability is 1.386. Raise ee to 1.386 and you get about 4. A perplexity of 4 means the model is as unsure as if it were picking between 4 equally likely words each time.

For marketers: when a metric spans a huge range (spend per customer, page views per URL), plot it on a log scale or analyze np.log(value). Percentage changes like "+20%" become steps of the same size, and one giant customer stops squashing the rest of the chart flat.

Quick check
You add up a sentence's log-probabilities and get −6.9. Which line turns that back into the plain probability?
  1. 10 * -6.9
  2. np.log(-6.9)
  3. (-6.9) ** 2
  4. np.exp(-6.9)
Show the answer

np.exp(-6.9)

exp undoes ln. np.exp(-6.9) is about 0.001. np.log(-6.9) gives nan ("not a number"), because logs only exist for numbers above zero.

Practice what you just read

  • 6 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

ln(a) = 2 and ln(b) = 3. What is ln(ab)?

  1. 5
  2. 6
  3. 8
  4. 1.5

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

Before this lesson