class gpr::laplace::TCovSecondOrder¶
Overview¶
Analytical closed-form 2nd-order TCOV-INLA correction cache (partial). More…
#include <TCovSecondOrder.h>
class TCovSecondOrder {
public:
// fields
static double kTrustTau = 0.5;
// construction
TCovSecondOrder();
// methods
bool compute(const GaussianProcessRegression& gpr, const Eigen::MatrixXd& H_inv);
void applyCorrection(const GaussianProcessRegression& gpr, Observation& image1);
bool valid() const;
std::size_t nLs() const;
void invalidate();
};
Detailed Documentation¶
Analytical closed-form 2nd-order TCOV-INLA correction cache (partial).
- At the MAP hyperparameter theta_star, precomputes the vectors needed to evaluate the quadratic-in-Delta theta correction to the predictive mean at any query x*: m(x*) = mu_MAP(x*)
0.5 * sum_{ij} (H^{-1})_{ij} * d^2 mu / d theta_i d theta_j (x*)
- with d^2 mu / d theta_i d theta_j (x*) =
k_{ij}(x*)^T * alpha_star
k_i(x*)^T * z_j - k_j(x*)^T * z_i
k_star(x*)^T * beta_{ij}
SymPy proof: python/tests/test_sympy_laplace_tcov_analytical.py (identities A1-A8; A8 is the partial-scope acceptance gate).
SCOPE: only (log_magn, log_magn) and (log_magn, log_ls_d) pairs are kept. Both (log_ls_d, log_ls_e) and (log_sn, *) are set to zero. The A8 gate shows this captures >= 50% of the full 2nd-order shift when H diagonal on log_ls is >= 10x the entry on log_magn, with sign agreement in the tight-posterior regime. The missed (ls, ls) terms are suppressed by 1/H_ls^2 and dominate only in the broad- posterior regime, which is opposite the post-SCG regime we target.
Required cached quantities, evaluated ONCE at theta_star:
K_d = dK / d theta_d |_* for d in {0 (magn), 1..nls (ls)} z_d = K_star^{-1} * K_d * alpha_star (m_tr vectors, size m_tr) beta_{0,d} = K_star^{-1} * (K_0 z_d + K_d z_0 - K_d alpha_star) for d in {0..nls} (beta_{00} = K_star^{-1} * (2 K_0 z_0 - K_0 alpha_star)) using A2: K_{0,0} = K_0 and K_{0,d} = K_d
m_tr = rows of gpr.R_matrix (= N_tr * (D+1) with gradient observations).
Non-copyable, value-semantic.
Fields¶
static double kTrustTau = 0.5
Trust-region cap on the per-component Taylor correction: applyCorrection writes image1.{E,G} += sign(corr) * min(|corr|, kTrustTau * |MAP|). With kTrustTau < 1 the corrected gradient stays in the same hemisphere as MAP proven by sympy TR2 in python/tests/test_sympy_laplace_trust_region.py. Exposed as a class constant so tests can reference the same value.
Methods¶
bool compute(const GaussianProcessRegression& gpr, const Eigen::MatrixXd& H_inv)
Populate the cache at the current GPR state (after decomposeCovarianceMatrix at theta_star and alpha = K_star^-1 y).
Parameters:
gpr |
Configured GPR (must have valid L and a at theta*). |
H_inv |
Inverse Hessian (p x p) from the Laplace cache. |
Returns:
true on success; false if K_star is singular or hypers are invalid (fall back to MAP or to the 1st-order TCOV-INLA path).
void applyCorrection(const GaussianProcessRegression& gpr, Observation& image1)
Apply the partial 2nd-order correction to image1.E and image1.G per query point. Adds the quadratic shift in-place.
bool valid() const
Is the cache populated and usable?
std::size_t nLs() const
Number of cached lengthscale dimensions (0..n_ls).
void invalidate()
Invalidate (drops all cached vectors).