Differentiation

Don’t just watch — invent.

Navigate: press → or Space to advance  |  ← to go back

Part 1: How Fast Is a Function Changing?

Challenge (skip ahead if you can):

Write a Python function diff(my_func, x) that takes any function and a point $x$, and returns the derivative of that function at $x$.

def diff(my_func, x):
    """Return the derivative of my_func at point x."""
    # your code here

Test:

def g(x):
    return x ** 2

print(diff(g, 3))   # should print ≈ 6

Already got it? Skip to Part 2. Otherwise, the next slides will guide you step by step.

Think of a function as a machine. You feed it an input $x$, and it gives you an output $y$.

x
y = 2x
y

Feed it two inputs very close together:

InputOutput
$x_1 = 1$$y_1 = \;?$
$x_2 = 1.01$$y_2 = \;?$

Compute $y_1$ and $y_2$.

What did you get for $y_1$ and $y_2$? Check your answers:

InputOutput
$x_1 = 1$$y_1 = 2$
$x_2 = 1.01$$y_2 = 2.02$

Now compute:

$\dfrac{y_2 - y_1}{x_2 - x_1} = \;?$

$= \dfrac{2.02 - 2}{1.01 - 1} = \dfrac{0.02}{0.01} = \mathbf{2}$

What does this number mean?

When $x$ increased by $0.01$, $y$ increased by $0.02$ — twice as fast. This ratio measures how fast $y$ changes per unit change in $x$.

This ratio is called the derivative of $y$ with respect to $x$.

You’ll also see it written as:

$\dfrac{dy}{dx}$   or   $\dfrac{\Delta y}{\Delta x}$

The process of finding it is called differentiation.

Now let’s try another function: $y = 3x$.

Write it as a Python function:

def f(x):
    # your code here
def f(x):
    return 3 * x

Now:

  1. Compute f(1)
  2. Increase $x$ by a tiny amount — try 0.000001. Compute f(1.000001)
  3. Compute $\dfrac{y_2 - y_1}{x_2 - x_1}$

You should get:

 Value
f(1)$3$
f(1.000001)$3.000003$
$\dfrac{3.000003 - 3}{1.000001 - 1}$$= \mathbf{3}$

The derivative of $y = 3x$ is $\mathbf{3}$. That makes sense — for every 1 unit increase in $x$, $y$ increases by 3.

You just computed a derivative using Python. Well done!

Now a more interesting function: $y = x^2$.

Your turn: Write it as a Python function:

def g(x):
    # your code here
def g(x):
    return x ** 2

Using the same technique (nudge $x$ by $0.000001$), find the derivative of $g$ at each of these points:

$x$Derivative at $x$
$1$?
$-1$?
$0$?
$2$?

Check your answers:

$x$Derivative at $x$
$1$$\approx \mathbf{2}$
$-1$$\approx \mathbf{-2}$
$0$$\approx \mathbf{0}$
$2$$\approx \mathbf{4}$

Notice something? The derivative of $x^2$ at $x$ seems to be $2x$. Unlike $y = 3x$ where the derivative was the same everywhere, here it changes depending on where you are.

At $x = 0$ the function is flat (derivative = 0). At $x = 2$ it’s climbing steeply (derivative = 4).

You’ve been repeating the same steps each time:

  1. Pick a tiny $h$ (like $0.000001$)
  2. Compute $f(x)$ and $f(x + h)$
  3. Return $\dfrac{f(x + h) - f(x)}{h}$

Your turn: Put this into a reusable Python function. It should work for any function, at any point $x$:

def diff(my_func, x):
    """Return the derivative of my_func at point x."""
    # your code here

Here’s one way to write it:

def diff(my_func, x, h=1e-6):
    return (my_func(x + h) - my_func(x)) / h

Test it:

print(diff(g, 1))    # should be ≈ 2
print(diff(g, -1))   # should be ≈ -2
print(diff(g, 0))    # should be ≈ 0
print(diff(g, 2))    # should be ≈ 4

You now have a function that can compute the derivative of any function at any point. You just invented numerical differentiation.

Part 2: Algebraic Differentiation

Challenge (skip ahead if you can):

Your diff function uses a tiny nudge — an approximation. Can you find the exact derivative of $y = x^2$ using pure algebra?

Hint: compute $y$ at $x + d$, subtract $y$ at $x$, divide by $d$, and see what happens as $d \to 0$.

Then do the same for $y = 10$, $y = 5x + 6$, and $y = 3x^2 + 2$.

Already got it? Skip to Part 3. Otherwise, the next slides will guide you.

Your diff function works, but it uses a tiny nudge — an approximation. Can we find the exact derivative using algebra?

Let’s try with $y = x^2$.

If our input is $x$, then $y_1 = x^2$.

Now nudge $x$ by a tiny amount $d$. The new input is $x + d$.

What is $y_2$? Expand $(x + d)^2$.

What did you get for $(x + d)^2$? Check:

$y_2 = (x + d)^2 = x^2 + 2xd + d^2$

Now compute the derivative:

$\dfrac{y_2 - y_1}{(x + d) - x}$

$= \dfrac{(x^2 + 2xd + d^2) - x^2}{d}$

$= \dfrac{2xd + d^2}{d} = 2x + d$

We got:

$\dfrac{dy}{dx} = 2x + d$

But $d$ is a tiny nudge — as small as we want. In the limit, $d$ vanishes to zero.

$\dfrac{dy}{dx} = \mathbf{2x}$

That’s exactly the pattern you saw numerically! At $x = 1$ the derivative is $2$, at $x = 2$ it’s $4$, at $x = 0$ it’s $0$.

This is algebraic (or analytical) differentiation — an exact answer, no approximation.

Your turn: Use the same algebra technique to find the derivative of these functions. For each one, compute $y_2$ at $x + d$, then simplify $\dfrac{y_2 - y_1}{d}$, and drop $d$.

Function$\dfrac{dy}{dx} = \;?$
$y = 10$?
$y = 5x + 6$?
$y = 3x^2 + 2$?

Verify your answers with your diff function from Part 1!

Check your work:

Function $y_2$ at $x + d$ $\dfrac{y_2 - y_1}{d}$ $\dfrac{dy}{dx}$
$y = 10$ $10$ $\dfrac{10 - 10}{d} = 0$ $\mathbf{0}$
$y = 5x + 6$ $5(x\!+\!d) + 6$ $\dfrac{5d}{d} = 5$ $\mathbf{5}$
$y = 3x^2 + 2$ $3(x\!+\!d)^2 + 2$ $6x + 3d$ $\mathbf{6x}$

Now verify these algebraic results using your diff function from Part 1:

def c(x):  return 10
def h(x):  return 5*x + 6
def k(x):  return 3*x**2 + 2

print(diff(c, 3))   # should be ≈ 0
print(diff(h, 3))   # should be ≈ 5
print(diff(k, 3))   # should be ≈ 6*3 = 18

Notice the patterns: a constant disappears, $5x$ becomes $5$, and $3x^2$ becomes $6x$. You’re discovering the rules of differentiation.

Part 3: Rules You Just Discovered

Challenge (skip ahead if you can):

Without expanding $(x+d)^n$, can you state a general rule for the derivative of $x^n$? What about the derivative of a sum $f(x) + g(x)$ or a constant times a function $c \cdot f(x)$?

Use your rules to differentiate: $x^5$,   $7x^3$,   $4x^2 + 3x + 1$,   $2x^4 - x^2 + 5$.

Already got it? Skip to Part 4. Otherwise, the next slides will guide you.

Let’s collect what you’ve found so far. Look at the results and fill in the pattern:

$y$ $\dfrac{dy}{dx}$ Rule
$10$$0$ Constant → $0$
$5x + 6$$5$ $ax + b$ → $a$
$x^2$$2x$ $x^n$ → ?
$3x^2 + 2$$6x$

Can you guess the derivative of $x^3$? What about $x^4$? Try to see the pattern before we verify.

Let’s verify algebraically for $y = x^3$:

$y_2 = (x + d)^3 = x^3 + 3x^2 d + 3x d^2 + d^3$

$\dfrac{y_2 - y_1}{d} = \dfrac{3x^2 d + 3x d^2 + d^3}{d} = 3x^2 + 3xd + d^2$

Drop terms with $d$ → $\dfrac{dy}{dx} = \mathbf{3x^2}$

Now look at the pattern:

$y$ $\dfrac{dy}{dx}$
$x^2$$2x^1$
$x^3$$3x^2$
$x^n$ $nx^{n-1}$

This is the Power Rule. You just invented it.

Two more patterns are hiding in your results. Look closely:

$y = 3x^2 + 2$ → $\dfrac{dy}{dx} = 6x$

Question 1: You know the derivative of $x^2$ is $2x$, and the derivative of $2$ is $0$. What happened when you differentiated the sum $3x^2 + 2$? Can you state a rule for differentiating $f(x) + g(x)$?

The derivative of a sum is the sum of the derivatives.

(Shorthand: $f'(x)$ means “the derivative of $f$ at $x$” — same as $\dfrac{df}{dx}$, just shorter to write.)

$\dfrac{d}{dx}\big[f(x) + g(x)\big] = f'(x) + g'(x)$

Question 2: The derivative of $x^2$ is $2x$. The derivative of $3x^2$ is $6x = 3 \cdot 2x$. What happened to the constant multiplier $3$? Can you state a rule for differentiating $c \cdot f(x)$?

A constant multiplier stays put:

$\dfrac{d}{dx}\big[c \cdot f(x)\big] = c \cdot f'(x)$

Your turn: Using the rules you discovered, find $\dfrac{dy}{dx}$ for each — no algebra needed this time, just apply the rules:

$y$ $\dfrac{dy}{dx}$
$x^5$?
$7x^3$?
$4x^2 + 3x + 1$?
$2x^4 - x^2 + 5$?

Verify each answer numerically with your diff function!

Check your answers:

$y$ $\dfrac{dy}{dx}$ Rule used
$x^5$ $5x^4$ Power
$7x^3$ $21x^2$ Constant mult + Power
$4x^2 + 3x + 1$ $8x + 3$ Sum + Power
$2x^4 - x^2 + 5$ $8x^3 - 2x$ Sum + Power

You can now differentiate any polynomial — instantly, exactly, by hand. These are the same rules taught in calculus courses. You didn’t memorize them — you derived them.

Part 4: What If There Are Two Inputs?

Challenge (skip ahead if you can):

Given $y = x_1^2 + 2 x_1 x_2$, find $\dfrac{\partial y}{\partial x_1}$ and $\dfrac{\partial y}{\partial x_2}$ algebraically.

Then write a function diff2(my_func, x1, x2) that returns both partial derivatives numerically as a tuple.

Already got it? Skip to Part 5. Otherwise, the next slides will guide you.

So far, your functions had one input. But what if a function takes two?

x₁ x₂
y = x₁² + 2·x₁·x₂
y

$y = x_1^2 + 2 x_1 x_2$

How do you find the derivative now? With respect to which input?

The trick: differentiate with respect to one input at a time, treating the other as a constant. This is called a partial derivative.

Your turn (algebraic):

$y = x_1^2 + 2 x_1 x_2$

  1. Treat $x_2$ as a constant. Differentiate with respect to $x_1$.
    $\dfrac{\partial y}{\partial x_1} = \;?$
  2. Treat $x_1$ as a constant. Differentiate with respect to $x_2$.
    $\dfrac{\partial y}{\partial x_2} = \;?$

(Hint: $2 x_1 x_2$ is just “$\text{constant} \cdot x_1$” when $x_2$ is fixed, and “$\text{constant} \cdot x_2$” when $x_1$ is fixed.)

Check your answers:

$\dfrac{\partial y}{\partial x_1} = 2x_1 + 2x_2$

(power rule on $x_1^2$ → $2x_1$;   $2x_2$ is a constant times $x_1$ → $2x_2$)

$\dfrac{\partial y}{\partial x_2} = 2x_1$

($x_1^2$ is a constant with respect to $x_2$ → $0$;   $2x_1 \cdot x_2$ → $2x_1$)

The symbol $\partial$ (curly-d) reminds us it’s a partial derivative — we only moved one input.

Now verify numerically. Define the function in Python and use tiny nudges to compute both partial derivatives:

def f(x1, x2):
    return x1**2 + 2*x1*x2

Compute $\dfrac{\partial y}{\partial x_1}$ and $\dfrac{\partial y}{\partial x_2}$ at these points:

Point $\dfrac{\partial y}{\partial x_1}$ $\dfrac{\partial y}{\partial x_2}$
$x_1\!=\!1,\; x_2\!=\!1$??
$x_1\!=\!2,\; x_2\!=\!1.5$??

(Remember: to nudge only $x_1$, compute $\dfrac{f(x_1 + h,\; x_2) - f(x_1,\; x_2)}{h}$. Same idea for $x_2$.)

Check your numerical results:

Point $\dfrac{\partial y}{\partial x_1}$ $\dfrac{\partial y}{\partial x_2}$
$x_1\!=\!1,\; x_2\!=\!1$ $2(1) + 2(1) = \mathbf{4}$ $2(1) = \mathbf{2}$
$x_1\!=\!2,\; x_2\!=\!1.5$ $2(2) + 2(1.5) = \mathbf{7}$ $2(2) = \mathbf{4}$

Your algebraic answers and numerical answers should match. Algebra gives the formula; numbers let you verify.

Your turn: Write a function diff2(my_func, x1, x2) that returns both partial derivatives as a tuple:

def diff2(my_func, x1, x2):
    """Return (dy/dx1, dy/dx2) numerically."""
    # your code here

Test it:

print(diff2(f, 1, 1))      # should be ≈ (4, 2)
print(diff2(f, 2, 1.5))    # should be ≈ (7, 4)

Here’s one way:

def diff2(my_func, x1, x2, h=1e-6):
    dy_dx1 = (my_func(x1 + h, x2) - my_func(x1, x2)) / h
    dy_dx2 = (my_func(x1, x2 + h) - my_func(x1, x2)) / h
    return (dy_dx1, dy_dx2)

Each partial derivative nudges one input while keeping the other fixed — exactly what you did algebraically, but automated.

In machine learning, most functions have hundreds or millions of inputs (weights). Partial derivatives tell the optimizer how to tweak each weight individually. You just invented the building block of gradient descent.

Part 5: Scaling to Any Number of Inputs

Challenge (skip ahead if you can):

Write a function diffn(my_func, arr) that takes a function with any number of inputs (passed as a list) and returns the list of all partial derivatives — the gradient.

def diffn(my_func, arr):
    """Return a list of partial derivatives, one per input."""
    # your code here

Test:

def sum_of_squares(a, b, c):
    return a**2 + b**2 + c**2

print(diffn(sum_of_squares, [3, 4, 5]))
# should print ≈ [6, 8, 10]

Already got it? Skip to Part 6. Otherwise, the next slides will guide you.

Your diff2 works for two inputs. But what if a function takes 3, 10, or 1000 inputs?

First problem: how do you even call such a function? Writing f(x1, x2, x3, ...) doesn’t scale.

Python has a trick — you can pass a list as arguments using *:

def f(a, b, c):
    return a + b + c

args = [10, 20, 30]
f(*args)            # same as f(10, 20, 30)  → 60

The * unpacks the list into separate arguments. This works for any length.

Try it yourself:

def g(x1, x2, x3):
    return x1**2 + x2**2 + x3**2

inputs = [3, 4, 5]
print(g(*inputs))       # what do you get?

$3^2 + 4^2 + 5^2 = 9 + 16 + 25 = \mathbf{50}$

Now, you can also modify one element of the list and call the function again:

nudged = inputs.copy()
nudged[0] = inputs[0] + 0.000001    # nudge only x1
print(g(*nudged))                   # ≈ 50.000006

That’s exactly what you need for a partial derivative — nudge one input, keep the rest fixed.

Your turn: Write diffn(my_func, arr) that returns a list of all partial derivatives — one for each element of arr:

def diffn(my_func, arr):
    """Return a list of partial derivatives, one per input."""
    # your code here

Hints:

  • Loop over each index $i$ in arr
  • Make a copy, nudge position $i$ by a tiny $h$
  • Compute $\dfrac{f(\text{nudged}) - f(\text{original})}{h}$
  • Use * to unpack when calling my_func

Here’s one way:

def diffn(my_func, arr, h=1e-6):
    partials = []
    base = my_func(*arr)
    for i in range(len(arr)):
        nudged = list(arr)
        nudged[i] += h
        partials.append((my_func(*nudged) - base) / h)
    return partials

Test it with a 3-argument function:

def f3(x1, x2, x3):
    return x1**2 + x2**2 + x3**2

print(diffn(f3, [3, 4, 5]))
# ≈ [6, 8, 10]   (i.e. 2·x1, 2·x2, 2·x3)

Now test with a 4-argument function:

def f4(a, b, c, d):
    return a*b + c**2 - 3*d

print(diffn(f4, [2, 5, 4, 1]))
# ≈ [5, 2, 8, -3]

Verify by hand:

Partial Formula At $(2, 5, 4, 1)$
$\partial y / \partial a$$b$$5$
$\partial y / \partial b$$a$$2$
$\partial y / \partial c$$2c$$8$
$\partial y / \partial d$$-3$$-3$

This list of all partial derivatives has a name: the gradient. Your diffn computes the gradient of any function with any number of inputs.

Part 6: A Function of a Function

Challenge (skip ahead if you can):

Given $z = 2x + 5$ and $y = z^2$ (chained: $x \to z \to y$), find $\dfrac{dy}{dx}$ at $x = 1$ without writing the combined function. Use only $\dfrac{dz}{dx}$ and $\dfrac{dy}{dz}$.

What general rule lets you do this?

Already got it? Skip to Part 7. Otherwise, the next slides will guide you.

What if the output of one function feeds into another?

x
z = 2x + 5
z
y = z²
y

Your turn: Write two Python functions matching the diagram:

  • zz(x) — takes $x$, returns $2x + 5$
  • yy(z) — takes $z$, returns $z^2$

You should have something like:

def zz(x):
    return 2*x + 5

def yy(z):
    return z**2

Now use them together — compute $z$ and $y$ at $x = 1$:

z_val = zz(1)
y_val = yy(z_val)
print(z_val, y_val)

$z = 2(1) + 5 = \mathbf{7}$

$y = 7^2 = \mathbf{49}$

Now, using your diff function from Part 1, compute these two derivatives at $x = 1$:

  1. $\dfrac{dz}{dx}$ — how fast does $z$ change when you nudge $x$?
  2. $\dfrac{dy}{dz}$ — how fast does $y$ change when you nudge $z$? (use $z = 7$)

Check your answers:

dz_dx = diff(zz, 1)     # ≈ 2
dy_dz = diff(yy, 7)     # ≈ 14

$\dfrac{dz}{dx} = \mathbf{2}$   (slope of $2x + 5$)

$\dfrac{dy}{dz} = \mathbf{14}$   ($2z$ at $z = 7$)

Now the big question: can you figure out $\dfrac{dy}{dx}$ — how fast does $y$ change when you nudge $x$ — using only these two numbers?

Think about it before moving on.

Hint: if nudging $x$ by $1$ makes $z$ change by $2$, and nudging $z$ by $1$ makes $y$ change by $14$…

Then nudging $x$ by $1$ makes $y$ change by…?

$\dfrac{dy}{dx} = \dfrac{dy}{dz} \times \dfrac{dz}{dx} = 14 \times 2 = \mathbf{28}$

This is the Chain Rule: when functions are chained together, you multiply the derivatives along the chain.

$\dfrac{dy}{dx} = \dfrac{dy}{dz} \cdot \dfrac{dz}{dx}$

Let’s verify. Create a combined function that takes $x$ and returns $y$ directly:

def yz(x):
    return yy(zz(x))

Now compute its derivative numerically at $x = 1$:

print(diff(yz, 1))    # should be ≈ 28

$\approx \mathbf{28}$ — exactly what the chain rule predicted!

$\dfrac{dy}{dz} \times \dfrac{dz}{dx} = 14 \times 2 = 28 \;\checkmark$

In neural networks, each layer is a function feeding into the next. The chain rule lets you compute how the final output changes when you tweak a weight in any layer. That process is called backpropagation.

Part 7: A Bigger Computation Graph

Challenge (skip ahead if you can):

Two blocks: $z = x_1^2 + 2x_1 x_2 - x_2^3 + 5x_3$ and $y = 3(z + x_4)$. Input $x_4$ skips block 1.

Compute the full gradient $[dy/dx_1,\; dy/dx_2,\; dy/dx_3,\; dy/dx_4]$ at $(1, 2, 1, 3)$ using the chain rule. Then verify with diffn.

Already got it? Skip to Part 8. Otherwise, the next slides will guide you.

Real models have many inputs flowing through many blocks. Let’s try one with four inputs and two blocks:

x₁ x₂ x₃
z = x₁² + 2x₁x₂ − x₂³ + 5x₃
z
y = 3(z + x₄)
y x₄

Notice: $x_4$ skips block 1 and feeds directly into block 2. This is common in real networks.

Your turn (algebraic): Start from the output and work backwards.

$y = 3(z + x_4)$

  1. $\dfrac{\partial y}{\partial x_4} = \;?$
  2. $\dfrac{\partial y}{\partial z} = \;?$

Check:

$\dfrac{\partial y}{\partial x_4} = \mathbf{3}$   $\dfrac{\partial y}{\partial z} = \mathbf{3}$

(Both are just constants — $y$ is linear in $z$ and $x_4$.)

Now the first block: $z = x_1^2 + 2x_1 x_2 - x_2^3 + 5x_3$

Find all three partial derivatives:

  1. $\dfrac{\partial z}{\partial x_1} = \;?$
  2. $\dfrac{\partial z}{\partial x_2} = \;?$ (Remember: $-x_2^3$ is $(-1) \cdot x_2^3$, so its derivative is $(-1) \cdot 3x_2^2 = -3x_2^2$)
  3. $\dfrac{\partial z}{\partial x_3} = \;?$

Check:

$\dfrac{\partial z}{\partial x_1} = 2x_1 + 2x_2$   $\dfrac{\partial z}{\partial x_2} = 2x_1 - 3x_2^2$   $\dfrac{\partial z}{\partial x_3} = 5$

Now use the chain rule to get from the output all the way back to each input:

$\dfrac{dy}{dx_i} = \dfrac{\partial y}{\partial z} \cdot \dfrac{\partial z}{\partial x_i}$

Your turn: Evaluate at $x_1\!=\!1,\; x_2\!=\!2,\; x_3\!=\!1,\; x_4\!=\!3$.

  Formula Value
$dy/dx_1$$3 \cdot (2x_1 + 2x_2)$?
$dy/dx_2$$3 \cdot (2x_1 - 3x_2^2)$?
$dy/dx_3$$3 \cdot 5$?
$dy/dx_4$$3$?

Check your answers at $(1, 2, 1, 3)$:

  Calculation Value
$dy/dx_1$ $3 \cdot (2 + 4) = 3 \cdot 6$ $\mathbf{18}$
$dy/dx_2$ $3 \cdot (2 - 12) = 3 \cdot (-10)$ $\mathbf{-30}$
$dy/dx_3$ $3 \cdot 5$ $\mathbf{15}$
$dy/dx_4$ $3$ $\mathbf{3}$

The gradient is $[18,\; -30,\; 15,\; 3]$.

Now verify numerically. Define the full pipeline as a single function and use diffn:

def block1(x1, x2, x3):
    return x1**2 + 2*x1*x2 - x2**3 + 5*x3

def block2(z, x4):
    return 3 * (z + x4)

def full(x1, x2, x3, x4):
    z = block1(x1, x2, x3)
    return block2(z, x4)

print(diffn(full, [1, 2, 1, 3]))

$\approx [18,\; -30,\; 15,\; 3]$ — matches your algebraic answers. $\checkmark$

Reflect: you computed the gradient two ways.

Approach How it works
diffn Nudge each of the 4 inputs, call full each time → 4 function calls
Chain rule Compute $\partial y / \partial z$ once, then multiply by each $\partial z / \partial x_i$ → reuse one shared derivative

With 4 inputs the difference is small. But imagine a neural network with a million weights.

The chain rule lets you compute $\dfrac{\partial y}{\partial z}$ once and reuse it for every weight in block 1 — that’s the efficiency behind backpropagation.

You work backwards from the output: compute each block’s local derivatives, then multiply along the chain. One pass, all gradients.

Part 8: Seeing the Derivative

Challenge (skip ahead if you can):

Plot $y = x^2$. At any point, what geometric object does the derivative correspond to? What does a positive, negative, or zero derivative tell you about the curve at that point?

Already got it? Skip to Part 9. Otherwise, the next slides will guide you.

You’ve been computing derivatives as numbers. But what does a derivative look like?

Plot $y = x^2$ and pick two points close together. The dashed line through them is called a secant:

Compute: What is the slope $\dfrac{\Delta y}{\Delta x}$ of this secant?

$\dfrac{2.89 - 2.25}{1.7 - 1.5} = \dfrac{0.64}{0.2} = 3.2$ — exactly the ratio you’ve been computing!

Now bring the two points closer and closer together. The secant becomes a tangent — a line that just touches the curve at one point:

This tangent touches the curve at $x = 1.5$. What is its slope? Use the derivative formula you found for $x^2$.

Derivative of $x^2$ is $2x$, so at $x = 1.5$: slope $= 2(1.5) = \mathbf{3}$.

The derivative at a point is the slope of the tangent line at that point.

What does the slope tell you? Look at three points on $y = x^2$:

Your turn: For each tangent line, is the curve rising, falling, or flat? What is the connection between the sign of the slope and the curve’s direction?

Point Slope Meaning
$x = -1.5$ $-3$ Negative ↓ — curve is falling
$x = 0$ $0$ Zero — curve is flat (minimum!)
$x = 1.5$ $3$ Positive ↑ — curve is rising

Your turn: Complete this table from what you just observed. What does the slope tell you about the curve’s direction?

Derivative Slope Curve is…
< 0 ? ?
= 0 ? ?
> 0 ? ?
Derivative Slope Curve is…
< 0 tilts downward ╲ falling
= 0 flat — at a peak or valley
> 0 tilts upward ╱ rising

This is why gradient descent works: if the derivative is positive, moving left decreases the function. If it’s negative, moving right decreases it. If it’s zero, you’re at the bottom.

The derivative doesn’t just tell you how fast — it tells you which direction to go.

Part 9: The Second Derivative

Challenge (skip ahead if you can):

For $y = x^2 - 10x + 5$, find where the derivative equals zero. Is that flat point a minimum or a maximum? Can you figure it out without plotting the curve?

Hint: what happens if you take the “derivative of the derivative”? What does its sign tell you?

Already got it? Skip to the ending. Otherwise, the next slides will guide you.

Consider the function $y = x^2 - 10x + 5$.

Your turn: Find its derivative algebraically using the rules you discovered.

$\dfrac{dy}{dx} = 2x - 10$

Where is $\dfrac{dy}{dx} = 0$?

$2x - 10 = 0 \;\Rightarrow\; x = 5$. That’s where the curve is flat — a candidate for a minimum or maximum. What is $y$ there?

$y = 25 - 50 + 5 = \mathbf{-20}$. The minimum is at $(5, -20)$.

Let’s look at $y$ and $\dfrac{dy}{dx}$ around the minimum. Fill in the table:

$y = x^2 - 10x + 5$   $\dfrac{dy}{dx} = 2x - 10$

$x$ $y$ $\dfrac{dy}{dx}$ Slope direction
$2$???
$4$???
$5$???
$6$???
$8$???

Now check your answers on the next slide.

$x$ $y$ $\dfrac{dy}{dx}$ Slope
$2$ $-11$ $-6$ Negative ╲
$4$ $-19$ $-2$ Negative ╲ (less steep)
$5$ $-20$ $0$ Flat — (minimum)
$6$ $-19$ $+2$ Positive ╱
$8$ $-11$ $+6$ Positive ╱ (steeper)

See the pattern? The slope goes from negative → zero → positive as you cross the minimum.

Let’s see this visually:

The slope is increasing as you move left to right: $-6 \to -2 \to 0 \to +2 \to +6$.

Question: is the rate of change of the slope positive or negative at the minimum?

It’s positive — the slope is increasing. The slope keeps growing from negative through zero to positive.

The “rate of change of the slope” is just the derivative of the derivative — the second derivative:

$\dfrac{d^2 y}{dx^2} = \dfrac{d}{dx}\!\left(\dfrac{dy}{dx}\right)$

Your turn: $\dfrac{dy}{dx} = 2x - 10$. What is $\dfrac{d^2 y}{dx^2}$?

$\dfrac{d^2 y}{dx^2} = \mathbf{2}$ — a positive constant.

Positive second derivative means the slope is always increasing — the curve is bending upward (like a bowl). That guarantees the flat point ($dy/dx = 0$) is a minimum, not a maximum.

To summarize:

At a point where $\dfrac{dy}{dx} = 0$ $\dfrac{d^2y}{dx^2}$ Meaning
slope going ↑ > 0 It’s a minimum (bowl ∪)
slope going ↓ < 0 It’s a maximum (hill ∩)

This is why the second derivative matters in optimization: it tells you whether a flat point is a valley you want to reach or a hilltop you want to avoid.

You computed the second derivative algebraically. Can you also compute it numerically using the diff function you built?

Hint: the second derivative is the derivative of the derivative. You already have a function that computes $\dfrac{dy}{dx}$ — can you write a new function whose output is $\dfrac{dy}{dx}$, and then pass that to diff?

Start with:

def f(x):
    return x**2 - 10*x + 5

def dfdx(x):
    """Return the first derivative of f at x."""
    # YOUR CODE HERE

def d2fdx(x):
    """Return the second derivative of f at x."""
    # YOUR CODE HERE

print(d2fdx(5))    # should be ≈ 2

Check your solution:

def dfdx(x):
    return diff(f, x)

def d2fdx(x):
    return diff(dfdx, x)

print(d2fdx(5))    # ≈ 2

The second derivative of $x^2 - 10x + 5$ is $\mathbf{2}$ everywhere — matching your algebraic answer. The curve always bends upward at the same rate.

What You Just Invented

What you built Its real name
Nudge $x$, measure $\Delta y / \Delta x$ Numerical differentiation
Expand $(x+d)^2$, cancel, drop $d$ Algebraic (analytical) differentiation
$x^n \to nx^{n-1}$ Power rule
Nudge one input, hold the rest Partial derivative
List of all partial derivatives Gradient
Multiply derivatives along a chain Chain rule
Slope of the tangent line Geometric interpretation
Derivative of the derivative Second derivative

Nobody taught you these — you derived them yourself. The next time you see $\nabla$, backprop, or gradient descent, you’ll know exactly what’s happening under the hood.