BRAGA

02 Writing02-02 Notes02-02-311

Gradient of Squared Error

Published 16 Apr 202612 min read
Contents
  1. 01Deep Breakdown
  2. 02Flowchart
  3. 03Real-world use
  4. 04The formula, piece by piece
  5. 05The formula in words
  6. 06Critical Concepts
  7. 07Step-by-step calculation (tiny example)
  8. 08Code examples
∇x∥Ax−b∥2=2AT(Ax−b)\nabla_\mathbf{x} \|A\mathbf{x} - \mathbf{b}\|^2 = 2A^T(A\mathbf{x} - \mathbf{b})
(1)

Deep Breakdown

What it tells me (Situation Awareness): This is the single most important gradient formula in applied machine learning and statistics. It gives the gradient of a squared residual objective L(x)=∥Ax−b∥2=(Ax−b)T(Ax−b)L(\mathbf{x}) = \|A\mathbf{x} - \mathbf{b}\|^2 = (A\mathbf{x} - \mathbf{b})^T(A\mathbf{x} - \mathbf{b}) with respect to the parameter vector x\mathbf{x}. Setting this gradient to zero yields the normal equations ATAx=ATbA^TA\mathbf{x} = A^T\mathbf{b}, whose solution is the OLS estimator x^=(ATA)−1ATb\hat{\mathbf{x}} = (A^TA)^{-1}A^T\mathbf{b}. In ML notation: AA is the design matrix X∈Rn×dX \in \mathbb{R}^{n \times d}, x\mathbf{x} is the weight vector w∈Rd\mathbf{w} \in \mathbb{R}^d, and b\mathbf{b} is the target vector y∈Rn\mathbf{y} \in \mathbb{R}^n. The gradient 2XT(Xw−y)2X^T(X\mathbf{w} - \mathbf{y}) is the cornerstone of linear regression, ridge regression, least squares, and any gradient descent optimization of a quadratic loss. Understanding this gradient from first principles is essential before moving to logistic regression, neural networks, or any nonlinear variant. Note: the file header uses row-vector (numerator-layout) form 2(Ax−b)TA2(Ax-b)^TA; this file uses the equivalent column-vector form 2AT(Ax−b)2A^T(Ax-b), which is what most ML frameworks and textbooks report as the gradient. Both contain the same information.

Flowchart

L(x) = ||Ax -b||^2 = (Ax -b)^T (Ax - b)Let r = Ax - b(residual vectorin R^m)L = r^T r = sumof squaredresidualsdL/dx via chainrule: dL/dx = 2 *r^T * d(Ax-b)/dxd(Ax - b)/dx = A(Jacobian oflinear map)Row vector:dL/dx = 2(Ax -b)^T AColumn vector(gradient):nabla_x L = 2A^T (Ax - b)Set gradient = 0:A^T A x = A^T b(Normalequations)OLS solution:x_hat = (A^TA)^{-1} A^T bGradientdescent: x <- x -alpha * 2 A^T(Ax - b)

Real-world use

Where it is used

Ordinary least squares (OLS) regression: minimize ∥Xw−y∥2\|X\mathbf{w} - \mathbf{y}\|^2 over w\mathbf{w}. Ridge regression: add L2 penalty, gradient becomes 2XT(Xw−y)+2λw2X^T(X\mathbf{w} - \mathbf{y}) + 2\lambda\mathbf{w}. Gradient descent for large-scale linear regression: update w←w−α⋅2nXT(Xw−y)\mathbf{w} \leftarrow \mathbf{w} - \alpha \cdot \frac{2}{n}X^T(X\mathbf{w} - \mathbf{y}). Deriving the normal equations analytically. Weighted least squares, where the objective is ∥W1/2(Xw−y)∥2\|W^{1/2}(X\mathbf{w} - \mathbf{y})\|^2. Output layer gradient of a neural network with MSE loss.

Problem it solves

When you want to minimize a sum-of-squared-errors objective over a vector parameter x\mathbf{x}, you need its gradient to either solve analytically (set gradient = 0) or to run gradient descent. Without this formula, you would have to compute dd partial derivatives individually, which is both inefficient and error-prone for high-dimensional parameter spaces.

How it solves the problem

Expand L=(Ax−b)T(Ax−b)=xTATAx−2bTAx+bTbL = (A\mathbf{x} - \mathbf{b})^T(A\mathbf{x} - \mathbf{b}) = \mathbf{x}^TA^TA\mathbf{x} - 2\mathbf{b}^TA\mathbf{x} + \mathbf{b}^T\mathbf{b}. Differentiate term by term: ∇x(xTATAx)=2ATAx\nabla_\mathbf{x}(\mathbf{x}^TA^TA\mathbf{x}) = 2A^TA\mathbf{x} (symmetric matrix quadratic form), ∇x(−2bTAx)=−2ATb\nabla_\mathbf{x}(-2\mathbf{b}^TA\mathbf{x}) = -2A^T\mathbf{b}, ∇x(bTb)=0\nabla_\mathbf{x}(\mathbf{b}^T\mathbf{b}) = 0. Sum: ∇xL=2ATAx−2ATb=2AT(Ax−b)\nabla_\mathbf{x} L = 2A^TA\mathbf{x} - 2A^T\mathbf{b} = 2A^T(A\mathbf{x} - \mathbf{b}).

Example in a business

A pricing analyst fits a linear model to predict sales volume from price, promotion indicator, and day-of-week dummies. The design matrix X∈Rn×dX \in \mathbb{R}^{n \times d} holds all features; y∈Rn\mathbf{y} \in \mathbb{R}^n holds observed sales. The OLS estimator w^=(XTX)−1XTy\hat{\mathbf{w}} = (X^TX)^{-1}X^T\mathbf{y} follows directly from setting ∇w∥Xw−y∥2=2XT(Xw−y)=0\nabla_\mathbf{w} \|X\mathbf{w} - \mathbf{y}\|^2 = 2X^T(X\mathbf{w} - \mathbf{y}) = \mathbf{0}. For ridge regularization to prevent overfitting on correlated features: w^λ=(XTX+λI)−1XTy\hat{\mathbf{w}}_\lambda = (X^TX + \lambda I)^{-1}X^T\mathbf{y}.

The formula, piece by piece

∇x∥Ax−b∥2=2AT(Ax−b)\nabla_\mathbf{x} \|A\mathbf{x} - \mathbf{b}\|^2 = 2A^T(A\mathbf{x} - \mathbf{b})
(2)

Each symbol:

  • AA: a constant matrix ∈Rm×n\in \mathbb{R}^{m \times n} (e.g., design matrix XX)
  • x\mathbf{x}: the variable vector ∈Rn\in \mathbb{R}^n (e.g., weight vector w\mathbf{w})
  • b\mathbf{b}: a constant vector ∈Rm\in \mathbb{R}^m (e.g., target vector y\mathbf{y})
  • Ax−bA\mathbf{x} - \mathbf{b}: the residual vector r∈Rm\mathbf{r} \in \mathbb{R}^m
  • ∥⋅∥2\|\cdot\|^2: squared Euclidean norm (sum of squared components)
  • ∇x\nabla_\mathbf{x}: gradient with respect to x\mathbf{x}, result is a column vector ∈Rn\in \mathbb{R}^n
  • ATA^T: transpose of AA, shape n×mn \times m — "pulls back" the residual to parameter space Normal equations (set gradient to zero):
ATAx=ATb  ⟹  x^=(ATA)−1ATbA^TA\mathbf{x} = A^T\mathbf{b} \implies \hat{\mathbf{x}} = (A^TA)^{-1}A^T\mathbf{b}
(3)

Row vector form (numerator layout, equivalent):

ddx∥Ax−b∥2=2(Ax−b)TA\frac{d}{d\mathbf{x}}\|A\mathbf{x} - \mathbf{b}\|^2 = 2(A\mathbf{x} - \mathbf{b})^TA
(4)

Ridge variant (L2-regularized):

∇x(∥Ax−b∥2+λ∥x∥2)=2AT(Ax−b)+2λx\nabla_\mathbf{x}\left(\|A\mathbf{x} - \mathbf{b}\|^2 + \lambda\|\mathbf{x}\|^2\right) = 2A^T(A\mathbf{x} - \mathbf{b}) + 2\lambda\mathbf{x}
(5)

MSE version (normalized by nn):

∇w(1n∥Xw−y∥2)=2nXT(Xw−y)\nabla_\mathbf{w}\left(\frac{1}{n}\|X\mathbf{w} - \mathbf{y}\|^2\right) = \frac{2}{n}X^T(X\mathbf{w} - \mathbf{y})
(6)

The formula in words

"The squared error ∥Ax−b∥2\|A\mathbf{x} - \mathbf{b}\|^2 measures how far the prediction AxA\mathbf{x} is from the target b\mathbf{b}. Its gradient with respect to x\mathbf{x} is 2AT2A^T times the residual vector (Ax−b)(A\mathbf{x} - \mathbf{b}). Intuitively: the residual tells you how wrong you are in output space; multiplying by ATA^T maps that error back into parameter space, telling you in which direction to nudge x\mathbf{x} to reduce the error. The factor of 2 comes from differentiating a square."

Critical Concepts

  • Normal equations: setting ∇L=0\nabla L = 0 gives ATAx^=ATbA^TA\hat{\mathbf{x}} = A^T\mathbf{b}. The OLS solution minimizes the squared error exactly (no iteration needed when ATAA^TA is invertible).
  • Gradient descent update: x(t+1)=x(t)−α⋅2AT(Ax(t)−b)\mathbf{x}^{(t+1)} = \mathbf{x}^{(t)} - \alpha \cdot 2A^T(A\mathbf{x}^{(t)} - \mathbf{b}). Used when nn or dd is too large to solve the normal equations directly.
  • Shape check: A∈Rm×nA \in \mathbb{R}^{m \times n}, AT∈Rn×mA^T \in \mathbb{R}^{n \times m}, (Ax−b)∈Rm(A\mathbf{x} - \mathbf{b}) \in \mathbb{R}^m. Product AT(Ax−b)∈RnA^T(A\mathbf{x} - \mathbf{b}) \in \mathbb{R}^n — same shape as x\mathbf{x}. Always verify shapes.
  • ATAA^TA is PSD: the Gram matrix ATAA^TA is always positive semidefinite. If AA has full column rank, ATAA^TA is positive definite and the OLS solution is unique.
  • Ridge adds stability: (ATA+λI)(A^TA + \lambda I) is always positive definite for λ>0\lambda > 0, making the regularized problem always uniquely solvable regardless of AA's rank.
  • Companion: ∇A∥Ax−b∥2=2(Ax−b)xT\nabla_A \|A\mathbf{x} - \mathbf{b}\|^2 = 2(A\mathbf{x} - \mathbf{b})\mathbf{x}^T — gradient with respect to the matrix AA itself.
  • Layout warning: some textbooks (including the original heading) write 2(Ax−b)TA2(Ax-b)^T A (row vector, numerator layout).

The column vector form 2AT(Ax−b)2A^T(Ax-b) is what most ML code expects. Same values, transposed arrangement.

Step-by-step calculation (tiny example)

Let A=[1234]A = \begin{bmatrix}1 & 2 \\ 3 & 4\end{bmatrix}, x=(x1,x2)T\mathbf{x} = (x_1, x_2)^T, b=(1,1)T\mathbf{b} = (1, 1)^T. Compute ∇x∥Ax−b∥2\nabla_\mathbf{x} \|A\mathbf{x} - \mathbf{b}\|^2.

Step 1: Compute the residual symbolically

Ax−b=[x1+2x2−13x1+4x2−1]=[r1r2]A\mathbf{x} - \mathbf{b} = \begin{bmatrix}x_1 + 2x_2 - 1 \\ 3x_1 + 4x_2 - 1\end{bmatrix} = \begin{bmatrix}r_1 \\ r_2\end{bmatrix}
(7)

Step 2: Expand the squared norm and differentiate

L=r12+r22=(x1+2x2−1)2+(3x1+4x2−1)2L = r_1^2 + r_2^2 = (x_1 + 2x_2 - 1)^2 + (3x_1 + 4x_2 - 1)^2
(8)
∂L∂x1=2r1(1)+2r2(3)=2r1+6r2\frac{\partial L}{\partial x_1} = 2r_1(1) + 2r_2(3) = 2r_1 + 6r_2
(9)
∂L∂x2=2r1(2)+2r2(4)=4r1+8r2\frac{\partial L}{\partial x_2} = 2r_1(2) + 2r_2(4) = 4r_1 + 8r_2
(10)

Step 3: Verify against 2ATr2A^T\mathbf{r}

2ATr=2[1324][r1r2]=[2r1+6r24r1+8r2]✓2A^T\mathbf{r} = 2\begin{bmatrix}1 & 3 \\ 2 & 4\end{bmatrix}\begin{bmatrix}r_1 \\ r_2\end{bmatrix} = \begin{bmatrix}2r_1 + 6r_2 \\ 4r_1 + 8r_2\end{bmatrix} \checkmark
(11)

Step 4: Find the minimum (normal equations) Set ATAx=ATbA^TA\mathbf{x} = A^T\mathbf{b}: ATA=[10141420]A^TA = \begin{bmatrix}10 & 14 \\ 14 & 20\end{bmatrix}, ATb=[46]A^T\mathbf{b} = \begin{bmatrix}4 \\ 6\end{bmatrix}. Solve: x^=(ATA)−1ATb\hat{\mathbf{x}} = (A^TA)^{-1}A^T\mathbf{b}.

Code examples

Beginner example (Python)

python
import numpy as np   # A is the design matrix (observations x features), b is the target
A = np.array([[1.0, 2.0], [3.0, 4.0], [5.0, 6.0]])   # 3 data points, 2 features
b = np.array([1.0, 3.0, 5.0])   # targets
x0 = np.array([0.5, 0.5])   # initial guess

def squared_error(x: np.ndarray) -> float:
    """L(x) = ||Ax - b||^2."""
    r = A @ x - b
    return float(r @ r)

def analytic_gradient(x: np.ndarray) -> np.ndarray:
    """nabla_x ||Ax - b||^2 = 2 A^T (Ax - b)."""
    return 2.0 * A.T @ (A @ x - b)

def numerical_gradient(x: np.ndarray, h: float = 1e-5) -> np.ndarray:
    """Centered finite difference."""
    grad = np.zeros_like(x)
    for i in range(len(x)):
        e_i = np.zeros_like(x)
    e_i[i] = h
    grad[i] = (squared_error(x + e_i) - squared_error(x - e_i)) / (2 * h)
    return grad
g_analytic = analytic_gradient(x0)
g_numerical = numerical_gradient(x0)
print("Gradient check at x0:")
print(f" Analytic: {g_analytic}")
print(f" Numerical: {g_numerical}")
print(f" Max error: {np.abs(g_analytic - g_numerical).max():.2e}")   # OLS solution via normal equations: x_hat = (A^T A)^{-1} A^T b
x_hat_ols = np.linalg.solve(A.T @ A, A.T @ b)
print(f"\nOLS solution (normal equations): {x_hat_ols}")
print(f"Gradient at OLS (should be ~0): {analytic_gradient(x_hat_ols)}")   # Compare to numpy lstsq
x_hat_lstsq, _, _, _ = np.linalg.lstsq(A, b, rcond=None)
print(f"np.linalg.lstsq solution: {x_hat_lstsq}")
print(f"Max diff: {np.abs(x_hat_ols - x_hat_lstsq).max():.2e}")   # Gradient descent from x0
ALPHA = 0.01
N_ITER = 200
x_gd = x0.copy()
for _ in range(N_ITER):
    x_gd -= ALPHA * analytic_gradient(x_gd)
print(f"\nGradient descent ({N_ITER} steps): {x_gd}")
print(f"Loss at GD solution: {squared_error(x_gd):.6f}")
print(f"Loss at OLS: {squared_error(x_hat_ols):.6f}")

Beginner example (R)

r
# nabla_x ||Ax - b||^2 = 2 A^T (Ax - b)
A <- matrix(c(1, 3, 5, 2, 4, 6), nrow = 3, ncol = 2)  # column-major
b <- c(1, 3, 5)
x0 <- c(0.5, 0.5)
squared_error <- function(x) sum((A %*% x - b)^2)
analytic_grad <- function(x) 2 * t(A) %*% (A %*% x - b)  # Numerical gradient check
h <- 1e-5
num_grad <- sapply(1:2, function(i) { e_i <- rep(0, 2); e_i[i] <- h (squared_error(x0 + e_i) - squared_error(x0 - e_i)) / (2 * h)
}) cat("Analytic gradient: ", as.vector(analytic_grad(x0)), "\n")
cat("Numerical gradient:", num_grad, "\n")  # OLS normal equations: (A^T A)
x = A^T b
x_hat <- solve(t(A) %*% A, t(A) %*% b)
cat("OLS solution: ", as.vector(x_hat), "\n")
cat("Gradient at OLS (should be ~0):", as.vector(analytic_grad(x_hat)), "\n")  # Ridge regression: (A^T A + lambda I)
x = A^T b
lambda <- 0.1
x_ridge <- solve(t(A) %*% A + lambda * diag(2), t(A) %*% b)
cat("Ridge solution (lambda=0.1): ", as.vector(x_ridge), "\n")

Professional example (Python)

python
"""
Linear regression: OLS vs. gradient descent vs. ridge.
All three methods use nabla_w ||Xw - y||^2 = 2 X^T (Xw - y). Business context: pricing analyst fits weekly_sales as a linear function
of (price, is_promoted, competitor_price, day_of_week encoding).
"""
import numpy as np
from sklearn.datasets import make_regression
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
RANDOM_SEED = 42
rng = np.random.default_rng(RANDOM_SEED)   # Synthetic marketing data
x_raw, y_data = make_regression( n_samples=500, n_features=8, n_informative=5, noise=20.0, random_state=RANDOM_SEED )[:2]
x_train, x_test, y_train, y_test = train_test_split( x_raw, y_data, test_size=0.2, random_state=RANDOM_SEED )
scaler = StandardScaler()
x_train_s = scaler.fit_transform(x_train)
x_test_s = scaler.transform(x_test)   # Add intercept column
x_train_aug = np.hstack([x_train_s, np.ones((len(x_train_s), 1))])
x_test_aug = np.hstack([x_test_s, np.ones((len(x_test_s), 1))])
n, d = x_train_aug.shape

def mse_loss(w: np.ndarray) -> float:
    """MSE loss: (1/n) ||Xw - y||^2."""
    return float(np.mean((x_train_aug @ w - y_train) ** 2))

def mse_gradient(w: np.ndarray) -> np.ndarray:
    """Gradient: (2/n) X^T (Xw - y)."""
    return (2.0 / n) * x_train_aug.T @ (x_train_aug @ w - y_train)   # 1. OLS via normal equations
w_ols = np.linalg.solve(x_train_aug.T @ x_train_aug, x_train_aug.T @ y_train)
mse_ols_test = float(np.mean((x_test_aug @ w_ols - y_test) ** 2))   # 2. Gradient descent
ALPHA = 0.1
N_ITER = 1000
w_gd = rng.standard_normal(d) * 0.01
for _ in range(N_ITER):
    w_gd = w_gd - ALPHA * mse_gradient(w_gd)
mse_gd_test = float(np.mean((x_test_aug @ w_gd - y_test) ** 2))   # 3. Ridge: gradient = 2X^T(Xw-y) + 2*lambda*w -> normal eqs: (X^T X + lambda I) w = X^T y
LAMBDA_RIDGE = 1.0
w_ridge = np.linalg.solve( x_train_aug.T @ x_train_aug + LAMBDA_RIDGE * np.eye(d), x_train_aug.T @ y_train,
)
mse_ridge_test = float(np.mean((x_test_aug @ w_ridge - y_test) ** 2))
grad_norm_ols = float(np.linalg.norm(mse_gradient(w_ols)))
grad_norm_gd = float(np.linalg.norm(mse_gradient(w_gd)))
print("=== Linear Regression: Gradient of Squared Error ===")
print(f" Formula: nabla_w ||Xw - y||^2 = 2 X^T (Xw - y)")
print()
print(f" {'Method':<22} {'Test MSE':>10} {'Grad Norm':>12}")
print(f" {'-'*46}")
print(f" {'OLS (normal eqs)':<22} {mse_ols_test:>10.4f} {grad_norm_ols:>12.2e}")
print(f" {'GD (1000 steps)':<22} {mse_gd_test:>10.4f} {grad_norm_gd:>12.2e}")
print(f" {'Ridge (lambda=1.0)':<22} {mse_ridge_test:>10.4f} {'N/A':>12}")
print()
print(f" Max coef diff OLS vs GD: {np.abs(w_ols - w_gd).max():.4f}")

Source: MML1 p. 237

#calculus#multivariable-calculus-and-matrix-calculus#matrix-calculus-identities-and-automatic-differentiation

Keyboard shortcuts

Single keys, ignored while typing in a field or with Cmd, Ctrl or Alt held.

0
Home
1 2 3 4
Work, Writing, Tools, About
j / k
Next / previous section on this page
n / p
Next / previous project or essay
u
Up one level
l
Deutsch
t
Light or dark theme
?
This list
Esc
Close