BRAGA

02 Writing02-02 Notes02-02-260

Sum Rule

Published 16 Apr 20269 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
ddx[u±v]=dudx±dvdx\frac{d}{dx}[u \pm v] = \frac{du}{dx} \pm \frac{dv}{dx}
(1)

Deep Breakdown

What it tells me (Situation Awareness): The sum (and difference) rule states that differentiation distributes over addition: the derivative of a sum is the sum of the derivatives. Together with the scalar multiplication rule, this establishes that d/dxd/dx is a linear operator. In DA/DS: every multi-term loss function (MSE + regularization, cross-entropy + label smoothing, primary task loss + auxiliary task loss) has its gradient computed as the sum of the individual gradients; parameter update formulas like ∇L=∇Ldata+∇Lreg\nabla L = \nabla L_{\text{data}} + \nabla L_{\text{reg}} use this rule directly; differentiating polynomial features like x3+2x2−x+5x^3 + 2x^2 - x + 5 applies the sum rule term by term.

Flowchart

h(x) = u(x) + v(x)First principles:[h(x+h_step) -h(x)] / h_step= [u(x+h_step) +v(x+h_step) -u(x) - v(x)] /h_step=[u(x+h_step)-u(x)]/h_step +[v(x+h_step)-v(x)]/h_steplim - u'(x) + v'(x)d/dx[u+v] = u' +v'Difference:d/dx[u-v] = u' - v'(same rule, vscaled by -1)Extension:d/dx[u+v+w+...]= u'+v'+w'+...(finite sum)

Real-world use

Where it is used

Gradient of regularized loss: ∇w[Ldata+λR(w)]=∇wLdata+λ∇wR(w)\nabla_w[L_{\text{data}} + \lambda R(w)] = \nabla_w L_{\text{data}} + \lambda \nabla_w R(w); gradient of polynomial regression model output y^=w0+w1x+w2x2\hat{y} = w_0 + w_1 x + w_2 x^2; gradient of cross-entropy with label smoothing: ∇[(1−ϵ)H+ϵHuniform]=(1−ϵ)∇H+ϵ∇Huniform\nabla[(1-\epsilon)H + \epsilon H_{\text{uniform}}] = (1-\epsilon)\nabla H + \epsilon \nabla H_{\text{uniform}}; any situation where a loss combines multiple components.

Problem it solves

When a function is built from a sum of simpler functions, it would be tedious to differentiate the combined expression from scratch each time. The sum rule allows each term to be differentiated independently and the results added together.

How it solves the problem

From first principles: [(u(x+h)+v(x+h))−(u(x)+v(x))]/h=[u(x+h)−u(x)]/h+[v(x+h)−v(x)]/h[(u(x+h)+v(x+h)) - (u(x)+v(x))]/h = [u(x+h)-u(x)]/h + [v(x+h)-v(x)]/h. The limit distributes over the sum (the limit of a sum is the sum of the limits, when both limits exist).

Example in a business

A DS uses a composite loss: L=LMSE+0.1LMAEL = L_{\text{MSE}} + 0.1 L_{\text{MAE}}, where LMSE=(1/N)∥y−y^∥2L_{\text{MSE}} = (1/N)\|y - \hat{y}\|^2 and LMAE=(1/N)∑i∣yi−y^i∣L_{\text{MAE}} = (1/N)\sum_i |y_i - \hat{y}_i|. The gradient: ∇L=∇LMSE+0.1∇LMAE\nabla L = \nabla L_{\text{MSE}} + 0.1 \nabla L_{\text{MAE}}. Each component's gradient is computed independently, then added. The sum rule is the justification.

The formula, piece by piece

  • uu: first differentiable function of xx
  • vv: second differentiable function of xx
  • u±vu \pm v: their sum or difference
  • du/dx±dv/dxdu/dx \pm dv/dx: the derivative of the sum equals the sum of the derivatives
  • Proof mechanism: limit distributes over addition
  • Extension to nn terms: d/dx[u1+u2+…+un]=u1′+u2′+…+un′d/dx[u_1 + u_2 + \ldots + u_n] = u_1' + u_2' + \ldots + u_n'
  • Combined linearity: d/dx[au+bv]=au′+bv′d/dx[au + bv] = au' + bv' (sum + scalar rules together)
  • Note: does NOT hold for products (d/dx[uv]≠u′v′d/dx[uv] \ne u'v') — that needs the product rule

The formula in words

"The derivative of a sum is the sum of the derivatives. You can break a function into pieces, differentiate each piece separately, and add the results. This works because differentiation is a linear operation." Tiny examples: d/dx(x3+x2)=3x2+2xd/dx(x^3 + x^2) = 3x^2 + 2x. d/dx(sin⁡x+ex)=cos⁡x+exd/dx(\sin x + e^x) = \cos x + e^x. d/dx(x2−ln⁡x)=2x−1/xd/dx(x^2 - \ln x) = 2x - 1/x. d/dx(2x3+5x−7)=6x2+5−0=6x2+5d/dx(2x^3 + 5x - 7) = 6x^2 + 5 - 0 = 6x^2 + 5 (constant rule used too).

Critical Concepts

  • Linearity of the derivative: sum rule + scalar rule = linearity. d/dx[af+bg]=af′+bg′d/dx[af + bg] = af' + bg' for constants aa, bb. This is one of the most important structural properties of the derivative, shared by integrals, expectations, and many other operators in mathematics.
  • Every multi-term loss gradient uses this: if L=L1+L2+L3L = L_1 + L_2 + L_3, then ∇L=∇L1+∇L2+∇L3\nabla L = \nabla L_1 + \nabla L_2 + \nabla L_3. No approximation, no interaction terms. This additivity is why gradient computation can be parallelized across loss components.
  • Difference rule is the same rule: d/dx[u−v]=d/dx[u+(−1)v]=u′+(−1)v′=u′−v′d/dx[u - v] = d/dx[u + (-1)v] = u' + (-1)v' = u' - v'. The minus sign is just the scalar k=−1k = -1 case.
  • Infinite sums (series) require more care: the sum rule holds for finite sums. For infinite sums (power series, Fourier series), additional conditions (uniform convergence) are needed before differentiating term by term.
  • Gradient additivity in code: the automatic differentiation engines (PyTorch, TensorFlow/JAX) exploit the sum rule.

When a computation graph adds two tensors, the backward pass routes the upstream gradient to both branches unchanged. This is the sum rule implemented in reverse mode AD.

Step-by-step calculation (tiny example)

Differentiate f(x)=5x4−3x2+2x−1f(x) = 5x^4 - 3x^2 + 2x - 1.

Step 1: Apply sum rule — differentiate each term. f′(x)=d/dx(5x4)−d/dx(3x2)+d/dx(2x)−d/dx(1)f'(x) = d/dx(5x^4) - d/dx(3x^2) + d/dx(2x) - d/dx(1).

Step 2: Scalar + power rule on each term. d/dx(5x4)=20x3d/dx(5x^4) = 20x^3. d/dx(3x2)=6xd/dx(3x^2) = 6x. d/dx(2x)=2d/dx(2x) = 2. d/dx(1)=0d/dx(1) = 0.

Step 3: Combine. f′(x)=20x3−6x+2f'(x) = 20x^3 - 6x + 2. At x=1x = 1: f′(1)=20−6+2=16f'(1) = 20 - 6 + 2 = 16.

Code examples

Beginner example (Python)

python
import numpy as np

def f(x: float) -> float:
    """f(x) = 5x^4 - 3x^2 + 2x - 1."""
    return 5*x**4 - 3*x**2 + 2*x - 1

def f_prime(x: float) -> float:
    """f'(x) = 20x^3 - 6x + 2 (sum rule applied term by term)."""
    return 20*x**3 - 6*x + 2


# Verify numerically
h = 1e-7
x_vals = [-2.0, -1.0, 0.0, 1.0, 2.0]
analytic_label = "Analytic f'(x)"
print(f"{'x':>6} {analytic_label:>16} {'Numerical':>12} {'Match':>7}")
for x in x_vals:
    analytic = f_prime(x)
    numerical = (f(x + h) - f(x - h)) / (2 * h)
    match = abs(analytic - numerical) < 1e-5
    print(f"{x:>6.1f} {analytic:>16.6f} {numerical:>12.6f} {str(match):>7}")

# Multi-component loss gradient: sum rule
print("\nSum rule for multi-component loss gradient:")
y = np.array([1.0, 2.0, 3.0, 4.0])
y_pred = np.array([1.2, 1.8, 3.3, 3.7])
grad_mse = 2 * np.mean(y_pred - y)   # d/dpred(MSE)
grad_mae = np.mean(np.sign(y_pred - y))   # d/dpred(MAE) via subgradient
ALPHA, BETA = 0.7, 0.3
grad_combined = ALPHA * grad_mse + BETA * grad_mae
print(f" grad_MSE = {grad_mse:.4f}")
print(f" grad_MAE = {grad_mae:.4f}")
print(f" grad_combined (0.7*MSE + 0.3*MAE) = {grad_combined:.4f}")
print(f" Key: sum rule gives grad = alpha*grad_A + beta*grad_B")

Beginner example (R)

r
# Sum rule: d/dx[u + v] = u' + v'
f <- function(x) 5*x^4 - 3*x^2 + 2*x - 1
f_prime <- function(x) 20*x^3 - 6*x + 2
h <- 1e-7
x_vals <- c(-2, -1, 0, 1, 2)
cat(sprintf("%-6s %-16s %-12s\n", "x", "Analytic f'(x)", "Numerical"))
for (x in x_vals) {
  numerical <- (f(x + h) - f(x - h)) / (2 * h)
  cat(sprintf("%-6.1f %-16.6f %-12.6f\n", x, f_prime(x), numerical))
}

# Regularized loss gradient: sum rule
cat("\nRegularized loss gradient = gradient_data + lambda * gradient_reg\n")
w <- c(1.0, -0.5, 2.0)
grad_data <- c(-0.3, 0.1, -0.2)  # hypothetical data gradient
grad_reg <- 2 * w  # L2 gradient
lambda <- 0.1
grad_total <- grad_data + lambda * grad_reg
cat(sprintf("grad_data: %.4f %.4f %.4f\n", grad_data[1], grad_data[2], grad_data[3]))
cat(sprintf("grad_reg: %.4f %.4f %.4f\n", grad_reg[1], grad_reg[2], grad_reg[3]))
cat(sprintf("grad_total: %.4f %.4f %.4f\n", grad_total[1], grad_total[2], grad_total[3]))

Professional example (Python)

python
import numpy as np
from sklearn.datasets import make_regression, make_classification
from sklearn.preprocessing import StandardScaler
import functools
np.random.seed(42)

# -- Sum rule: gradient of composite loss (regression + auxiliary classification) --
# Use case: a DS trains a model with a primary MSE loss and an auxiliary
# binary classification loss. Gradient uses sum rule component-by-component.
N, D = 400, 5
X_raw = np.random.randn(N, D)
scaler = StandardScaler()
X = scaler.fit_transform(X_raw)
w_true = np.array([2.0, -1.5, 0.5, 1.0, -0.3])
y_reg = X @ w_true + np.random.randn(N) * 0.5   # regression target
y_cls = (X @ w_true > np.median(X @ w_true)).astype(float)   # classification target

def sigmoid(z: np.ndarray) -> np.ndarray:
    return np.where(z >= 0, 1 / (1 + np.exp(-z)), np.exp(z) / (1 + np.exp(z)))

def mse_gradient(w: np.ndarray, X: np.ndarray, y: np.ndarray) -> np.ndarray:
    """Gradient of (1/N)||y - Xw||^2 with respect to w."""
    residuals = y - X @ w
    return -2.0 / N * X.T @ residuals

def bce_gradient(w: np.ndarray, X: np.ndarray, y: np.ndarray) -> np.ndarray:
    """Gradient of binary cross-entropy loss with respect to w."""
    p = sigmoid(X @ w)
    return X.T @ (p - y) / N

def composite_gradient(
    w: np.ndarray,
    X: np.ndarray,
    y_reg: np.ndarray,
    y_cls: np.ndarray,
    alpha: float,
    beta: float,
) -> np.ndarray:
    """grad(alpha*MSE + beta*BCE) = alpha*grad_MSE + beta*grad_BCE (sum rule)."""
    g_mse = mse_gradient(w, X, y_reg)
    g_bce = bce_gradient(w, X, y_cls)
    return alpha * g_mse + beta * g_bce


# Compare: gradient descent with only MSE vs composite loss
ALPHA = 0.6
BETA = 0.4
LR = 0.05
N_ITER = 500
w_mse_only = np.zeros(D)
w_composite = np.zeros(D)
for _ in range(N_ITER):
    w_mse_only -= LR * mse_gradient(w_mse_only, X, y_reg)
    w_composite -= LR * composite_gradient(w_composite, X, y_reg, y_cls, ALPHA, BETA)
print("Sum Rule: gradient of composite loss (MSE + BCE)")
print(f"\nalpha={ALPHA}, beta={BETA}")
print(f"grad(alpha*L_MSE + beta*L_BCE) = alpha*grad_MSE + beta*grad_BCE\n")
print(f"{'Param':>8} {'w_true':>10} {'w_mse_only':>12} {'w_composite':>13}")
for j in range(D):
    print(f"{'w['+str(j)+']':>8} {w_true[j]:>10.4f} {w_mse_only[j]:>12.4f} {w_composite[j]:>13.4f}")

# Final gradient decomposition at composite solution
g_mse_final = mse_gradient(w_composite, X, y_reg)
g_bce_final = bce_gradient(w_composite, X, y_cls)
g_total = ALPHA * g_mse_final + BETA * g_bce_final
print(f"\nFinal gradient norm: {np.linalg.norm(g_total):.6f}")
print(f"MSE component norm: {np.linalg.norm(g_mse_final):.6f}")
print(f"BCE component norm: {np.linalg.norm(g_bce_final):.6f}")

Source: 1300 p. 218

#calculus#differential-calculus#definition-and-properties-of-the-derivative

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