BRAGA

02 Writing02-02 Notes02-02-241

Newton-Raphson Method

Published 16 Apr 202611 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
xn+1=xn−f(xn)f′(xn)x_{n+1} = x_n - \frac{f(x_n)}{f'(x_n)}
(1)

Deep Breakdown

What it tells me (Situation Awareness): The Newton-Raphson method is a root-finding algorithm: it finds x∗x^* such that f(x∗)=0f(x^*) = 0 by iteratively refining an estimate using the tangent line. At each step, it linearizes ff around xnx_n and takes the zero of that linear approximation as the next estimate. Convergence is quadratic near the root (error squares at each step) — far faster than bisection (O(2−n)O(2^{-n})) or gradient descent (O(1/n)O(1/n)). In optimization, Newton's method for min⁡f(x)\min f(x) applies Newton-Raphson to the derivative equation f′(x)=0f'(x) = 0: the update becomes xn+1=xn−f′(xn)/f′′(xn)x_{n+1} = x_n - f'(x_n)/f''(x_n). In multivariate optimization: xn+1=xn−[∇2f(xn)]−1∇f(xn)x_{n+1} = x_n - [\nabla^2 f(x_n)]^{-1} \nabla f(x_n) (Newton's method using the Hessian). In DA/DS: Newton-Raphson is used in logistic regression fitting (IRLS — Iteratively Reweighted Least Squares), GLM estimation, maximum likelihood estimation of distribution parameters, and as the basis of quasi-Newton methods (L-BFGS) used in scipy and sklearn.

Flowchart

YESNOYESNOChoose initialguess x_0 (nearroot)Evaluate: f(x_n)and f'(x_n)|f'(x_n)| < tol?(near-zeroderivative)FAIL: derivativetoo small,method divergesUpdate: x_{n+1}= x_n - f(x_n) /f'(x_n)|f(x_{n+1})| < tolor |x_{n+1} -x_n| < tol?Return x* =x_{n+1} (rootfound)n = n + 1Geometricinterpretation:tangent line at(x_n, f(x_n))intersects x-axisat x_{n+1}

Real-world use

Where it is used

Logistic regression MLE via IRLS (Newton-Raphson applied to score equations); GLM parameter estimation in R (glm() uses IRLS internally); distribution parameter fitting (MLE of Beta, Gamma, Weibull shapes); root-finding for quantile functions; scipy.optimize.newton for scalar root-finding; as the basis of L-BFGS (limited-memory quasi-Newton) used in sklearn.LogisticRegression(solver='lbfgs').

Problem it solves

Gradient descent for optimization (min⁡xf(x)\min_x f(x)) converges at rate O(1/n)O(1/n) for convex ff. Newton's method (applied to f′=0f' = 0) converges quadratically: ∣xn+1−x∗∣≤C∣xn−x∗∣2|x_{n+1} - x^*| \le C|x_n - x^*|^2. For ML problems where high-precision parameter estimates are needed (GLMs, MLE fitting), Newton-Raphson converges in far fewer iterations than gradient descent, at the cost of computing the second derivative (Hessian).

How it solves the problem

Taylor expand ff around xnx_n: f(x)≈f(xn)+f′(xn)(x−xn)f(x) \approx f(x_n) + f'(x_n)(x-x_n). Setting this to zero: 0=f(xn)+f′(xn)(x∗−xn)0 = f(x_n) + f'(x_n)(x^* - x_n), giving x∗≈xn−f(xn)/f′(xn)x^* \approx x_n - f(x_n)/f'(x_n). Geometrically: draw the tangent to ff at xnx_n; the next iterate is where that tangent crosses the x-axis. Each iteration doubles the number of correct digits near the root (quadratic convergence).

Example in a business

A DS fits a logistic regression on 1M rows of fraud detection data. sklearn.LogisticRegression(solver='lbfgs') uses L-BFGS (a quasi-Newton method approximating the Hessian): converges in ~50 iterations. Plain gradient descent would require thousands of iterations for the same precision. The closed-form score equation for logistic regression is ∇wℓ=XT(y−p)\nabla_w \ell = X^T(y - p) and Hessian H=XTWXH = X^T W X where W=diag(p(1−p))W = \text{diag}(p(1-p)); IRLS = Newton-Raphson on this system.

The formula, piece by piece

  • xn+1x_{n+1}: the updated estimate of the root after iteration nn
  • xnx_n: the current estimate of the root at iteration nn
  • f(xn)f(x_n): value of the function at current estimate; should approach 0
  • f′(xn)f'(x_n): derivative of ff at current estimate; the slope of the tangent line
  • f(xn)/f′(xn)f(x_n)/f'(x_n): the step size; how far to move from xnx_n toward the root
  • −f(xn)/f′(xn)-f(x_n)/f'(x_n): the update; subtract to move in the direction that zeroes ff
  • For optimization (find zero of f′f'): replace ff with f′f' and f′f' with f′′f'': xn+1=xn−f′(xn)/f′′(xn)x_{n+1} = x_n - f'(x_n)/f''(x_n)
  • Multivariate: xn+1=xn−[∇2f(xn)]−1∇f(xn)x_{n+1} = x_n - [\nabla^2 f(x_n)]^{-1} \nabla f(x_n) (Newton step for optimization)
  • Convergence rate: quadratic near root; ∣en+1∣≈∣f′′(x∗)∣2∣f′(x∗)∣∣en∣2|e_{n+1}| \approx \frac{|f''(x^*)|}{2|f'(x^*)|} |e_n|^2 where en=xn−x∗e_n = x_n - x^*
  • Failure modes: f′(xn)=0f'(x_n) = 0 (vertical tangent); convergence to wrong root; divergence if initial guess too far

The formula in words

"Given a current guess xnx_n for where f(x)=0f(x)=0: draw the tangent line to ff at xnx_n and find where that line crosses the x-axis. That crossing point is the next (better) guess. Repeat until the guess stops changing." Tiny example: find root of f(x)=x2−2f(x) = x^2 - 2 (i.e., find 2\sqrt{2}). f′(x)=2xf'(x) = 2x. Start: x0=1x_0 = 1. x1=1−(1−2)/(2)=1+0.5=1.5x_1 = 1 - (1-2)/(2) = 1 + 0.5 = 1.5. x2=1.5−(1.52−2)/(2⋅1.5)=1.5−(2.25−2)/3=1.5−0.0833=1.4167x_2 = 1.5 - (1.5^2 - 2)/(2 \cdot 1.5) = 1.5 - (2.25-2)/3 = 1.5 - 0.0833 = 1.4167. x3=1.4167−(1.41672−2)/(2⋅1.4167)=1.4167−0.00174=1.41421x_3 = 1.4167 - (1.4167^2-2)/(2\cdot1.4167) = 1.4167 - 0.00174 = 1.41421. True 2=1.41421\sqrt{2} = 1.41421. Three iterations; already 5-digit precision. ✓\checkmark

Critical Concepts

  • Quadratic vs linear convergence: gradient descent on f′(x)=0f'(x) = 0 converges linearly (error multiplied by constant <1< 1 each step). Newton converges quadratically: error squared each step. For ∣e0∣=0.1|e_0| = 0.1: GD needs ~10n10n steps; Newton needs ~log⁡2log⁡2(1/tol)\log_2 \log_2(1/\text{tol}) steps.
  • Hessian cost in high dimensions: the multivariate Newton step requires inverting an d×dd \times d Hessian — O(d3)O(d^3) cost. For d=108d = 10^8 (large neural net), this is infeasible. L-BFGS approximates the inverse Hessian using mm recent gradient pairs (O(md)O(md) cost), making quasi-Newton practical for moderate dd.
  • IRLS for logistic regression: Newton-Raphson on the logistic log-likelihood leads to the IRLS algorithm: at each iteration, solve a weighted least squares problem XTWXβ=XTWzX^TWX\beta = X^TWz where WW and zz depend on current predictions. This is what glm() in R and scipy's logistic regression solvers use.
  • Saddle points and Newton: in non-convex objectives (deep learning), f′′(x)<0f''(x) < 0 (negative curvature) causes Newton to move toward a saddle point or maximum, not a minimum. Gradient descent's behavior near saddle points is preferable. This is why Newton's method is not used for raw deep learning training.
  • Secant method: approximates f′(xn)f'(x_n) by finite difference when f′f' is not available: xn+1=xn−f(xn)(xn−xn−1)/(f(xn)−f(xn−1))x_{n+1} = x_n - f(x_n)(x_n - x_{n-1})/(f(x_n)-f(x_{n-1})).

Superlinear convergence (order ≈1.618\approx 1.618, the golden ratio). Used when exact derivatives are expensive.

Step-by-step calculation (tiny example)

Find the root of f(x)=ex−3f(x) = e^x - 3 using Newton-Raphson. f′(x)=exf'(x) = e^x. Start: x0=1x_0 = 1. True root: x∗=ln⁡(3)≈1.0986x^* = \ln(3) \approx 1.0986. | nn | xnx_n

f(xn)=exn−3f(x_n) = e^{x_n}-3 f′(xn)=exnf'(x_n) = e^{x_n} xn+1=xn−f/f′x_{n+1} = x_n - f/f' $ x_n - x^* $
0 1.0000 -0.2817 2.7183 1.1036 0.0986
1 1.1036 0.0147 3.0147 1.0987 0.0050
2 1.0987 0.000044 3.000044 1.09861 0.000014

Error reduces from ~0.1 to ~0.005 to ~0.00001: quadratic convergence visible.

Code examples

Beginner example (Python)

python
import numpy as np

def newton_raphson(
    func, func_deriv, x_init: float, tol: float = 1e-10, max_iter: int = 50,
) -> float:
    """Newton-Raphson root finder: solve f(x) = 0."""
    x = x_init
    for iteration in range(max_iter):
        f_val = func(x)
        f_prime = func_deriv(x)
        if abs(f_prime) < 1e-14:
            raise ValueError(f"Derivative too small at x={x}; method diverges.")
        x_new = x - f_val / f_prime
        if abs(x_new - x) < tol:
            print(f" Converged at iteration {iteration + 1}")
            return x_new
        x = x_new
    raise RuntimeError(f"Newton-Raphson did not converge in {max_iter} iterations.")


# Example 1: find sqrt(2) via f(x) = x^2 - 2
print("=== Finding sqrt(2): f(x) = x^2 - 2 ===")
x_star = newton_raphson(
    func=lambda x: x**2 - 2, func_deriv=lambda x: 2 * x, x_init=1.0,
)
print(f"x* = {x_star:.15f}")
print(f"True sqrt(2) = {np.sqrt(2):.15f}")
print(f"Error = {abs(x_star - np.sqrt(2)):.2e}")

# Example 2: solve e^x = 3 (find ln(3))
print("\n=== Finding ln(3): f(x) = e^x - 3 ===")
x_star2 = newton_raphson(
    func=lambda x: np.exp(x) - 3, func_deriv=lambda x: np.exp(x), x_init=1.0,
)
print(f"x* = {x_star2:.15f}")
print(f"True ln(3) = {np.log(3):.15f}")

# Example 3: Newton's method for optimization: minimize f(x) = x^4 - 4x^2
# Apply NR to f'(x) = 4x^3 - 8x, f''(x) = 12x^2 - 8
print("\n=== Minimizing f(x) = x^4 - 4x^2 (finding zero of f') ===")
x_opt = newton_raphson(
    func=lambda x: 4*x**3 - 8*x,         # f'(x)
    func_deriv=lambda x: 12*x**2 - 8,    # f''(x)
    x_init=1.5,                          # start near positive minimum at x = sqrt(2)
)
print(f"x* = {x_opt:.10f} (true: {np.sqrt(2):.10f})")
print(f"f(x*) = {x_opt**4 - 4*x_opt**2:.8f} (true: -4)")

Beginner example (R)

r
# Newton-Raphson root finding: x_{n+1} = x_n - f(x_n) / f'(x_n)
newton_raphson <- function(func, func_deriv, x_init, tol = 1e-10, max_iter = 50) {
  x <- x_init
  for (i in seq_len(max_iter)) {
    f_val <- func(x)
    f_prime <- func_deriv(x)
    if (abs(f_prime) < 1e-14) stop(sprintf("Derivative too small at x=%.4f", x))
    x_new <- x - f_val / f_prime
    if (abs(x_new - x) < tol) {
      cat(sprintf(" Converged at iteration %d\n", i))
      return(x_new)
    }
    x <- x_new
  }
  stop("Newton-Raphson did not converge")
}

# Find sqrt(2): f(x) = x^2 - 2
cat("=== Finding sqrt(2) ===\n")
x_star <- newton_raphson(
  func = function(x) x^2 - 2, func_deriv = function(x) 2 * x, x_init = 1.0
)
cat(sprintf("x* = %.15f\n", x_star))
cat(sprintf("True sqrt(2) = %.15f\n", sqrt(2)))
cat(sprintf("Error = %.2e\n", abs(x_star - sqrt(2))))

# Minimizing f(x) = x^4 - 4x^2 by solving f'(x) = 0
cat("\n=== Minimizing f(x) = x^4 - 4x^2 ===\n")
x_opt <- newton_raphson(
  func = function(x) 4*x^3 - 8*x,         # f'(x)
  func_deriv = function(x) 12*x^2 - 8,    # f''(x)
  x_init = 1.5
)
cat(sprintf("x* = %.10f (true: %.10f)\n", x_opt, sqrt(2)))

Professional example (Python)

python
import numpy as np
from scipy.optimize import newton
np.random.seed(42)

# -- IRLS: Newton-Raphson for logistic regression MLE --------------------------
# Logistic regression score equations solved via Newton-Raphson (IRLS)


def sigmoid(z: np.ndarray) -> np.ndarray:
    return 1 / (1 + np.exp(-np.clip(z, -500, 500)))


def irls_logistic_regression(
    X: np.ndarray, y: np.ndarray, max_iter: int = 20, tol: float = 1e-8,
) -> np.ndarray:
    """Iteratively Reweighted Least Squares (IRLS) for logistic regression.

    Newton-Raphson on log-likelihood: w_{n+1} = w_n - H^{-1} grad.
    H = X^T W X (Hessian, where W = diag(p(1-p)))
    grad = X^T (p - y)
    Equivalent to solving WLS: (X^T W X) w = X^T W z, z = Xw + W^{-1}(y-p).
    """
    n, d = X.shape
    w = np.zeros(d)
    for iteration in range(max_iter):
        p = sigmoid(X @ w)
        # Working weights: W = diag(p * (1 - p))
        weights = p * (1 - p)
        weights = np.maximum(weights, 1e-10)   # numerical safety
        # Gradient of negative log-likelihood: X^T (p - y)
        grad = X.T @ (p - y)
        # Hessian: X^T W X
        W_sqrt = np.sqrt(weights)
        X_weighted = X * W_sqrt[:, np.newaxis]   # sqrt(W) X
        hessian = X_weighted.T @ X_weighted       # X^T W X
        # Newton step: w_new = w - H^{-1} grad
        try:
            w_new = w - np.linalg.solve(hessian, grad)
        except np.linalg.LinAlgError:
            break
        if np.linalg.norm(w_new - w) < tol:
            print(f" IRLS converged at iteration {iteration + 1}")
            return w_new
        w = w_new
    return w


# Generate binary classification data
from sklearn.datasets import make_classification
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import roc_auc_score
X_raw, y = make_classification(n_samples=500, n_features=8, n_informative=5, random_state=42)
scaler = StandardScaler()
X = np.hstack([np.ones((len(y), 1)), scaler.fit_transform(X_raw)])   # add bias
print("IRLS Logistic Regression (Newton-Raphson on score equations)")
w_irls = irls_logistic_regression(X, y, max_iter=25)

# Compare to scipy (also Newton-based)
from sklearn.linear_model import LogisticRegression
clf = LogisticRegression(fit_intercept=True, C=1e9, solver="lbfgs", max_iter=1000)
clf.fit(X[:, 1:], y)   # sklearn handles bias separately
auc_irls = roc_auc_score(y, sigmoid(X @ w_irls))
auc_sklearn = roc_auc_score(y, clf.predict_proba(X[:, 1:])[:, 1])
print(f"\nAUC (IRLS / Newton-Raphson): {auc_irls:.4f}")
print(f"AUC (sklearn lbfgs): {auc_sklearn:.4f}")
print(f"\nIRLS converges in <20 steps vs GD which needs >1000 steps.")
print(f"Quadratic convergence of Newton-Raphson is the key advantage.")

# Scalar demo: Newton-Raphson via scipy.optimize.newton
print("\n=== scipy.optimize.newton (scalar root finding) ===")
# Find MLE of Poisson lambda from data: solve d/d_lambda log L = n/lambda - sum(x) = 0
sample_data = np.random.poisson(lam=3.5, size=200)
n_data = len(sample_data)
sum_x = sample_data.sum()
poisson_score = lambda lam: n_data / lam - sum_x   # d/d_lambda log L = 0
poisson_hess = lambda lam: -n_data / lam**2   # second derivative
# Newton on n/lambda - sum(x) converges only for 0 < x0 < 2/mean(x), so start low
lambda_mle = newton(poisson_score, x0=0.5, fprime=poisson_hess)
print(f"Poisson MLE via Newton-Raphson: lambda_hat = {lambda_mle:.6f}")
print(f"Sample mean (analytical MLE): {sample_data.mean():.6f}")
print(f"Difference: {abs(lambda_mle - sample_data.mean()):.2e}")

Source: domain knowledge

#calculus#continuous-optimisation#numerical-stability-methods

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