Qu

least_squares

Builtin index · Core maths

result = least_squares("f", x0, lower=, upper=, max_iter=200, tol=1e-10)

Input: "f", x0, lower, upper, max_iter, tol · Output: result

What it is

Nonlinear least squares on a residual function you named, via Levenberg-Marquardt. "f" is a Str naming an already-defined function that takes a length-p parameter Vec and returns a residual Vec; x0 is the length-p initial guess Vec. lower=/upper= are optional length-p Vecs of box bounds (enforced by clamping every trial point before it is evaluated, rather than by penalty); max_iter= (default 200) caps the iteration count, tol= (default 1e-10) sets the convergence tolerance.

Overloads

One call shape — this function is not overloaded.

CodeInputOutputDescription
result = least_squares("f", x0, lower=, upper=, max_iter=200, tol=1e-10)
"f" Str or Vec"f" is a Str naming an already-defined function that takes a length-p parameter Vec and returns a residual Vec.
x0 Vecx0 is the length-p initial guess Vec.
lower Veclower=/upper= are optional length-p Vecs of box bounds (enforced by clamping every trial point before it is evaluated, rather than by penalty).
upper Veclower=/upper= are optional length-p Vecs of box bounds (enforced by clamping every trial point before it is evaluated, rather than by penalty).
max_iter — (default 200)max_iter= (default 200) caps the iteration count, tol= (default 1e-10) sets the convergence tolerance.
tol — (default 1e-10)max_iter= (default 200) caps the iteration count, tol= (default 1e-10) sets the convergence tolerance.
Model —kind "least_squares"
params Veclength-p Vec, the fitted parameters
residual Vecthe residual at the solution
cost scalar or Numscalar Num
iterations scalar or Numscalar Num
converged —Bool
p_values —two-sided, Student t on dof = n - p
ci matrixa (p, 2) matrix at level=, default 0.95
bootstrap=N —with seed=
Returns a Model (kind "least_squares") with fields params (length-p Vec, the fitted parameters), residual (Vec, the residual at the solution), cost (scalar Num), iterations (scalar Num), and converged (Bool). Every fit also carries its parameter uncertainty (*added in v0.4.4*): stderr, cov, correlation, t, p_values (two-sided, Student t on dof = n - p), ci (a (p, 2) matrix at level=, default 0.95), dof, rmse, sigma, and note -- which says when there are no degrees of freedom (the statistics are then NaN) or a parameter is not identifiable from the data (stderr = inf). These are linearized at the solution (cov = s^2 (J^T J)^+): exact for a model linear in its parameters with independent normal errors, an approximation otherwise. bootstrap=N (with seed=) refits N residual resamples and adds bootstrap_stderr/bootstrap_ci -- when the two disagree, distrust the linearization. method= picks the solver: "lm" (Levenberg-Marquardt, default), "gauss_newton" (with step halving) or "gradient_descent" (backtracking; slow, and says converged = false rather than pretending). summary(fit) prints the table. A parameter sitting on an active lower=/upper= bound is flagged in at_bound: its linearized stderr does not hold there.

Examples

From the documentation, and run by the build -- the output and the figure below are what the engine actually produced. Simplest first.

bounded = least_squares("resid", [1.0, 1.0], lower = [0.0, 0.01])
print("bounded tau {bounded.params[1]:.4f}")
output
bounded tau 0.3502

from from-zero

tau   = 0.35
decay = 2.5 * exp(0 - t / tau) + 0.02 * randn(1000, seed = 2)

function resid(p)
    return p[0] * exp(0 - t / p[1]) - decay
end function

fit = least_squares("resid", [1.0, 1.0])
print("amplitude {fit.params[0]:.4f} (true 2.5)")
print("tau       {fit.params[1]:.4f} (true {tau})")
output
amplitude 2.4990 (true 2.5)
tau       0.3502 (true 0.35)

from from-zero

How it works

least_squares(f, x0, [lower=], [upper=], [max_iter=], [tol=]) — nonlinear least squares on a RESIDUAL function. f(p) returns the vector to be driven toward zero, not a scalar and not a model evaluated against data. That is the contract curve_fit does not have and the one every fit in this lab needs: a weighting, a Kramers-Kronig penalty or a regularization term is just more entries in the residual. lower=/upper= are box bounds, enforced by clamping every trial point into the box before it is evaluated -- a negative capacitance evaluated once can put NaN through the whole residual, so the bound has to hold at evaluation time, not just at the solution. method=, level=, bootstrap=, seed= and the uncertainty parameter on an active bound is flagged in at_bound, since its linearized stderr does not hold there.

From the note above this builtin in the interpreter, where the reasoning was written down as it was built.