Functions and graphs
Read a graph and see how an output depends on an input.
Create a free account Try part of it here
Why it matters
A trained model is a function. Text goes in and probabilities come out. Its loss (one number that says how wrong it is) is a function too, this time of its weights, the numbers it learns. Training is a search for the lowest point on that function's graph. Marketing is full of functions as well: revenue depends on price, and conversions depend on ad spend. This lesson teaches you to look at a graph and say "this flattens out" or "this peaks here". The lessons that follow, on derivatives (a derivative is the exact slope of a graph at a point), turn that habit into exact tools.
What you'll be able to do
- Read function notation and evaluate functions on whole arrays of inputs
- Read a graph: where it rises, falls, flattens and peaks
- Recognize the shapes that recur in machine learning: line, bowl, S-curve, hinge
- Find the best input for a function by evaluating many candidates
What it covers
- Inputs to outputs
- From a function to a graph
- A marketing function: diminishing returns
- Finding the best budget
- Shapes you'll keep meeting
- Worked example: four shapes, three inputs
Inputs to outputs
Think of a vending machine. You press B4 and out comes one particular snack. Press B4 again tomorrow and you get the same snack. One button never gives you two snacks, and it never gives you a random one.
A function works the same way. It takes an input and gives back exactly one output. Same input, same output, every time.
You already write functions in Python with def. Math writes them in a short form:
Here is the function's name, like the name after def. The letter stands for the input. Then means times , called "x squared".
In plain words: "f of x equals x squared." Whatever number you put in, multiply it by itself to get the output.
Try some small numbers. Put in 3 and you get 3 × 3 = 9. Put in 0 and you get 0. Put in −2 and you get (−2) × (−2) = 4, because a negative times a negative is positive. The same thing in Python:
def f(x): return x ** 2 print(f(3), f(0), f(-2))
It prints 9 0 4.
Some functions only accept certain inputs. The inputs a function accepts are called its domain. A square root, for instance, only accepts (zero or more) when you work with ordinary numbers. No ordinary number times itself gives −4, so −4 has no square root.
def sales(ad_spend): return 100 + 3 * ad_spend print(sales(10) - sales(0))
Show the answer
30
A slope of 3 means 3 more sales per dollar, so 10 dollars adds 30.
Show the answer
9
(−3) × (−3) = 9. Squaring a negative number gives a positive one.
From a function to a graph
A long list of inputs and outputs is hard to read at a glance. A picture is easier. The graph of a function draws each input and its output as a dot: input across, output up. Math writes each dot as : first how far across, then how far up.
For the dots include (−2, 4), (0, 0) and (3, 9). Draw enough dots and they join into a smooth U-shaped curve.
NumPy makes this quick. Hand it a whole array of inputs and one call works out every output at once. That's how you draw a graph: pick many inputs, compute the outputs, plot them.
import numpy as np import matplotlib.pyplot as plt def f(x): return x ** 2 x = np.linspace(-3, 3, 200) # 200 evenly spaced inputs plt.plot(x, f(x)) plt.title("f(x) = x²") print(f(3), f(np.array([-2, 0, 2])))
np.linspace(-3, 3, 200) makes 200 evenly spaced inputs from −3 to 3. The plot shows the U. The printout is 9 [4 0 4]. One input gives one output. An array of inputs gives an array of outputs.
A marketing function: diminishing returns
Think about cups of coffee. The first one in the morning makes a big difference. The second helps a little. By the fifth you feel almost nothing extra. Each cup adds less than the one before. That pattern is called diminishing returns.
Ad spend often behaves the same way. The first dollars reach the people most likely to buy. Later dollars reach people who care less. So conversions (sales or sign-ups from the ads) don't grow in a straight line with spend. They climb fast, then level off toward a ceiling.
A common model for this is a saturating curve:
Take the symbols one at a time:
- is the monthly ad spend in dollars. It's the input.
- is the number of conversions you get for that spend. It's the output.
- , said "c max", is the ceiling: the level conversions creep toward but never quite reach.
- is the spend at which you reach half the ceiling.
- The dot means multiply.
In plain words: divide your spend by (spend plus k). That gives a fraction between 0 and 1. Multiply the fraction by the ceiling to get your conversions.
Here's a worked example. Say the ceiling is 900 conversions and k is $4,000.
| Spend | Fraction s / (s + k) | Conversions |
|---|---|---|
| $0 | 0 / 4,000 = 0 | 0 |
| $4,000 | 4,000 / 8,000 = 0.5 | 450 |
| $8,000 | 8,000 / 12,000 ≈ 0.67 | 600 |
| $12,000 | 12,000 / 16,000 = 0.75 | 675 |
The first $4,000 brings 450 conversions. The next $4,000 brings only 150 more. The $4,000 after that brings 75 more. Each step buys less. The same calculation in Python:
def conversions(spend, c_max=900, k=4000): return c_max * spend / (spend + k) for spend in [0, 4000, 8000, 12000]: print(spend, conversions(spend))
Next to each spend it prints the table's last column: 0.0, 450.0, 600.0 and 675.0.
Go deeper Why k is the halfway point
Set the spend equal to . The fraction becomes . So , half the ceiling, whatever the numbers are.
The fraction never quite reaches 1, because the bottom () is always bigger than the top (). That's why the curve creeps closer and closer to the ceiling without touching it.
Finding the best budget
More conversions isn't the same as more profit. Say each conversion earns you $60 of margin, which is what's left after costs. Then your profit is that margin minus what you spent on ads:
profit = 60 × conversions − spend
Use the numbers from the table. At $4,000 of spend, profit is 60 × 450 − 4,000 = $23,000. At $12,000 it's 60 × 675 − 12,000 = $28,500. Spend a lot more and profit drops again, because the extra conversions no longer cover the extra spend.
The code below tries 300 budgets from $0 to $30,000. It works out the profit for each and keeps the best one.
import numpy as np import matplotlib.pyplot as plt def conversions(spend, c_max=900, k=4000): return c_max * spend / (spend + k) spend = np.linspace(0, 30000, 300) profit = 60 * conversions(spend) - spend # $60 margin per conversion, minus spend best = spend[np.argmax(profit)] plt.plot(spend, conversions(spend), label="conversions") plt.plot(spend, profit / 60, label="profit ÷ 60") plt.axvline(best, linestyle="--", color="gray") plt.xlabel("monthly ad spend ($)") plt.legend() print(f"best spend ≈ ${best:,.0f}, profit ≈ ${profit.max():,.0f}")
It prints a best spend of about $10,736 and a profit of about $28,606. np.argmax finds the position of the largest profit. Then spend[...] looks up the budget at that position.
Now read the graph. Conversions keep rising but flatten out. Profit rises, peaks, then falls. The dashed line marks the peak: the best budget.
Trying every candidate and keeping the best is called grid search. It's simple and reliable when there are one or two inputs. For an AI model it's hopeless. A model can have billions of weights, the numbers it adjusts while it learns. Try 10 values for each of 2 inputs and you need 10 × 10 = 100 tries. Try 10 values for each of a million weights and the count is 1 followed by a million zeros. That's why the next lessons need derivatives. They point toward better settings without trying them all.
Go deeper How close does the grid get?
The grid checks budgets about $100 apart (30,000 ÷ 299 ≈ 100.3). The true peak is near $10,697, which you'll be able to find exactly once you know derivatives. The grid's answer, $10,736, is the nearest budget it tried. A finer grid gets closer, but it costs more work.
Show the answer
1,000
10 × 10 × 10 = 1,000. Each extra input multiplies the count by 10, which is why grid search falls apart with many inputs.
Shapes you'll keep meeting
A handful of shapes turn up again and again in machine learning, which is the craft of fitting such shapes to data. Once you can spot them, many formulas start to look familiar.
| Shape | Formula | Where it shows up |
|---|---|---|
| Line | linear models, a neuron before the step called activation | |
| Bowl | loss functions: one lowest point | |
| S-curve (sigmoid) | turning a score into a probability between 0 and 1 | |
| Hinge (ReLU) | the most common activation in neural networks |
Line
In , the number sets how steep the line is. The number is the output when the input is 0.
In plain words: multiply the input by one fixed number, then add another.
With a = 2 and b = 1, input 2 gives 2 × 2 + 1 = 5, and input −2 gives −3.
Bowl
In plain words: subtract 2 from the input, square the result, then add 1.
Input 0 gives (0 − 2)² + 1 = 5. Input 2 gives 0 + 1 = 1, the lowest output there is. Any other input lands higher up the sides of the bowl. Training a model means looking for the bottom of a bowl like this one. Real loss bowls are bumpier, but the idea is the same.
Show the answer
2
At 2 the squared part is 0, so the output is 1. Any other input adds something positive.
S-curve (sigmoid)
The S-curve is called the sigmoid. Its name is written , the Greek letter sigma. The formula also uses , a fixed number about 2.718 that you'll meet properly in the next lesson.
In plain words: raise to the power of minus the input, add 1, then divide 1 by that. Big negative inputs give almost 0. Big positive inputs give almost 1. An input of 0 gives exactly 0.5.
Input 2 gives about 0.88. Input −2 gives about 0.12. That squashing is how a model turns any score into something that can be read as a probability.
Hinge (ReLU)
ReLU is short for "rectified linear unit". The part means "the larger of 0 and x".
In plain words: if the input is positive, keep it. If it's negative, output 0.
Input 2 gives 2. Input −2 gives 0.
Words for describing a graph
- Increasing: the graph goes up as you move left to right.
- Decreasing: it goes down.
- Minimum: its lowest point. Maximum: its highest point.
- Steep or flat: how fast the output changes as the input moves.
Steepness has a proper name, the derivative. It's coming next.
Show the answer
0 and 3
ReLU keeps positive inputs and turns negative ones into 0.
Worked example: four shapes, three inputs
Put the inputs −2, 0 and 2 through each shape and compare. The line uses a = 2 and b = 1. Predict each row before you run it.
import math def line(x): return 2 * x + 1 def bowl(x): return (x - 2) ** 2 + 1 def sigmoid(x): return 1 / (1 + math.exp(-x)) def relu(x): return max(0, x) for x in [-2, 0, 2]: print(x, line(x), bowl(x), round(sigmoid(x), 2), relu(x))
Each row is one input, then the line, bowl, sigmoid and ReLU outputs. The line rises by the same amount at every step: −3, 1, 5. The bowl falls from 17 to 5 to 1, its lowest point at x = 2. The sigmoid goes 0.12, 0.5, 0.88: always between 0 and 1, and exactly 0.5 at 0. ReLU gives 0 for −2 and 0, then 2 for 2.
Three activation functions: sigmoid, ReLU and tanh, which is a cousin of the sigmoid and runs from −1 to 1. Drag the point along the sigmoid: big negative inputs give almost 0, big positive inputs almost 1, and 0 gives exactly 0.5.
Show the answer
Prices near $40 maximize profit; going higher or lower earns less
A peak is a maximum: moving away from it in either direction lowers the output.
Practice what you just read
- 5 code examples you can edit and run
- a practice exercise that checks your code
- a 5-question quiz
- 4 review cards for spaced repetition
Try a quiz question
Which function shape is typical of a loss function with one best setting?