Our treatment of gradient descent used a fixed
learning rate (or step size) \(\eta\) chosen by experiment. A
principled alternative is the line search. Given a current iterate
\(\boldsymbol{\theta}_t\) and a descent direction \(\mathbf{d}_t\) (that is, one
with \(\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \lt 0\)), we select a step that
minimizes the objective along the ray
\(\{\boldsymbol{\theta}_t + \eta\, \mathbf{d}_t : \eta \gt 0\}\), assuming such a step exists:
\[
\eta_t \in \operatorname*{arg\,min}_{\eta \gt 0}\, \mathcal{L}(\boldsymbol{\theta}_t + \eta\, \mathbf{d}_t).
\]
Exact Line Search on a Quadratic
On a strictly convex quadratic
\[
\begin{align*}
\mathcal{L}(\boldsymbol{\theta}) &= \tfrac{1}{2}\, \boldsymbol{\theta}^\top \mathbf{A} \boldsymbol{\theta}
+ \mathbf{b}^\top \boldsymbol{\theta} + c, \\\\
\mathbf{A} &\succ 0,
\end{align*}
\]
the one-dimensional problem admits a closed-form solution.
Differentiating with respect to \(\eta\):
\[
\frac{d}{d\eta}\, \mathcal{L}(\boldsymbol{\theta} + \eta\, \mathbf{d})
= \mathbf{d}^\top (\mathbf{A} \boldsymbol{\theta} + \mathbf{b}) + \eta\, \mathbf{d}^\top \mathbf{A}\, \mathbf{d}.
\]
Setting this to zero and using
\(\mathbf{A} \boldsymbol{\theta} + \mathbf{b} = \nabla \mathcal{L}(\boldsymbol{\theta})\):
\[
\eta^*_t = -\,\frac{\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t)}{\mathbf{d}_t^\top \mathbf{A}\, \mathbf{d}_t}.
\]
Positivity of \(\mathbf{A}\) makes the denominator positive, and the descent-direction condition makes the
numerator negative, so \(\eta^*_t \gt 0\) as required.
Inexact Line Search
Solving the subproblem exactly at every outer iteration is wasteful. Inexact line searches instead seek
any step \(\eta\) that delivers "sufficient" progress along \(\mathbf{d}_t\). The most common such rule
is the Armijo condition.
Fix \(c_1 \in (0, 1)\). A step size \(\eta \gt 0\) satisfies the Armijo condition at
\(\boldsymbol{\theta}_t\) along a descent direction \(\mathbf{d}_t\) if
\[
\begin{align*}
\mathcal{L}(\boldsymbol{\theta}_t + \eta\, \mathbf{d}_t)
&\leq \mathcal{L}(\boldsymbol{\theta}_t) + c_1\, \eta\, \mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t).
\tag{1}
\end{align*}
\]
Because \(\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \lt 0\), the right-hand side is
strictly smaller than \(\mathcal{L}(\boldsymbol{\theta}_t)\). Thus (1) enforces a decrease proportional to
the step and the directional derivative. A typical choice is \(c_1 = 10^{-4}\).
The standard backtracking implementation starts from an initial trial step
\(\eta\) (often \(\eta = 1\) for Newton-type methods) and shrinks it by a factor
\(\tau \in (0, 1)\) (commonly \(\tau = 0.5\)) until (1) holds. Since \(\mathcal{L}\) is
differentiable at \(\boldsymbol{\theta}_t\),
\[
\mathcal{L}(\boldsymbol{\theta}_t + \eta\, \mathbf{d}_t)
= \mathcal{L}(\boldsymbol{\theta}_t) + \eta\, \mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) + o(\eta),
\]
and because \(c_1 \lt 1\) and
\(\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \lt 0\), the leftover
\((1 - c_1)\, \eta\, \mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t)\) dominates the
\(o(\eta)\) term, so (1) holds for all sufficiently small \(\eta\).
Newton's Method
Gradient descent uses a first-order linear model of \(\mathcal{L}\). Newton's method uses the
second-order quadratic model. Instead of following the negative gradient, at each step it jumps to the
minimizer of the local quadratic approximation, exploiting curvature information encoded in the Hessian.
The second-order Taylor expansion around the current iterate
\(\boldsymbol{\theta}_t\) reads
\[
\begin{align*}
\mathcal{L}(\boldsymbol{\theta}_t + \Delta\boldsymbol{\theta})
&\approx \mathcal{L}(\boldsymbol{\theta}_t)
+ \mathbf{g}_t^\top \Delta\boldsymbol{\theta} \\\\
&\quad + \tfrac{1}{2}\, \Delta\boldsymbol{\theta}^\top \mathbf{H}_t\, \Delta\boldsymbol{\theta},
\end{align*}
\]
where \(\mathbf{g}_t = \nabla \mathcal{L}(\boldsymbol{\theta}_t)\) and
\(\mathbf{H}_t = \nabla^2 \mathcal{L}(\boldsymbol{\theta}_t)\). Minimizing the right-hand side over
\(\Delta\boldsymbol{\theta}\) leads to the Newton step.
Proposition: Newton Direction
Let \(\mathbf{H}_t \succ 0\). The quadratic model
\(q(\Delta\boldsymbol{\theta}) = \mathbf{g}_t^\top \Delta\boldsymbol{\theta}
+ \tfrac{1}{2}\, \Delta\boldsymbol{\theta}^\top \mathbf{H}_t\, \Delta\boldsymbol{\theta}\) has a unique
minimizer
\[
\mathbf{d}_t = -\mathbf{H}_t^{-1}\, \mathbf{g}_t,
\]
called the Newton direction. It is a descent direction whenever
\(\mathbf{g}_t \neq \mathbf{0}\):
\(\mathbf{d}_t^\top \mathbf{g}_t = -\mathbf{g}_t^\top \mathbf{H}_t^{-1}\, \mathbf{g}_t \lt 0\).
Proof:
Completing the square gives
\[
\begin{align*}
q(\Delta\boldsymbol{\theta})
&= \tfrac{1}{2}\, (\Delta\boldsymbol{\theta} + \mathbf{H}_t^{-1}\mathbf{g}_t)^\top \mathbf{H}_t\, (\Delta\boldsymbol{\theta} + \mathbf{H}_t^{-1}\mathbf{g}_t) \\\\
&\quad - \tfrac{1}{2}\, \mathbf{g}_t^\top \mathbf{H}_t^{-1} \mathbf{g}_t.
\end{align*}
\]
Since \(\mathbf{H}_t \succ 0\), the first term is nonnegative and vanishes exactly at
\(\Delta\boldsymbol{\theta} = -\mathbf{H}_t^{-1}\mathbf{g}_t\), which is therefore the unique
minimizer \(\mathbf{d}_t\). Positive-definiteness of \(\mathbf{H}_t^{-1}\), inherited from
\(\mathbf{H}_t\) because \(\mathbf{H}_t^{-1}\) is symmetric and
\(\mathbf{x}^\top \mathbf{H}_t^{-1} \mathbf{x} = (\mathbf{H}_t^{-1}\mathbf{x})^\top \mathbf{H}_t (\mathbf{H}_t^{-1}\mathbf{x}) \gt 0\)
for \(\mathbf{x} \neq \mathbf{0}\), yields
\(\mathbf{g}_t^\top \mathbf{H}_t^{-1} \mathbf{g}_t \gt 0\) whenever
\(\mathbf{g}_t \neq \mathbf{0}\).
Pure Newton's method takes
\(\boldsymbol{\theta}_{t+1} = \boldsymbol{\theta}_t + \mathbf{d}_t\) (unit step). Near a minimizer
at which the Hessian is positive definite and Lipschitz continuous, this scheme converges
quadratically (local quadratic convergence), a classical result we state without
proof on this page, but can diverge when started far from the optimum or when the Hessian is not
positive definite.
To recover global convergence (under standard assumptions that we do not prove here), the
Damped Newton's Method scales the Newton direction by a line-search step size:
\[
\boldsymbol{\theta}_{t+1} = \boldsymbol{\theta}_t + \eta_t\, \mathbf{d}_t,
\quad \eta_t \text{ chosen to satisfy the }
\href{#D-armijo_condition}{\textbf{Armijo condition}}.
\]
Algorithm 1: DAMPED_NEWTONInput: objective \(\mathcal{L}\), tolerance \(\epsilon\); Output: approximate stationary point \(\boldsymbol{\theta}_t\); begin
\(t \leftarrow 0\); choose initial point \(\boldsymbol{\theta}_0\); repeat
\(\mathbf{g}_t \leftarrow \nabla \mathcal{L}(\boldsymbol{\theta}_t)\);
\(\mathbf{H}_t \leftarrow \nabla^2 \mathcal{L}(\boldsymbol{\theta}_t)\);
Solve \(\mathbf{H}_t\, \mathbf{d}_t = -\mathbf{g}_t\) for \(\mathbf{d}_t\);
\(\eta_t \leftarrow \mathrm{LINE\_SEARCH}(\boldsymbol{\theta}_t, \mathbf{d}_t)\) satisfying the Armijo condition;
\(\boldsymbol{\theta}_{t+1} \leftarrow \boldsymbol{\theta}_t + \eta_t\, \mathbf{d}_t\);
\(t \leftarrow t + 1\); until \(\|\mathbf{g}_t\| \lt \epsilon\);
Output \(\boldsymbol{\theta}_t\); end
Computational Note: Solving vs. Inverting
Although we write \(\mathbf{d}_t = -\mathbf{H}_t^{-1}\, \mathbf{g}_t\), the inverse is never formed
explicitly. Forming \(\mathbf{H}_t^{-1}\) costs \(O(n^3)\) and is numerically fragile. Instead we
solve the linear system \(\mathbf{H}_t\, \mathbf{d}_t = -\mathbf{g}_t\) directly, by Cholesky
factorization when \(\mathbf{H}_t \succ 0\) or by conjugate gradients for large sparse problems. The cost
is the same asymptotically but the constants and numerical stability are dramatically better.
When Newton's Method Fails
Newton's direction is a descent direction only when \(\mathbf{H}_t \succ 0\). In non-convex landscapes,
ubiquitous in deep learning, the Hessian is often indefinite near saddle points, so
\(-\mathbf{H}_t^{-1} \mathbf{g}_t\) may point uphill. Practical remedies include
trust-region methods, Levenberg-Marquardt damping
\(\mathbf{H}_t \mapsto \mathbf{H}_t + \mu \mathbf{I}\), and saddle-free Newton (Dauphin
et al., 2014), which replaces \(\mathbf{H}_t\) by \(|\mathbf{H}_t|\) (constructed from the absolute values
of its eigenvalues).
Another concern is cost. Storing the full Hessian requires \(O(n^2)\) memory, and solving the
Newton system is \(O(n^3)\), which is intractable for modern neural networks with \(n\) of
order \(10^9\) or more. This motivates the quasi-Newton methods of the next section.
BFGS Method
To avoid the \(O(n^3)\) cost of Hessian computation and inversion, quasi-Newton methods
maintain a symmetric positive-definite matrix \(\mathbf{B}_t \approx \mathbf{H}_t\) (or its inverse
\(\mathbf{C}_t \approx \mathbf{H}_t^{-1}\)) that is updated cheaply at each iteration using only
gradient information. The BFGS method of
Broyden-Fletcher-Goldfarb-Shanno is the quasi-Newton method most widely used in practice.
Secant Condition
Let \(\mathbf{s}_t = \boldsymbol{\theta}_{t+1} - \boldsymbol{\theta}_t\) denote the parameter step and
\(\mathbf{y}_t = \mathbf{g}_{t+1} - \mathbf{g}_t\) the gradient change. A first-order
Taylor expansion of \(\nabla \mathcal{L}\) around
\(\boldsymbol{\theta}_t\) gives
\[
\begin{align*}
\mathbf{g}_{t+1} &\approx \mathbf{g}_t + \mathbf{H}_t\, \mathbf{s}_t \\\\
&\Longrightarrow \mathbf{y}_t \approx \mathbf{H}_t\, \mathbf{s}_t.
\end{align*}
\]
The quasi-Newton family therefore imposes a curvature-matching requirement on the updated approximation:
Definition: Secant Condition
A sequence of Hessian approximations \(\{\mathbf{B}_t\}\) satisfies the secant condition
if
\[
\mathbf{B}_{t+1}\, \mathbf{s}_t = \mathbf{y}_t \quad \text{for all } t.
\]
Equivalently, the inverse approximations \(\mathbf{C}_t = \mathbf{B}_t^{-1}\) satisfy
\(\mathbf{C}_{t+1}\, \mathbf{y}_t = \mathbf{s}_t\).
Derivation of the BFGS Update
The secant condition alone under-determines \(\mathbf{B}_{t+1}\). In \(n\) dimensions there are \(n(n+1)/2\)
free parameters in a symmetric matrix but only \(n\) linear constraints.
BFGS singles out one update by requiring (i) the update be a symmetric rank-2
correction of \(\mathbf{B}_t\), and (ii) \(\mathbf{B}_{t+1} \succ 0\) be preserved.
Writing \(\mathbf{B}_{t+1} = \mathbf{B}_t + \mathbf{U}\), the secant condition forces
\(\mathbf{U}\, \mathbf{s}_t = \mathbf{y}_t - \mathbf{B}_t\, \mathbf{s}_t\), and the specific
rank-2 ansatz built from
\(\mathbf{y}_t\) and \(\mathbf{B}_t \mathbf{s}_t\), the two vectors this equation involves,
\[
\mathbf{U} = \alpha\, \mathbf{y}_t \mathbf{y}_t^\top + \beta\, (\mathbf{B}_t \mathbf{s}_t)(\mathbf{B}_t \mathbf{s}_t)^\top
\] is chosen so that the first term injects curvature along \(\mathbf{y}_t\) while the second
removes the now-stale curvature along \(\mathbf{B}_t \mathbf{s}_t\). Enforcing
\(\mathbf{U}\, \mathbf{s}_t = \mathbf{y}_t - \mathbf{B}_t \mathbf{s}_t\) pins the scalars, by
comparing coefficients when \(\mathbf{y}_t\) and \(\mathbf{B}_t \mathbf{s}_t\) are linearly
independent (the formula is then adopted in all cases), to
\(\alpha = 1/(\mathbf{y}_t^\top \mathbf{s}_t)\) and
\(\beta = -1/(\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t)\), yielding the BFGS update formula.
Proposition: BFGS Hessian Update
Given a symmetric \(\mathbf{B}_t \succ 0\) and vectors \(\mathbf{s}_t, \mathbf{y}_t\)
satisfying the curvature condition \(\mathbf{y}_t^\top \mathbf{s}_t \gt 0\),
define
\[
\begin{align*}
\mathbf{B}_{t+1}
&= \mathbf{B}_t
+ \frac{\mathbf{y}_t \mathbf{y}_t^\top}{\mathbf{y}_t^\top \mathbf{s}_t} \\\\
&\quad - \frac{(\mathbf{B}_t \mathbf{s}_t)(\mathbf{B}_t \mathbf{s}_t)^\top}{\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t}.
\end{align*}
\]
Then \(\mathbf{B}_{t+1}\) is symmetric, positive definite, and satisfies the secant condition
\(\mathbf{B}_{t+1}\, \mathbf{s}_t = \mathbf{y}_t\).
Symmetry. Both rank-1 correction terms are outer products of a vector with itself,
hence symmetric. \(\mathbf{B}_t\) is symmetric by hypothesis, so \(\mathbf{B}_{t+1}\) is symmetric.
Positive-definiteness. Note first that \(\mathbf{s}_t \neq \mathbf{0}\). If
\(\mathbf{s}_t = \mathbf{0}\) then \(\mathbf{y}_t^\top \mathbf{s}_t = 0\), contradicting the
curvature condition. Hence \(\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t \gt 0\) by
\(\mathbf{B}_t \succ 0\), and the scalar below is well-defined. For any
\(\mathbf{v} \neq \mathbf{0}\), decompose by projecting onto \(\mathbf{s}_t\) (in the
\(\mathbf{B}_t\)-inner product): write \(\mathbf{w} = \mathbf{v} - \gamma \mathbf{s}_t\) with
\(\gamma = (\mathbf{s}_t^\top \mathbf{B}_t \mathbf{v})/(\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t)\),
so that \(\mathbf{s}_t^\top \mathbf{B}_t \mathbf{w} = 0\). A direct calculation then gives
\[
\begin{align*}
\mathbf{v}^\top \mathbf{B}_{t+1} \mathbf{v}
&= \mathbf{w}^\top \mathbf{B}_t \mathbf{w}
+ \frac{(\mathbf{v}^\top \mathbf{y}_t)^2}{\mathbf{y}_t^\top \mathbf{s}_t}.
\end{align*}
\]
Both terms are \(\geq 0\): the first by \(\mathbf{B}_t \succ 0\), the second because
\(\mathbf{y}_t^\top \mathbf{s}_t \gt 0\). To see that the sum is strictly positive
when \(\mathbf{v} \neq \mathbf{0}\), suppose both terms vanish. The first vanishes only when
\(\mathbf{w} = \mathbf{0}\), that is, when \(\mathbf{v} = \gamma \mathbf{s}_t\). Substituting
into the second term gives
\(\mathbf{v}^\top \mathbf{y}_t = \gamma\, \mathbf{s}_t^\top \mathbf{y}_t\). Since
\(\mathbf{s}_t^\top \mathbf{y}_t \gt 0\), this vanishes only when \(\gamma = 0\), forcing
\(\mathbf{v} = \mathbf{0}\), a contradiction. Hence
\(\mathbf{v}^\top \mathbf{B}_{t+1} \mathbf{v} \gt 0\) for every
\(\mathbf{v} \neq \mathbf{0}\).
The curvature condition \(\mathbf{y}_t^\top \mathbf{s}_t \gt 0\) is not automatic. It fails on non-convex
objectives unless the step size \(\eta_t\) is chosen carefully. The Wolfe conditions
introduced below guarantee it, which is why Wolfe (not plain Armijo) is the standard line search for BFGS.
Proposition: BFGS Inverse Update
Under the same hypotheses as the previous proposition, the inverse
\(\mathbf{C}_{t+1} = \mathbf{B}_{t+1}^{-1}\) admits the closed form
\[
\begin{align*}
\mathbf{C}_{t+1}
&= \Bigl(\mathbf{I} - \frac{\mathbf{s}_t \mathbf{y}_t^\top}{\mathbf{y}_t^\top \mathbf{s}_t}\Bigr)
\mathbf{C}_t
\Bigl(\mathbf{I} - \frac{\mathbf{y}_t \mathbf{s}_t^\top}{\mathbf{y}_t^\top \mathbf{s}_t}\Bigr) \\\\
&\quad + \frac{\mathbf{s}_t \mathbf{s}_t^\top}{\mathbf{y}_t^\top \mathbf{s}_t}.
\end{align*}
\]
Proof (via two applications of Sherman-Morrison):
Apply the
Sherman-Morrison formula
first to the rank-1 addition
\(\mathbf{B}_t + \mathbf{y}_t \mathbf{y}_t^\top / (\mathbf{y}_t^\top \mathbf{s}_t)\): with
\(\mathbf{u} = \mathbf{y}_t\),
\(\mathbf{v}^\top = \mathbf{y}_t^\top / (\mathbf{y}_t^\top \mathbf{s}_t)\) (the formula
applies because
\(1 + \mathbf{y}_t^\top \mathbf{C}_t \mathbf{y}_t / \mathbf{y}_t^\top \mathbf{s}_t \gt 0\), as
\(\mathbf{C}_t \succ 0\) inherits positive-definiteness from \(\mathbf{B}_t\) exactly as
\(\mathbf{H}_t^{-1}\) did above, and \(\mathbf{y}_t^\top \mathbf{s}_t \gt 0\)),
\[
\begin{align*}
\Bigl(\mathbf{B}_t + \frac{\mathbf{y}_t \mathbf{y}_t^\top}{\mathbf{y}_t^\top \mathbf{s}_t}\Bigr)^{-1}
&= \mathbf{C}_t - \frac{\mathbf{C}_t \mathbf{y}_t \mathbf{y}_t^\top \mathbf{C}_t}{\mathbf{y}_t^\top \mathbf{s}_t + \mathbf{y}_t^\top \mathbf{C}_t \mathbf{y}_t}.
\end{align*}
\]
Next apply Sherman-Morrison to the rank-1 subtraction of
\((\mathbf{B}_t \mathbf{s}_t)(\mathbf{B}_t \mathbf{s}_t)^\top / (\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t)\)
from the intermediate matrix. This second application is again legitimate, because the scalar
in the formula works out to
\[
\frac{(\mathbf{y}_t^\top \mathbf{s}_t)^2}{(\mathbf{y}_t^\top \mathbf{s}_t + \mathbf{y}_t^\top \mathbf{C}_t \mathbf{y}_t)\, \mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t} \gt 0.
\]
After collecting terms and repeatedly using
\(\mathbf{C}_t \mathbf{B}_t \mathbf{s}_t = \mathbf{s}_t\) (since \(\mathbf{C}_t = \mathbf{B}_t^{-1}\)) and
the identity
\(\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t \cdot (\mathbf{y}_t^\top \mathbf{s}_t + \mathbf{y}_t^\top \mathbf{C}_t \mathbf{y}_t) - (\mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t)(\mathbf{y}_t^\top \mathbf{C}_t \mathbf{y}_t)
= \mathbf{s}_t^\top \mathbf{B}_t \mathbf{s}_t \cdot \mathbf{y}_t^\top \mathbf{s}_t\), the expression
telescopes to the stated form. The final form can be verified mechanically by direct multiplication
\(\mathbf{C}_{t+1} \mathbf{B}_{t+1} = \mathbf{I}\).
Why the two-factor form matters
The compact form
\(\mathbf{C}_{t+1} = (\mathbf{I} - \rho_t \mathbf{s}_t \mathbf{y}_t^\top)\, \mathbf{C}_t\, (\mathbf{I} - \rho_t \mathbf{y}_t \mathbf{s}_t^\top) + \rho_t \mathbf{s}_t \mathbf{s}_t^\top\),
where \(\rho_t = 1/(\mathbf{y}_t^\top \mathbf{s}_t)\), exposes the action of the update:
\(\mathbf{C}_{t+1} \mathbf{v}\) can be computed using only inner products and outer-product sums involving
\(\mathbf{s}_t, \mathbf{y}_t\) and \(\mathbf{C}_t \mathbf{v}\). No explicit matrix storage of the
correction is needed. This is the structural observation that enables L-BFGS below.
Unrolling this two-factor recurrence over the most recent \(m\) pairs yields a two-loop algorithm that
never materializes \(\mathbf{C}_t\) at all.
Wolfe Conditions
BFGS's positive-definiteness preservation and fast convergence both depend on the step
\(\eta_t\) satisfying conditions stronger than Armijo alone. The Wolfe conditions
pair the sufficient-decrease condition with a curvature condition that prevents steps that are too short.
Definition: Wolfe Conditions
Fix \(0 \lt c_1 \lt c_2 \lt 1\). A step size \(\eta \gt 0\) satisfies the Wolfe
conditions at \(\boldsymbol{\theta}_t\) along a descent direction \(\mathbf{d}_t\) if both hold:
(W2) Curvature:
\[
\begin{align*}
\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t + \eta\, \mathbf{d}_t)
&\geq c_2\, \mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t).
\end{align*}
\]
The strong Wolfe conditions replace (W2) with the tighter two-sided form
\(|\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t + \eta \mathbf{d}_t)| \leq c_2\, |\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t)|\).
Typical choices for quasi-Newton methods are \(c_1 = 10^{-4}\) and \(c_2 = 0.9\).
The curvature condition (W2) is precisely what guarantees the BFGS prerequisite
\(\mathbf{y}_t^\top \mathbf{s}_t \gt 0\). Indeed, for a descent direction
\(\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \lt 0\), (W2) gives
\[
\begin{align*}
\mathbf{y}_t^\top \mathbf{s}_t
&= \eta_t\, \mathbf{d}_t^\top \bigl(\nabla \mathcal{L}(\boldsymbol{\theta}_{t+1}) - \nabla \mathcal{L}(\boldsymbol{\theta}_t)\bigr) \\\\
&\geq \eta_t\, (c_2 - 1)\, \mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \\\\
&\gt 0,
\end{align*}
\]
since \(\eta_t \gt 0\), \(c_2 \lt 1\), and
\(\mathbf{d}_t^\top \nabla \mathcal{L}(\boldsymbol{\theta}_t) \lt 0\).
That chain of inequalities is the reason BFGS line searches are implemented with (strong) Wolfe rather than
plain Armijo.
Limited-Memory BFGS (L-BFGS)
For large-scale problems, storing the \(n \times n\) matrix \(\mathbf{C}_t\) explicitly is infeasible. At
\(n \sim 10^6\) the matrix already requires terabytes. L-BFGS sidesteps this by never forming
\(\mathbf{C}_t\). It retains only the most recent \(m\) pairs \(\{(\mathbf{s}_i, \mathbf{y}_i)\}\) (typically
\(m \in \{5, \ldots, 20\}\)) and computes \(\mathbf{C}_t\, \mathbf{g}_t\) implicitly via the two-loop
recursion below.
Unrolling the two-factor recurrence over the last \(m\) pairs, applied to a vector \(\mathbf{g}_t\) against an
implicit initial \(\mathbf{C}_t^{(0)}\) (often \(\mathbf{I}\)), produces exactly that recursion. The memory
cost drops to \(O(mn)\) and each iteration costs \(O(mn)\).
Algorithm 2: L_BFGSInput: objective \(\mathcal{L}\), tolerance \(\epsilon\), memory size \(m\); Output: approximate stationary point \(\boldsymbol{\theta}^*\); begin
Choose initial point \(\boldsymbol{\theta}_0\); initialise \((\mathbf{s}, \mathbf{y})\) storage for up to \(m\) past updates;
\(t \leftarrow 0\); repeat
\(\mathbf{g}_t \leftarrow \nabla \mathcal{L}(\boldsymbol{\theta}_t)\); \(\mathbf{q} \leftarrow \mathbf{g}_t\); Backward loop (newest to oldest stored pair):
\(\alpha_i \leftarrow \rho_i\, \mathbf{s}_i^\top \mathbf{q}\); \(\mathbf{q} \leftarrow \mathbf{q} - \alpha_i\, \mathbf{y}_i\);
\(\mathbf{r} \leftarrow \mathbf{C}_t^{(0)}\, \mathbf{q}\) (typically \(\mathbf{C}_t^{(0)} = \mathbf{I}\) or a scaled identity); Forward loop (oldest to newest stored pair):
\(\beta_i \leftarrow \rho_i\, \mathbf{y}_i^\top \mathbf{r}\); \(\mathbf{r} \leftarrow \mathbf{r} + \mathbf{s}_i (\alpha_i - \beta_i)\);
\(\mathbf{d}_t \leftarrow -\mathbf{r}\);
\(\eta_t \leftarrow \mathrm{LINE\_SEARCH}(\boldsymbol{\theta}_t, \mathbf{d}_t)\) satisfying Wolfe conditions;
\(\boldsymbol{\theta}_{t+1} \leftarrow \boldsymbol{\theta}_t + \eta_t\, \mathbf{d}_t\);
\(\mathbf{g}_{t+1} \leftarrow \nabla \mathcal{L}(\boldsymbol{\theta}_{t+1})\);
Store \(\mathbf{s}_t \leftarrow \boldsymbol{\theta}_{t+1} - \boldsymbol{\theta}_t\), \(\mathbf{y}_t \leftarrow \mathbf{g}_{t+1} - \mathbf{g}_t\), \(\rho_t \leftarrow 1/(\mathbf{y}_t^\top \mathbf{s}_t)\);
If the number of stored pairs exceeds \(m\), discard the oldest pair;
\(t \leftarrow t + 1\); until \(\|\mathbf{g}_t\| \lt \epsilon\);
Output \(\boldsymbol{\theta}_t\); end
For numerical efficiency, the scalar \(\rho_t = 1/(\mathbf{y}_t^\top \mathbf{s}_t)\) is computed once and
stored alongside each \((\mathbf{s}_t, \mathbf{y}_t)\) pair rather than being recomputed whenever it is needed
in the two loops.
Python Implementation
The sample implementation below tests L-BFGS on the Rosenbrock function
\[
\begin{align*}
f(\mathbf{x}) &= \sum_{i=1}^{n-1} \bigl[a\, (x_{i+1} - x_i^2)^2 + (b - x_i)^2\bigr], \\\\
a &= 100, \quad b = 1,
\end{align*}
\]
a standard optimization benchmark with global minimum \(f(\mathbf{1}) = 0\).
Despite the simple appearance, the Rosenbrock function is notoriously difficult for optimization
algorithms because its global minimum lies at the bottom of a narrow, curved, "banana-shaped" valley.
The surrounding landscape is ill-conditioned (strong anisotropy of the Hessian) and along the valley
floor the gradient is small, so naive gradient descent crawls while Newton-type methods must handle
curvature carefully.
import numpy as np
# Line search with Wolfe conditions
def line_search(f, grad_f, theta, p, c1 = 1e-4, c2 = 0.9, max_iter = 100):
eta = 1.0
eta_low = 0.0
eta_high = None
phi_0 = f(theta)
grad_phi_0 = np.dot(grad_f(theta), p)
for _ in range(max_iter):
phi_eta = f(theta + eta * p)
# Check Armijo condition
if phi_eta > phi_0 + c1 * eta * grad_phi_0:
eta_high = eta
else:
# Check Curvature condition
grad_phi_eta = np.dot(grad_f(theta + eta * p), p)
if grad_phi_eta < c2 * grad_phi_0:
eta_low = eta
else:
return eta
# Update step size using bisection method
if eta_high is not None:
eta = (eta_low + eta_high) / 2.0
else:
eta *= 2.0
return eta
# Limited memory BFGS
def limited_bfgs(f, grad_f, theta0, m = 10, tol = 1e-6, max_iter = 2000):
theta = theta0.copy()
g = grad_f(theta)
s_list = []
y_list = []
rho_list = [] # We introduce rho = 1/s^\top y instead of directly using 1/s^\top y for efficiency & stability.
for _ in range(max_iter):
if np.linalg.norm(g) < tol:
break
q = g.copy()
alpha_list = [] # Need this for the second loop to avoid computing alpha again
# Loop backward through stored (s, y) pairs
for s, y, rho in reversed(list(zip(s_list, y_list, rho_list))):
alpha = rho * np.dot(s, q)
alpha_list.append(alpha)
q -= alpha * y
# Initial Hessian approximation is identity: H0 = I, so H0 * q = q
# Note: In the first iteration (when s_list is empty), the loops do nothing,
# so r = q = g, and thus p = -r = -g (steepest descent direction)
r = q
# Loop forward through stored (s, y) pairs
for (s, y, rho), alpha in zip(zip(s_list, y_list, rho_list), reversed(alpha_list)):
beta = rho * np.dot(y, r)
r += s * (alpha - beta)
# Search direction
p = -r
# Compute the step size by Line search satisfying Wolfe conditions
eta = line_search(f, grad_f, theta, p)
# Update parameters
theta += eta * p
grad_next = grad_f(theta)
# Update memory for (s, y) pairs
s = eta * p
y = grad_next - g
if np.dot(s, y) > 1e-10 * np.linalg.norm(s) * np.linalg.norm(y):
if len(s_list) == m:
s_list.pop(0)
y_list.pop(0)
rho_list.pop(0)
s_list.append(s)
y_list.append(y)
rho_list.append(1.0 / np.dot(y, s))
# Update gradient
g = grad_next
return theta
# Objective function and its gradient:
# The Rosenbrock function is commonly used for testing optimization algorithms.
def rosenbrock(x):
return np.sum(100 * (x[1:] - x[:-1]**2)**2 + (1 - x[:-1])**2)
def grad_rosenbrock(x):
grad = np.zeros_like(x)
grad[:-1] = -400 * x[:-1] * (x[1:] - x[:-1]**2) - 2 * (1 - x[:-1]) # # x_1 to x_n-1
grad[1:] += 200 * (x[1:] - x[:-1]**2) # x_2 to x_n
return grad
# Finite difference gradient to check grad_rosenbrock().
def finite_difference_gradient(f, x, epsilon=1e-6):
grad = np.zeros_like(x)
for i in range(len(x)):
x_forward = x.copy()
x_backward = x.copy()
x_forward[i] += epsilon
x_backward[i] -= epsilon
grad[i] = (f(x_forward) - f(x_backward)) / (2 * epsilon)
return grad
if __name__ == "__main__":
n = 50 # Dimensionality
# Randomly generate an initial point x0:
# You could try : x0 = np.ones(n) + 0.3 * np.random.randn(n), which represents adding small
# perturbation around the global minimum x* = [1, ... , 1]^\top
x0 = np.random.randn(n)
numeric_opt = limited_bfgs(rosenbrock, grad_rosenbrock, x0)
print("Initial point: \n", x0.tolist())
print("\n Numerical optimum: \n", numeric_opt.tolist())
'''
# If you are not sure about the gradient of the objective, always you can compare it with finite difference.
grad_analytic = grad_rosenbrock(x0)
grad_numeric = finite_difference_gradient(rosenbrock, x0)
relative_error_grad = np.linalg.norm(grad_analytic - grad_numeric) / np.linalg.norm(grad_analytic)
print("Relative error:", relative_error_grad)
'''
# Relative error between the numerical optimum and the global optimum
global_opt = np.ones(n) # The actual global optimum of Rosenbrock function is x* = [1, ... , 1]^\top
relative_error_optimal = np.linalg.norm(numeric_opt - global_opt) / np.linalg.norm(global_opt)
print(f"\n Relative error to the global minimum: {relative_error_optimal*100:.8f}%")
Why Rosenbrock is a hard benchmark
Even though \(\mathbf{x}^* = (1, 1, \ldots, 1)\) is easy to read off analytically, numerical optimizers
struggle with the Rosenbrock landscape for three compounding reasons:
Narrow, curved valley. The minimum lies at the bottom of a bent ravine. Steep walls
deflect iterates and trigger over- or undershooting unless curvature information is used.
Ill-conditioning. Along the valley the Hessian has eigenvalues differing by several
orders of magnitude. The condition number is large, and first-order methods slow dramatically (cf. the
condition-number analysis later in this section).
Slow progress along the floor. Along the valley floor the gradient is
small while the function is still far from its minimum, so progress requires long steps that
must not overshoot the valley walls.
These three properties mirror pathologies commonly reported for loss landscapes in deep
learning, namely anisotropic curvature, ill-conditioning, and flat plateaus, which is why
Rosenbrock remains a standard testbed for new optimization algorithms.