Exponential and Logarithmic Functions
Exponential functions grow by multiplying, logarithmic functions grow by counting multiplications. One models spread and decay, the other reads it back on a human scale.
Why Does This Exist?
Two shapes run the quantities ML cares about. Populations, virality, compounding returns and exploding gradients grow exponentially: multiply per step, and the curve goes vertical. Measurement, bits, magnitudes and learning curves grow logarithmically: count the multiplications, and thousand-fold spans fit on one axis.
They are inverses, mirror images across the line . Exponentials answer "how much after steps"; logs answer "how many steps to reach ". The log rules themselves are in logarithms.
The one idea you need first. says three doublings reach eight. counts them back. Growth multiplies; the log counts the multiplications. Hold both directions at once and the pair is simple.
Think of It Like This
A rumour and its contact tracer
A rumour spreads exponentially: each hearer tells two friends, so 1 becomes 2, 4, 8, doubling per round. The contact tracer works logarithmically: given 8 hearers, how many rounds ran? Three. The tracer counts doublings the way the rumour performs them.
Neither job replaces the other. The rumour predicts load; the tracer reconstructs history. Confuse them and you either expect linear spread from a compounding process or demand round-by-round logs from thin air.
Where it stops: rumours saturate when everyone has heard, while pure exponentials never do. Real growth is logistic; the exponential is its early phase, which is exactly the phase ML usually models.
How It Actually Works
Exponential form: with base , . Growth for , decay for . The special base makes calculus clean, since is its own derivative. Doubling time satisfies ; with 10 percent growth per period, gives periods. Half-life mirrors it: remains after half-lives.
Logarithmic form: , defined for , the exact inverse. It climbs steeply near zero then flattens: from 1 to 10 takes as much horizontal room as 10 to 100, each decade one unit on a base-10 log. Small inputs near zero plunge toward negative infinity, which is why log-scales never touch the axis.
Worked example
Culture: cells doubling every hours. After hours, three doublings: cells.
Half-life: g with a -hour half-life. After hours: g.
Count: , because . Five doublings from 1 reach 32, and the log counted them. The diagram above draws both directions: the climb through and the stroll through .
Code
cells: int = 500for _ in range(3): cells *= 2print(cells) # -> 4000
import mathprint(math.log2(32)) # -> 5.0print(100 * (0.5) ** 3) # -> 12.5The loop performs the doublings one by one, the honest version of exponentiation. The log line counts them back. The last line is the half-life in one expression: three halvings of 100.
Watch Out For
Exponentials overflowing to infinity
is about , far past float64's ceiling near , so softmax-style code exponentiates straight to inf and then divides inf/inf into NaN. The symptom is a loss that is fine for epochs, then NaN on one unlucky batch with large logits.
Subtract the max before exponentiating: exp(x - max(x)). Work in log-space wherever the math allows. Overflow is not a rare edge; it is the default fate of raw exponentials.
Logging zero in a measurement pipeline
is negative infinity, and any zero count, empty bin or exact-zero probability feeds it directly. Dashboards show -inf, downstream means become NaN, and the pipeline stays green because no exception fired.
Add epsilon before the log or filter zeros explicitly: math.log(x + 1e-12). Decide the floor on purpose instead of discovering negative infinity in a report.
The Quick Version
- multiplies per step: growth above 1, decay below it, for calculus.
- counts the multiplications; defined only for positive .
- Doubling triples 500 to 4000 in three rounds; three half-lives cut 100g to 12.5g.
- Raw exponentials overflow past : subtract the max first.
- Never log raw zeros; set an epsilon floor deliberately.