fips.Posterior.r2#
- property Posterior.r2: float#
The R² of the enhancement, \(\operatorname{corr}(z - c, H\hat{x})^2\).
How well the estimate fits the part of the observations the state explains: the observations \(z\) less the offset \(c\) (in a flux inversion, the enhancement over the background), against \(H\hat{x}\), which is
modeled_obsless the offset.The offset is taken out because it is given, not fitted. One that varies from observation to observation, as a background does from day to day, would otherwise raise the correlation by how well it follows the observations, whatever the fit of the state. A constant offset, or none, changes no correlation: then this is the squared correlation of the observations and
modeled_obs.It is a squared correlation, not \(1 - SS_{res} / SS_{tot}\): a fit that is off by a constant or a factor scores as well as an exact one.
rmsemeasures the misfit itself.See also
modeled_obs\(H\hat{x} + c\).
rmseThe root mean square of the residuals.
Examples
Four days of one flux over a background that rises from day to day, given as the offset:
>>> import numpy as np >>> import pandas as pd >>> import fips >>> state = fips.Space({"flux": pd.Index(["a"], name="cell")}) >>> days = fips.Space({"co2": pd.RangeIndex(4, name="day")}) >>> background = np.array([400.0, 402.0, 404.0, 406.0]) >>> problem = fips.Problem( ... prior=fips.Vector(np.zeros(1), state), ... prior_cov=fips.Covariance.diagonal(1.0, state), ... obs=fips.Vector(background + [1.0, 0.0, 2.0, 1.0], days), ... obs_cov=fips.Covariance.diagonal(0.5, days), ... forward=fips.Operator( ... np.array([[1.0], [0.5], [1.5], [0.0]]), days, state ... ), ... offset=fips.Vector(background, days), ... ) >>> post = fips.solve(problem) >>> round(post.r2, 3) 0.4
With the background left in, its rise alone would make the fit look nearly perfect:
>>> z, modeled = problem.obs.values, post.modeled_obs.values >>> round(float(np.corrcoef(z, modeled)[0, 1] ** 2), 3) 0.983