Welcome back. In the previous lesson, a dot product turned feature values and weights into a single score. Here, we use that same operation in a new role: it explains why the gradient tells us which small parameter change will increase or decrease a function most quickly.
You will treat a two-variable function as a local landscape, estimate its slopes numerically without differentiating it symbolically, combine those estimates into a gradient vector, and choose a step that lowers the function. This is the core calculation behind gradient descent, which you will implement more fully later in Month 1.
Partial derivatives: change one coordinate, hold the other fixed
Suppose a function depends on two inputs:
At a particular point , the partial derivative with respect to asks:
If changes slightly while stays fixed, how quickly does change?
Likewise, the partial derivative with respect to changes only , holding fixed.
For a loss function in machine learning, you can interpret and as two model parameters. Each partial derivative measures how sensitive the loss is to one parameter, assuming the other is temporarily unchanged.
For example, let
and evaluate it at:
The function value there is:
Rather than using calculus to obtain an exact derivative, we will estimate each slope by probing nearby points.
Finite differences: estimate a slope from nearby function values
A finite difference replaces an infinitesimal change with a small, concrete step . In one dimension, it approximates a tangent slope by a secant slope.
For the partial derivative with respect to , keep constant and move only in the direction.
Forward difference
This compares the current point with one point “forward” in the direction.
Backward difference
This uses the point behind the current position.
Central difference
Central difference samples on both sides of the target point. For smooth functions, it is usually the preferred numerical estimate because its approximation error decreases more rapidly as becomes smaller.
The same pattern applies to :

For a concise visual derivation of why central differences are typically more accurate than one-sided estimates, watch this segment.
Numerical Differentiation with Finite Difference Derivatives
Numerical Differentiation with Finite Difference Derivatives by Steve Brunton derives forward, backward, and central difference estimates and explains why the symmetric central estimate cancels more error.
Watch central differences. Focus on the symmetry of evaluating the function at both t+h and t-h, and on the conclusion that central-difference error is proportional to h^2, rather than h.
A note on choosing
Choosing involves a practical trade-off:
- If is too large, the secant line spans too much curvature and is a poor local approximation.
- If is extremely small, floating-point rounding can dominate the subtraction of nearly equal values.
For the small, well-scaled examples in this course, values such as 1e-4 or 1e-5 are sensible starting points. Numerical gradients are especially useful for checking an implementation; later, analytic gradients will usually be faster for actual model training.
Estimating two partial derivatives at one point
Return to:
at . Let .
To estimate the -partial derivative, change while keeping :
The two function values are:
Therefore:
So a small positive move in decreases : the local -slope is negative.
Now vary while keeping :
Here, increasing increases , so the -slope is positive.
These two values are the components of the gradient.
Assemble the gradient and reverse it to descend
For a two-variable function, the gradient is:
At , our finite-difference estimates give:
The gradient points in the local direction of steepest increase. Therefore, its negative points in the local direction of steepest decrease:
This tells us to increase and decrease .
The connection to the prior dot-product lesson is precise. For a small position change ,
If we choose:
where is a small step size, then:
This is negative whenever the gradient is nonzero. Thus, for a sufficiently small , the function should decrease locally.
Using :
The loss falls from:
to:
The direction was right; the step successfully moved downhill.
A zero gradient is a special case: it means there is no first-order uphill or downhill direction at that exact point. It may be a minimum, a maximum, or a saddle point, so zero gradient alone does not prove that a function is minimized.
Numerical gradients in NumPy
The CS231n notes provide a general pattern for numerical gradients: alter one coordinate, evaluate the function, restore the original coordinate, then repeat for each coordinate.
CS231n Deep Learning for Computer Vision
Read the numerical-gradient pattern and its connection to negative-gradient updates. The code is written for arbitrary arrays, but the underlying process is exactly the two-coordinate calculation from this lesson.
In the “Computing the gradient” section, read the finite difference explanation. Notice that one array entry is perturbed at a time, so every output entry of grad is one partial derivative. Then continue to the next discussion, beginning the negative gradient update. Focus on why the update subtracts the gradient and why a larger step size can increase loss rather than decrease it.
In practice, use .copy() when making perturbed versions of a parameter vector. This avoids accidentally changing the original evaluation point and corrupting later estimates.
Concept-Level Micro-Challenge: central-difference gradient and one descent step
Type and run this 15-line NumPy program. It estimates both partial derivatives using central differences, then takes one negative-gradient step.
import numpy as np
def loss(p):
x, y = p
return (x - 3)**2 + 2 * (y + 1)**2
p = np.array([0.0, 2.0]); h = 1e-4
grad = np.zeros_like(p)
for j in range(p.size):
plus = p.copy()
minus = p.copy()
plus[j] += h; minus[j] -= h
grad[j] = (loss(plus) - loss(minus)) / (2 * h)
p_new = p - 0.1 * grad
print("gradient:", grad, "old/new loss:", loss(p), loss(p_new))
assert np.allclose(grad, [-6.0, 12.0], atol=1e-6)
assert loss(p_new) < loss(p)
Your expected gradient is approximately:
Read the loop carefully:
- At
j = 0, only the first coordinate changes, so the code estimates . - At
j = 1, only the second coordinate changes, so it estimates . p - 0.1 * gradmoves in the negative-gradient direction.
As a brief self-check, change the final update to p + 0.1 * grad. The assertion that the loss decreases should fail, because this update deliberately moves uphill.
Common mistakes to catch early
-
Changing both variables for one partial derivative.
To estimate , alter onlyp[0]; keepp[1]fixed. Changing both coordinates estimates movement along a diagonal, not a partial derivative. -
Forgetting the denominator in central difference.
The two samples are apart, not apart. -
Using the gradient as a descent direction.
The gradient points uphill. Use-grador subtractlearning_rate * grad. -
Taking a step that is too large.
A gradient is local information. A direction can be correct while an oversized step overshoots into a higher-loss region. -
Mutating the base point accidentally.
Useplus = p.copy()andminus = p.copy(). If the base point changes inside the loop, the partial derivatives no longer refer to the same location.
Takeaways
A partial derivative measures local change along one coordinate while all other coordinates remain fixed. Finite differences approximate that derivative using nearby function values; central difference is usually the strongest default:
For a two-variable function, assemble both estimates into the gradient:
The gradient points toward local steepest increase. Its negative gives a local descent direction, and a small update of the form
should reduce the function when the step size is appropriate.
Next, you will switch from optimization math to probability, calculating conditional probabilities and applying Bayes’ rule in a compact diagnostic example.
Can't find a good explanation? Sign up and we'll make it for you
Sign up