txus's picture
download
raw
4.61 kB
"""Baseline optimizers and the Dolan-More performance-profile metric.
Baselines: L-BFGS, Adam, AdaHessian (Sec. 5.1.2). Each is run per problem and
returns the loss trajectory, so we can compute iterations-to-target and build
performance profiles. The learned L-SR1 optimizer is evaluated separately (it
runs batched) and its trajectories are fed into the same metric code.
"""
from __future__ import annotations
import numpy as np
import torch
# ---------------------------------------------------------------------------
# Baseline rollouts (single problem, x0: [1, N])
# ---------------------------------------------------------------------------
def _traj(problem, x):
with torch.no_grad():
return problem.value(x).item()
def run_adam(problem, x0, steps, lr=1e-2):
x = x0.clone().detach().requires_grad_(True)
opt = torch.optim.Adam([x], lr=lr)
out = [_traj(problem, x)]
for _ in range(steps):
opt.zero_grad()
loss = problem.value(x).sum()
loss.backward()
opt.step()
out.append(_traj(problem, x))
return np.array(out)
def run_lbfgs(problem, x0, steps, lr=1.0, history=10):
x = x0.clone().detach().requires_grad_(True)
opt = torch.optim.LBFGS([x], lr=lr, max_iter=1, history_size=history,
line_search_fn="strong_wolfe")
out = [_traj(problem, x)]
for _ in range(steps):
def closure():
opt.zero_grad()
loss = problem.value(x).sum()
loss.backward()
return loss
opt.step(closure)
out.append(_traj(problem, x))
return np.array(out)
def run_adahessian(problem, x0, steps, lr=0.1, beta1=0.9, beta2=0.999,
eps=1e-4, seed=0):
"""Minimal AdaHessian: diagonal Hessian via one-sample Hutchinson estimator."""
x = x0.clone().detach().requires_grad_(True)
g_rng = torch.Generator(device=x.device).manual_seed(seed)
m = torch.zeros_like(x)
vhat = torch.zeros_like(x)
out = [_traj(problem, x)]
for t in range(1, steps + 1):
loss = problem.value(x).sum()
grad = torch.autograd.grad(loss, x, create_graph=True)[0]
z = torch.randint(0, 2, x.shape, generator=g_rng,
device=x.device, dtype=x.dtype) * 2 - 1 # Rademacher
hv = torch.autograd.grad((grad * z).sum(), x, retain_graph=False)[0]
d = (hv * z).abs() # diagonal Hessian estimate
m = beta1 * m + (1 - beta1) * grad.detach()
vhat = beta2 * vhat + (1 - beta2) * d.detach() ** 2
mhat = m / (1 - beta1 ** t)
vh = (vhat / (1 - beta2 ** t)).sqrt()
with torch.no_grad():
x -= lr * mhat / (vh + eps)
x = x.detach().requires_grad_(True)
out.append(_traj(problem, x))
return np.array(out)
BASELINES = {
"L-BFGS": run_lbfgs,
"Adam": run_adam,
"AdaHessian": run_adahessian,
}
# ---------------------------------------------------------------------------
# Performance profile (Dolan & More, 2002)
# ---------------------------------------------------------------------------
def iters_to_target(traj, f_star, f0, rtol=1e-3, atol=1e-8):
"""First iteration index where f - f* <= rtol*(f0 - f*) + atol; inf if never."""
thresh = rtol * (f0 - f_star) + atol
hit = np.where((traj - f_star) <= thresh)[0]
return int(hit[0]) if len(hit) else np.inf
def performance_profile(cost_matrix, taus=None):
"""cost_matrix: dict[solver] -> np.array[n_problems] of costs (inf = fail).
Returns (taus, {solver: rho(tau)}) with rho_s(tau) = fraction of problems
whose performance ratio r_{p,s} = cost/min_over_solvers(cost) is <= tau.
"""
solvers = list(cost_matrix.keys())
costs = np.stack([cost_matrix[s] for s in solvers]) # [S, P]
best = np.min(costs, axis=0, keepdims=True) # [1, P]
ratios = np.where(np.isfinite(costs), costs / np.maximum(best, 1e-12),
np.inf)
if taus is None:
finite = ratios[np.isfinite(ratios)]
rmax = float(np.max(finite)) if finite.size else 2.0
taus = np.geomspace(1.0, max(rmax, 2.0), 60)
profiles = {}
P = ratios.shape[1]
for i, s in enumerate(solvers):
profiles[s] = np.array([(ratios[i] <= t).sum() / P for t in taus])
return taus, profiles
def auc(taus, rho):
"""Area under the performance profile over log(tau) -- a scalar summary."""
lt = np.log(taus)
trap = np.trapezoid if hasattr(np, "trapezoid") else np.trapz # np>=2 rename
return float(trap(rho, lt) / (lt[-1] - lt[0]))

Xet Storage Details

Size:
4.61 kB
·
Xet hash:
e3d9c0e0d6f7c2f057c2abe8dd8f8b4f2acc5a66380249eb67506a9cb7f06ac9

Xet efficiently stores files, intelligently splitting them into unique chunks and accelerating uploads and downloads. More info.