nlsq.result module¶
Result types for NLSQ optimization operations.
This module provides consolidated result types that were previously scattered
across the codebase. As of v0.4.3, OptimizeResult and OptimizeWarning
have been moved here from nlsq.core._optimize.
Result types for NLSQ optimization.
This package provides the canonical location for optimization result types:
OptimizeResult: Base container for optimization results with attribute access
OptimizeResultV2: Memory-efficient frozen dataclass (v0.4.3+)
OptimizeWarning: Warning class for non-critical optimization issues
CurveFitResult: Enhanced result with statistical properties and visualization
Example
>>> from nlsq.result import OptimizeResult, OptimizeResultV2
>>> result = OptimizeResult(x=[1.0, 2.0], success=True)
>>> result.x
[1.0, 2.0]
- class nlsq.result.CurveFitResult(*args, **kwargs)[source]
Bases:
OptimizeResultEnhanced curve fitting result with statistical properties and visualization.
This class extends OptimizeResult with convenience methods for statistical analysis and visualization. It maintains backward compatibility by supporting tuple unpacking:
popt, pcov = curve_fit(...).The result can be used in two ways:
Tuple unpacking (backward compatible):
popt, pcov = curve_fit(model, x, y)
Enhanced result object:
result = curve_fit(model, x, y) print(f"R² = {result.r_squared:.4f}") print(f"RMSE = {result.rmse:.4f}") result.plot() result.summary()
Additional Attributes¶
- modelcallable
The model function f(x, *params) used for fitting.
- xdataarray_like
The independent variable data.
- ydataarray_like
The dependent variable data (observations).
- poptarray_like
Fitted parameters (alias for self.x).
- pcovarray_like
Parameter covariance matrix.
- diagnosticsDiagnosticsReport | None
Model health diagnostics report (if compute_diagnostics=True).
Statistical Properties¶
- r_squaredfloat
Coefficient of determination (R²). Measures goodness of fit. Range: (-∞, 1], where 1 is perfect fit.
- adj_r_squaredfloat
Adjusted R² accounting for number of parameters. Preferred over R² when comparing models with different parameters.
- rmsefloat
Root mean squared error. Lower is better.
- maefloat
Mean absolute error. Robust to outliers.
- aicfloat
Akaike Information Criterion. Lower is better. Used for model selection.
- bicfloat
Bayesian Information Criterion. Lower is better. Penalizes model complexity more than AIC.
- residualsarray_like
Residuals (observed - predicted). Should be random for good fit.
- predictionsarray_like
Model predictions at xdata points.
- confidence_intervals(alpha=0.95)[source]
Compute parameter confidence intervals.
- prediction_interval(x, alpha=0.95)[source]
Compute prediction interval at new x values.
- plot(ax=None, show_residuals=True)[source]
Plot data, fit, and residuals.
- summary()[source]
Print statistical summary table.
Examples
Basic usage with enhanced features:
import numpy as np import jax.numpy as jnp from nlsq import curve_fit # Define model def exponential(x, a, b, c): return a * jnp.exp(-b * x) + c # Generate data x = np.linspace(0, 10, 100) y_true = 10 * np.exp(-0.5 * x) + 2 y = y_true + np.random.normal(0, 0.5, 100) # Fit and analyze result = curve_fit(exponential, x, y, p0=[10, 0.5, 2]) print(f"R² = {result.r_squared:.4f}") print(f"RMSE = {result.rmse:.4f}") print(f"AIC = {result.aic:.2f}") # Get confidence intervals ci = result.confidence_intervals(alpha=0.95) print(f"95% CI for parameters: {ci}") # Visualize fit result.plot() # Statistical summary result.summary()
With diagnostics:
result = curve_fit(exponential, x, y, compute_diagnostics=True) print(result.diagnostics.summary()) print(result.diagnostics.identifiability.health_status)
Backward compatibility:
# Tuple unpacking still works popt, pcov = curve_fit(exponential, x, y) # But enhanced features available if not unpacked result = curve_fit(exponential, x, y) result.plot()
- __init__(*args, **kwargs)[source]
Initialize enhanced curve fit result.
- __iter__()[source]
Support tuple unpacking: popt, pcov = curve_fit(…)
- property popt
Fitted parameters (alias for self.x).
- Returns:
popt – Fitted parameters as NumPy array for SciPy compatibility.
- Return type:
ndarray
- property pcov
Parameter covariance matrix.
- Returns:
pcov – Covariance matrix as NumPy array for SciPy compatibility.
- Return type:
ndarray
- property diagnostics
Model health diagnostics report.
Returns the health report if compute_diagnostics=True was specified when calling curve_fit(), otherwise returns None.
- Returns:
diagnostics – Aggregated model health report containing identifiability analysis, gradient health monitoring, and other health metrics. None if diagnostics were not computed.
- Return type:
ModelHealthReport | None
Examples
>>> result = curve_fit(model, x, y, compute_diagnostics=True) >>> if result.diagnostics is not None: ... print(result.diagnostics.summary()) ... print(result.diagnostics.status) ... print(result.diagnostics.health_score) ... if result.diagnostics.identifiability is not None: ... print(result.diagnostics.identifiability.health_status)
See also
nlsq.diagnostics.ModelHealthReportAggregated health report
nlsq.diagnostics.IdentifiabilityReportIdentifiability analysis
nlsq.diagnostics.GradientHealthReportGradient health monitoring
- property predictions
Model predictions at xdata points.
- Returns:
predictions – Model predictions: f(xdata, *popt)
- Return type:
ndarray
- property residuals
Residuals (observed - predicted).
- Returns:
residuals – Residuals: ydata - predictions
- Return type:
ndarray
Notes
For a good fit, residuals should be randomly distributed around zero with no systematic patterns.
- property r_squared
Coefficient of determination (R²).
- Returns:
r2 – R² value in range (-∞, 1]. Values closer to 1 indicate better fit.
- Return type:
Notes
R² = 1 - SS_res / SS_tot
where SS_res = sum((y - y_pred)²) and SS_tot = sum((y - y_mean)²)
Interpretation: - R² = 1: Perfect fit - R² = 0: Model no better than mean - R² < 0: Model worse than mean (overfitting or poor model)
- property adj_r_squared
Adjusted R² accounting for number of parameters.
- Returns:
adj_r2 – Adjusted R² value.
- Return type:
Notes
Adj R² = 1 - (1 - R²) * (n - 1) / (n - p - 1)
where n is number of data points and p is number of parameters.
Adjusted R² penalizes adding parameters and is better for comparing models with different numbers of parameters.
- property rmse
Root mean squared error.
- Returns:
rmse – Root mean squared error: sqrt(mean(residuals²))
- Return type:
Notes
RMSE has the same units as ydata and provides intuitive error measure. Lower values indicate better fit.
- property mae
Mean absolute error.
- Returns:
mae – Mean absolute error: mean(|residuals|)
- Return type:
Notes
MAE is more robust to outliers than RMSE.
- property aic
Akaike Information Criterion.
- Returns:
aic – AIC value. Lower is better.
- Return type:
Notes
AIC = 2k + n*ln(RSS/n)
where k is number of parameters, n is number of data points, and RSS is residual sum of squares.
Used for model selection. Penalizes model complexity.
- property bic
Bayesian Information Criterion.
- Returns:
bic – BIC value. Lower is better.
- Return type:
Notes
BIC = k*ln(n) + n*ln(RSS/n)
where k is number of parameters, n is number of data points, and RSS is residual sum of squares.
BIC penalizes model complexity more heavily than AIC. Preferred for larger datasets.
- confidence_intervals(alpha=0.95)[source]
Compute parameter confidence intervals.
- Parameters:
alpha (float, optional) – Confidence level (default: 0.95 for 95% CI).
- Returns:
intervals – Array of shape (n_params, 2) with [lower, upper] bounds for each parameter.
- Return type:
ndarray
Examples
>>> result = curve_fit(model, x, y) >>> ci = result.confidence_intervals(alpha=0.95) >>> for i, (lower, upper) in enumerate(ci): ... print(f"Parameter {i}: [{lower:.3f}, {upper:.3f}]")
Notes
Confidence intervals are computed using the parameter covariance matrix and Student’s t-distribution. Assumes residuals are normally distributed.
- prediction_interval(x=None, alpha=0.95)[source]
Compute prediction interval at x values.
- Parameters:
x (array_like, optional) – x values for prediction. If None, uses self.xdata (default: None).
alpha (float, optional) – Confidence level (default: 0.95).
- Returns:
intervals – Array of shape (n_points, 2) with [lower, upper] bounds for each point.
- Return type:
ndarray
Examples
>>> result = curve_fit(model, x, y) >>> pi = result.prediction_interval() # Use fitted x values >>> pi_new = result.prediction_interval(x_new) # Use new x values
Notes
Prediction intervals account for both parameter uncertainty (from pcov) and inherent data variability (residual variance).
- confidence_band(x=None, alpha=0.95)[source]
Compute mean prediction confidence band.
- Parameters:
x (array_like, optional) – x values for prediction. If None, uses self.xdata (default: None).
alpha (float, optional) – Confidence level (default: 0.95 for 95% CI).
- Returns:
lower (ndarray) – Lower confidence bound.
upper (ndarray) – Upper confidence bound.
Notes
This calculates the confidence interval for the mean response (f(x)), representing the uncertainty in the model curve itself due to parameter uncertainties.
- plot(ax=None, show_residuals=True, show_confidence=True, **kwargs)[source]
Plot data, fitted curve, and residuals.
- Parameters:
ax (matplotlib.axes.Axes, optional) – Axes to plot on. If None, creates new figure.
show_residuals (bool, optional) – Whether to show residual plot (default: True).
show_confidence (bool, optional) – Whether to show 95% confidence band (default: True).
**kwargs – Additional keyword arguments passed to plotting functions.
- Returns:
fig (matplotlib.figure.Figure) – Figure object.
axes (matplotlib.axes.Axes or array of Axes) – Axes object(s).
Examples
>>> result = curve_fit(model, x, y) >>> result.plot() >>> plt.show()
- summary()[source]
Print statistical summary of fit.
Displays: - Fitted parameters with standard errors - Goodness of fit metrics (R², RMSE, MAE) - Model selection criteria (AIC, BIC) - Convergence information - Diagnostics summary (if available)
Examples
>>> result = curve_fit(model, x, y) >>> result.summary()
- class nlsq.result.OptimizeResult[source]
Bases:
dictOptimization result container for NLSQ curve fitting operations.
This class stores the complete results from nonlinear least squares optimization performed using JAX-accelerated algorithms. It extends dict to provide both dictionary-style and attribute-style access to optimization results.
Core Attributes¶
- xjax.numpy.ndarray or numpy.ndarray
Optimized parameter vector containing the final fitted parameters. These represent the solution to the nonlinear least squares problem.
- successbool
Indicates whether the optimization terminated successfully. True means convergence criteria were satisfied within tolerance limits.
- statusint
Numerical termination status code indicating why optimization stopped:
1: Gradient convergence (||g||_inf < gtol)
2: Step size convergence (||dx||/||x|| < xtol)
3: Function value convergence (delta_f/f < ftol)
0: Maximum iterations reached
-1: Evaluation limit exceeded
-3: Inner loop iteration limit (algorithm-specific)
- messagestr
Human-readable description of termination cause. Provides detailed information about convergence status or failure reasons.
Objective Function Results¶
- funjax.numpy.ndarray
Final residual vector f(x) at the solution. For curve fitting, these are the differences between model predictions and data points.
- costfloat
Final cost function value: 0.5 * ||f(x)||² for standard least squares, or 0.5 * sum(ρ(f_i²/σ²)) for robust loss functions.
- jacjax.numpy.ndarray
Final Jacobian matrix J(x) with shape (m, n) where m is number of data points and n is number of parameters. Computed using JAX autodiff.
- gradjax.numpy.ndarray
Final gradient vector g = J^T * f with shape (n,). Used for convergence checking and parameter uncertainty estimation.
Convergence Metrics¶
- optimalityfloat
Final gradient norm ||g||_inf used for convergence assessment. Should be less than gtol for successful convergence.
- active_masknumpy.ndarray
Boolean mask indicating which parameters hit bounds (for bounded optimization). Shape (n,) with True for parameters at constraints.
Iteration Statistics¶
- nfevint
Total number of objective function evaluations during optimization. Each evaluation computes residuals f(x) for given parameters.
- njevint
Total number of Jacobian evaluations. With JAX autodiff, this equals the number of combined function+gradient evaluations.
- nitint
Number of optimization iterations completed. Not always available for all algorithms.
Algorithm-Specific Results¶
- pcovjax.numpy.ndarray, optional
Parameter covariance matrix with shape (n, n). Provides parameter uncertainty estimates. Available when uncertainty estimation is requested. Computed as: pcov = inv(J^T * J) * residual_variance
- active_masknumpy.ndarray
For bounded optimization, indicates which parameters are at bounds.
- all_timesdict, optional
Detailed timing information for algorithm profiling. Contains timing data for different optimization phases (function evaluation, Jacobian computation, linear algebra operations, etc.).
Usage Examples¶
Basic result access:
import nlsq # Perform curve fitting result = nlsq.curve_fit(model_func, x_data, y_data, p0=initial_guess) # Access optimized parameters fitted_params = result.x # Check convergence if result.success: print(f"Optimization converged: {result.message}") print(f"Final cost: {result.cost}") print(f"Function evaluations: {result.nfev}") else: print(f"Optimization failed: {result.message}") # Parameter uncertainties (if covariance computed) if hasattr(result, 'pcov'): param_errors = jnp.sqrt(jnp.diag(result.pcov)) print(f"Parameter uncertainties: {param_errors}")
Advanced result inspection:
# Examine residuals and fit quality final_residuals = result.fun rms_error = jnp.sqrt(jnp.mean(final_residuals**2)) # Check gradient convergence gradient_norm = result.optimality print(f"Final gradient norm: {gradient_norm}") # Analyze Jacobian condition jacobian = result.jac condition_number = jnp.linalg.cond(jacobian) print(f"Jacobian condition number: {condition_number}") # For bounded problems, check active constraints if hasattr(result, 'active_mask'): constrained_params = jnp.where(result.active_mask)[0] print(f"Parameters at bounds: {constrained_params}")
Integration with SciPy¶
This class maintains compatibility with scipy.optimize.OptimizeResult while adding JAX-specific features and NLSQ-specific results. It can be used interchangeably with SciPy optimization results in most contexts.
Technical Notes¶
All JAX arrays are automatically converted to NumPy arrays for compatibility
Covariance matrices use double precision for numerical stability
Large dataset results may include memory management statistics
GPU timing results require explicit timing mode activation
Progress monitoring data is stored in algorithm-specific attributes
- nlsq.result.OptimizeResultLegacy
alias of
OptimizeResult
- class nlsq.result.OptimizeResultV2(x, success, cost, fun, jac=None, grad=None, optimality=0.0, active_mask=None, nfev=0, njev=0, nit=0, status=0, message='', pcov=None, all_times=None)[source]
Bases:
objectMemory-efficient optimization result container (v2).
This class provides a memory-efficient alternative to OptimizeResult using Python’s frozen dataclass with slots. It offers:
~40% memory reduction per instance (no __dict__)
~2x faster attribute access (direct slot access vs dict lookup)
Immutability for thread-safety and caching
Core Attributes¶
- xjnp.ndarray
Optimized parameter vector containing the final fitted parameters.
- successbool
Indicates whether the optimization terminated successfully.
- costfloat
Final cost function value: 0.5 * ||f(x)||².
- funjnp.ndarray
Final residual vector f(x) at the solution.
Optional Attributes¶
- jacjnp.ndarray | None
Final Jacobian matrix J(x). None if not requested (saves ~400KB for 10k×50).
- gradjnp.ndarray | None
Final gradient vector g = J^T * f.
- optimalityfloat
Final gradient norm ||g||_inf.
- active_maskjnp.ndarray | None
Boolean mask indicating which parameters hit bounds.
- nfevint
Total number of objective function evaluations.
- njevint
Total number of Jacobian evaluations.
- nitint
Number of optimization iterations completed.
- statusint
Numerical termination status code.
- messagestr
Human-readable description of termination cause.
- pcovjnp.ndarray | None
Parameter covariance matrix.
- all_timesdict | None
Detailed timing information for profiling.
Examples
>>> result.x # Access optimized parameters >>> result.success # Check convergence >>> result.cost # Get final cost value >>> result.to_dict() # Convert to dictionary
- x: Array
- success: bool
- cost: float
- fun: Array
- optimality: float
- nfev: int
- njev: int
- nit: int
- status: int
- message: str
- to_dict()[source]
Convert to dictionary.
- Returns:
Dictionary containing all non-None fields.
- Return type:
- __repr__()[source]
Compact representation showing key fields.
- __init__(x, success, cost, fun, jac=None, grad=None, optimality=0.0, active_mask=None, nfev=0, njev=0, nit=0, status=0, message='', pcov=None, all_times=None)
- exception nlsq.result.OptimizeWarning[source]
Bases:
UserWarningWarning class for optimization-related issues.
This warning is raised when non-critical issues are encountered during optimization, such as unknown solver options, convergence concerns, or numerical stability warnings that don’t prevent the optimization from completing but should be brought to the user’s attention.
- Common scenarios:
Unknown or deprecated solver options passed to optimizer
Convergence achieved but with warnings about numerical conditioning
Parameter bounds adjusted automatically
Automatic algorithm selection overrides
Example
>>> import warnings >>> warnings.filterwarnings('error', category=OptimizeWarning) >>> # Now OptimizeWarning will raise an exception instead of warning
See also
nlsq.error_messages.OptimizationError : Exception for critical failures
Classes¶
OptimizeResult¶
- class nlsq.result.OptimizeResult[source]
Bases:
dictOptimization result container for NLSQ curve fitting operations.
This class stores the complete results from nonlinear least squares optimization performed using JAX-accelerated algorithms. It extends dict to provide both dictionary-style and attribute-style access to optimization results.
Core Attributes¶
- xjax.numpy.ndarray or numpy.ndarray
Optimized parameter vector containing the final fitted parameters. These represent the solution to the nonlinear least squares problem.
- successbool
Indicates whether the optimization terminated successfully. True means convergence criteria were satisfied within tolerance limits.
- statusint
Numerical termination status code indicating why optimization stopped:
1: Gradient convergence (||g||_inf < gtol)
2: Step size convergence (||dx||/||x|| < xtol)
3: Function value convergence (delta_f/f < ftol)
0: Maximum iterations reached
-1: Evaluation limit exceeded
-3: Inner loop iteration limit (algorithm-specific)
- messagestr
Human-readable description of termination cause. Provides detailed information about convergence status or failure reasons.
Objective Function Results¶
- funjax.numpy.ndarray
Final residual vector f(x) at the solution. For curve fitting, these are the differences between model predictions and data points.
- costfloat
Final cost function value: 0.5 * ||f(x)||² for standard least squares, or 0.5 * sum(ρ(f_i²/σ²)) for robust loss functions.
- jacjax.numpy.ndarray
Final Jacobian matrix J(x) with shape (m, n) where m is number of data points and n is number of parameters. Computed using JAX autodiff.
- gradjax.numpy.ndarray
Final gradient vector g = J^T * f with shape (n,). Used for convergence checking and parameter uncertainty estimation.
Convergence Metrics¶
- optimalityfloat
Final gradient norm ||g||_inf used for convergence assessment. Should be less than gtol for successful convergence.
- active_masknumpy.ndarray
Boolean mask indicating which parameters hit bounds (for bounded optimization). Shape (n,) with True for parameters at constraints.
Iteration Statistics¶
- nfevint
Total number of objective function evaluations during optimization. Each evaluation computes residuals f(x) for given parameters.
- njevint
Total number of Jacobian evaluations. With JAX autodiff, this equals the number of combined function+gradient evaluations.
- nitint
Number of optimization iterations completed. Not always available for all algorithms.
Algorithm-Specific Results¶
- pcovjax.numpy.ndarray, optional
Parameter covariance matrix with shape (n, n). Provides parameter uncertainty estimates. Available when uncertainty estimation is requested. Computed as: pcov = inv(J^T * J) * residual_variance
- active_masknumpy.ndarray
For bounded optimization, indicates which parameters are at bounds.
- all_timesdict, optional
Detailed timing information for algorithm profiling. Contains timing data for different optimization phases (function evaluation, Jacobian computation, linear algebra operations, etc.).
Usage Examples¶
Basic result access:
import nlsq # Perform curve fitting result = nlsq.curve_fit(model_func, x_data, y_data, p0=initial_guess) # Access optimized parameters fitted_params = result.x # Check convergence if result.success: print(f"Optimization converged: {result.message}") print(f"Final cost: {result.cost}") print(f"Function evaluations: {result.nfev}") else: print(f"Optimization failed: {result.message}") # Parameter uncertainties (if covariance computed) if hasattr(result, 'pcov'): param_errors = jnp.sqrt(jnp.diag(result.pcov)) print(f"Parameter uncertainties: {param_errors}")
Advanced result inspection:
# Examine residuals and fit quality final_residuals = result.fun rms_error = jnp.sqrt(jnp.mean(final_residuals**2)) # Check gradient convergence gradient_norm = result.optimality print(f"Final gradient norm: {gradient_norm}") # Analyze Jacobian condition jacobian = result.jac condition_number = jnp.linalg.cond(jacobian) print(f"Jacobian condition number: {condition_number}") # For bounded problems, check active constraints if hasattr(result, 'active_mask'): constrained_params = jnp.where(result.active_mask)[0] print(f"Parameters at bounds: {constrained_params}")
Integration with SciPy¶
This class maintains compatibility with scipy.optimize.OptimizeResult while adding JAX-specific features and NLSQ-specific results. It can be used interchangeably with SciPy optimization results in most contexts.
Technical Notes¶
All JAX arrays are automatically converted to NumPy arrays for compatibility
Covariance matrices use double precision for numerical stability
Large dataset results may include memory management statistics
GPU timing results require explicit timing mode activation
Progress monitoring data is stored in algorithm-specific attributes
OptimizeWarning¶
- class nlsq.result.OptimizeWarning[source]
Bases:
UserWarningWarning class for optimization-related issues.
This warning is raised when non-critical issues are encountered during optimization, such as unknown solver options, convergence concerns, or numerical stability warnings that don’t prevent the optimization from completing but should be brought to the user’s attention.
- Common scenarios:
Unknown or deprecated solver options passed to optimizer
Convergence achieved but with warnings about numerical conditioning
Parameter bounds adjusted automatically
Automatic algorithm selection overrides
Example
>>> import warnings >>> warnings.filterwarnings('error', category=OptimizeWarning) >>> # Now OptimizeWarning will raise an exception instead of warning
See also
nlsq.error_messages.OptimizationError : Exception for critical failures
Example Usage¶
from nlsq import curve_fit
# Perform fit
popt, pcov = curve_fit(model, x, y, p0=[1.0, 0.1], full_output=True)
# Access additional result information
# (when using LeastSquares directly)
from nlsq import LeastSquares
ls = LeastSquares()
result = ls.least_squares(residuals, p0)
print(f"Success: {result.success}")
print(f"Message: {result.message}")
print(f"Number of iterations: {result.nit}")
print(f"Final cost: {result.cost}")
Result Attributes¶
The OptimizeResult object contains:
x: Solution parameters
success: Whether optimization succeeded
status: Termination status code
message: Description of termination
fun: Final residuals
jac: Final Jacobian matrix
cost: Final cost value
nfev: Number of function evaluations
njev: Number of Jacobian evaluations
nit: Number of iterations
Migration Notes¶
As of v0.4.3, OptimizeResult and OptimizeWarning have been moved from
nlsq.core._optimize to nlsq.result. The old import paths continue to
work with deprecation warnings during the 12-month transition period:
# Old (deprecated)
from nlsq.core._optimize import OptimizeResult
# New (recommended)
from nlsq.result import OptimizeResult
# or
from nlsq import OptimizeResult
See Also¶
nlsq.least_squares module - Least squares solver
nlsq.minpack module - curve_fit interface