MagNET / analysis /code /shared /stats.py
ekwan16's picture
Add files using upload-large-folder tool
64c992d verified
Raw
History Blame Contribute Delete
2.29 kB
"""Error statistics and least-squares fitting shared across the analysis modules.
numpy.linalg.lstsq, not statsmodels: fitting by formula string through statsmodels' patsy parser is
about 1000x slower in a loop that fits many (solvent, solute, formula) combinations, so every fitting
harness here builds a plain design matrix and calls ols_fit directly. Where a module still needs to
report a p-value or similar statsmodels-only diagnostic, keep a separate, explicitly-named
statsmodels code path as a test oracle, not the harness itself.
"""
import numpy as np
def rmse(predicted, actual):
predicted = np.asarray(predicted, dtype=float)
actual = np.asarray(actual, dtype=float)
return float(np.sqrt(np.mean(np.square(predicted - actual))))
def mae(predicted, actual):
predicted = np.asarray(predicted, dtype=float)
actual = np.asarray(actual, dtype=float)
return float(np.mean(np.abs(predicted - actual)))
def median_ae(predicted, actual):
predicted = np.asarray(predicted, dtype=float)
actual = np.asarray(actual, dtype=float)
return float(np.median(np.abs(predicted - actual)))
def summarize_errors(predicted, actual):
"""{"n", "rmse", "mae", "median_ae"} for one (predicted, actual) pair."""
predicted = np.asarray(predicted, dtype=float)
actual = np.asarray(actual, dtype=float)
return {
"n": int(predicted.size),
"rmse": rmse(predicted, actual),
"mae": mae(predicted, actual),
"median_ae": median_ae(predicted, actual),
}
def ols_fit(design, response):
"""Least-squares coefficient vector for `design @ beta ~ response`. Callers build `design`
(including any intercept column) and drop non-finite rows themselves -- this is a thin,
single-purpose wrapper, not a formula parser."""
design = np.asarray(design, dtype=float)
response = np.asarray(response, dtype=float)
beta, _residuals, _rank, _sv = np.linalg.lstsq(design, response, rcond=None)
return beta
def linear_fit_1d(x, y):
"""(intercept, slope) of the least-squares line through (x, y)."""
x = np.asarray(x, dtype=float)
y = np.asarray(y, dtype=float)
design = np.column_stack([np.ones(len(x)), x])
intercept, slope = ols_fit(design, y)
return float(intercept), float(slope)