qmri.fitting¶
fitting ¶
Fitting algorithms and utilities.
This module provides:
- Linear least squares (LLS)
- Weighted linear least squares (WLLS)
- Iterative weighted linear least squares (IWLLS)
- Least squares fitting wrapper with sensible defaults
- Covariance estimation and standard errors
- Bootstrap uncertainty estimation (future)
Example
import numpy as np
from qmri.fitting import least_squares
def residual_func(params, x, y):
return y - params[0] * np.exp(-params[1] * x)
x_data = np.array([0, 1, 2, 3, 4])
y_data = np.array([1.0, 0.6, 0.4, 0.2, 0.15])
result = least_squares.fit(residual_func, x0=[1.0, 0.5], args=(x_data, y_data))
print(f"Success: {result.success}")
FitResult
dataclass
¶
FitResult(
x: NDArray[floating],
cost: float,
residuals: NDArray[floating],
success: bool,
message: str,
n_function_evals: int,
n_jacobian_evals: int,
jacobian: NDArray[floating] | None = None,
)
Result of least squares fitting.
Attributes:
| Name | Type | Description |
|---|---|---|
x |
NDArray[floating]
|
Solution vector (optimised parameters). |
cost |
float
|
Value of the cost function at the solution. |
residuals |
NDArray[floating]
|
Residual values at the solution. |
success |
bool
|
Whether the optimisation converged successfully. |
message |
str
|
Description of the termination reason. |
n_function_evals |
int
|
Number of function evaluations. |
n_jacobian_evals |
int
|
Number of Jacobian evaluations. |
jacobian |
NDArray[floating] | None
|
Jacobian matrix at the solution (if available). |
estimate_covariance ¶
estimate_covariance(
jacobian: NDArray[floating],
residuals: NDArray[floating],
) -> NDArray[floating]
Estimate parameter covariance matrix from Jacobian.
Computes the covariance matrix of the fitted parameters using the Jacobian matrix at the solution. This is useful for uncertainty estimation.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
jacobian
|
NDArray[floating]
|
Jacobian matrix at the solution, shape (n_residuals, n_params). |
required |
residuals
|
NDArray[floating]
|
Residual values at the solution, shape (n_residuals,). |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
Covariance matrix, shape (n_params, n_params). |
The covariance matrix is estimated as:
where \(\sigma^2\) is the variance of residuals estimated as \(\sigma^2 = \frac{\sum r_i^2}{n - p}\) with n residuals and p parameters.
Example
Source code in packages/qmri/src/qmri/fitting/least_squares.py
fit ¶
fit(
residual_func: Callable[..., NDArray[floating]],
x0: NDArray[floating] | list[float],
*,
args: tuple[Any, ...] = (),
bounds: tuple[
NDArray[floating] | list[float],
NDArray[floating] | list[float],
]
| None = None,
method: Method = "lm",
ftol: float = 1e-08,
xtol: float = 1e-08,
gtol: float = 1e-08,
max_nfev: int | None = None,
verbose: int = 0,
) -> FitResult
Fit parameters using least squares optimisation.
A wrapper around scipy.optimize.least_squares with sensible defaults for qMRI applications.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
residual_func
|
Callable[..., NDArray[floating]]
|
Function that computes the residuals: f(x, *args) -> residuals. The function should return a 1D array of residuals. |
required |
x0
|
NDArray[floating] | list[float]
|
Initial guess for the parameters. |
required |
args
|
tuple[Any, ...]
|
Additional arguments passed to residual_func. |
()
|
bounds
|
tuple[NDArray[floating] | list[float], NDArray[floating] | list[float]] | None
|
Lower and upper bounds on parameters: (lower, upper). Each array must match the size of x0. Only used with 'trf' or 'dogbox' methods. |
None
|
method
|
Method
|
Optimisation method (default "lm"):
|
'lm'
|
ftol
|
float
|
Tolerance for termination by change of cost function (default 1e-8). |
1e-08
|
xtol
|
float
|
Tolerance for termination by change of parameters (default 1e-8). |
1e-08
|
gtol
|
float
|
Tolerance for termination by norm of gradient (default 1e-8). |
1e-08
|
max_nfev
|
int | None
|
Maximum number of function evaluations. If None, uses scipy default. |
None
|
verbose
|
int
|
Level of algorithm verbosity (default 0, silent). |
0
|
Returns:
| Type | Description |
|---|---|
FitResult
|
Object containing optimisation results. |
Example
Simple exponential decay fitting:
import numpy as np
from qmri.fitting.least_squares import fit
def exp_residual(params, x, y):
a, b = params
return y - a * np.exp(-b * x)
x = np.array([0, 1, 2, 3, 4], dtype=np.float64)
y = np.array([1.0, 0.6, 0.35, 0.22, 0.13])
result = fit(exp_residual, x0=[1.0, 0.5], args=(x, y))
print(f"Success: {result.success}, params: {result.x}")
# With bounds:
result = fit(
exp_residual,
x0=[1.0, 0.5],
args=(x, y),
bounds=([0, 0], [10, 5]),
method="trf"
)
Source code in packages/qmri/src/qmri/fitting/least_squares.py
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 | |
standard_errors ¶
Compute standard errors of fitted parameters.
A convenience function that extracts the standard errors (square root of diagonal elements of covariance matrix) from Jacobian and residuals.
Parameters:
| Name | Type | Description | Default |
|---|---|---|---|
jacobian
|
NDArray[floating]
|
Jacobian matrix at the solution, shape (n_residuals, n_params). |
required |
residuals
|
NDArray[floating]
|
Residual values at the solution, shape (n_residuals,). |
required |
Returns:
| Type | Description |
|---|---|
NDArray[floating]
|
Standard errors for each parameter, shape (n_params,). |