fips.Posterior.candidate_worth#
- Posterior.candidate_worth(forward, obs_cov, by, W)[source]#
Return what each group of candidate observations, not in the problem, would add to the certainty of each aggregate.
Candidate observations are rows of a forward operator that the problem does not have (a new site, another platform, a season not yet measured) and the covariance of their errors; their values are not needed. For each group of candidates, the posterior standard deviation of each aggregate without the group (this posterior) and with it, from a rank \(m_c\) update of \(\hat{S}\), without solving again:
\[\hat{S}_{+c} = \hat{S} - \hat{S} H_c^T F^{-1} H_c \hat{S}, \qquad F = H_c \hat{S} H_c^T + R_c / \gamma,\]with \(H_c\) the group’s rows of forward and \(R_c\) its block of obs_cov. The errors of the candidates are taken to be independent of the problem’s observations, and are divided by the regularization factor \(\gamma\) as the problem’s are, so the result is the posterior of the problem solved again with the group’s observations added. For \(W\), the three blocks \(W \hat{S} W^T\), \(W \hat{S} H_c^T\) and \(H_c \hat{S} H_c^T\) are one
cov()of \(W\) and \(H_c\) stacked: nothingn x nis formed. Each group is added on its own, to the problem as it is.- Parameters:
forward (
Operator) – The candidates’ forward operator, from the state (its columns, the state’s labels in any order) to the candidate observations (its rows, labeled as observations are, on the levels by groups).obs_cov (
Covariance|CovarianceModel) – The covariance of the candidates’ errors, on the rows of forward; a model (fips.Independent().with_std(5.0)) is built there. It must be positive-definite.by (
Any) – The levels of the candidates’ labels to group by, asdata_worth()takes them ("site").W (
Operator) – An aggregation, ascov()takes it: one row per aggregate.
- Returns:
As
data_worth(): one row per group and aggregate, withn_obs,dofs(the group’s share of DOFS in the problem with it added, \(m_c - \operatorname{tr}(R_c F^{-1}) / \gamma\)),std_without(this posterior’s),std_with(with the group added) andreduction, \(1 - \sigma_{with} / \sigma_{without}\). A variance below zero by more than roundoff, which only a covariance that is not positive semidefinite can give, makes its standard deviation and the reduction NaN, with a logged warning (as inuncertainty()).- Return type:
- Raises:
TypeError – If the method’s estimate is not linear in the observations (its solution does not set
estimate_is_linear), forward or W is not an Operator, or obs_cov is not a covariance.ValueError – If the columns of forward or W do not have exactly the state’s labels, obs_cov is not on the rows of forward, or by puts no candidate in a group.
See also
data_worthWhat the groups of observations in the problem add.
uncertaintyThe prior and posterior uncertainty of each aggregate.
Notes
A candidate group is always added on top of the problem’s observations, so there are no
std_aloneandreduction_alonecolumns, whichdata_worth()has for the groups in the problem.Examples
One flux observed four times at site A; would a candidate site B, three observations with errors of the same size, help more than one more observation at A?
>>> import numpy as np >>> import pandas as pd >>> import fips >>> state = fips.Space({"flux": pd.Index(["a"], name="cell")}) >>> observed = fips.Space( ... { ... "co2": pd.MultiIndex.from_product( ... [["A"], range(4)], names=["site", "hour"] ... ) ... } ... ) >>> problem = fips.Problem( ... prior=fips.Vector(np.zeros(1), state), ... prior_cov=fips.Covariance.diagonal(1.0, state), ... obs=fips.Vector(np.ones(4), observed), ... obs_cov=fips.Covariance.diagonal(1.0, observed), ... forward=fips.Operator(np.ones((4, 1)), observed, state), ... ) >>> post = fips.solve(problem) >>> candidates = fips.Space( ... { ... "co2": pd.MultiIndex.from_tuples( ... [("A", 4), ("B", 0), ("B", 1), ("B", 2)], names=["site", "hour"] ... ) ... } ... ) >>> H_new = fips.Operator(np.ones((4, 1)), candidates, state) >>> W = fips.Operator(np.eye(1), state, state) >>> table = post.candidate_worth( ... H_new, fips.Independent().with_std(1.0), by="site", W=W ... ) >>> table.droplevel("block").round(3).reset_index() site cell n_obs dofs std_without std_with reduction 0 A a 1 0.167 0.447 0.408 0.087 1 B a 3 0.375 0.447 0.354 0.209