GEE unfolding: generalized estimating equations (gee port)#
The unfold_gee method is the Python analogue of the R package
gee 4.13-30 (V. Carey, T. Lumley, B. Ripley, CRAN, GPL-2; the
Liang-Zeger quasi-score solver). GEE treats the detector spheres of a
single Bonner-sphere irradiation as a correlated cluster of
observations of the same measurement b = A x and estimates the
spectrum from the generalized estimating equations
where \(R(\alpha)\) is the working correlation matrix and
\(G = D_2^{\mathsf T} D_2\) is the second-difference roughness
penalty (the ridge that makes the underdetermined system well posed;
regularization = lam is relative to the mean diagonal of
\(A^{\mathsf T} R^{-1} A\), like in the other bssunfold methods).
Working correlation structures#
corstr="independence"— \(R = I\) (the Liang-Zeger classical first model);corstr="exchangeable"(default) — \(R_{ii} = 1\), \(R_{ij} = \alpha\); \(\alpha\) is estimated by the classic method-of-moments (mean of the off-diagonal products of the standardised residuals), clipped into the SPD region;corstr="ar1"— \(R_{ij} = \alpha^{|i-j|}\) with the lag-1 moment estimator.
Quasi-likelihood families#
family selects the variance function \(v(\mu)\) (identity link):
"gaussian"— \(v = 1\) (default);"poisson"— \(v = \mu\) (counts-like readings);"gamma"— \(v = \mu^2\).
Robust (sandwich) uncertainties#
The selling point of gee over plain weighted least squares is the
inference: the module reports the two canonical Liang-Zeger covariance
estimators for the unfolded spectrum,
where \(\hat r_i\) are the Pearson residuals of the (working)
model. The robust sandwich stays consistent when the working
correlation is misspecified; the naive estimator is the
model-based inverse of the penalised information matrix. Both are
returned as robust_se / naive_se (and the full matrices in the
_full diag), plus alpha,
phi, pearson_chi2, iterations and converged.
Example#
from bssunfold import Detector
det = Detector(RF_GSF)
result = det.unfold_gee(readings) # gaussian/exchangeable
result = det.unfold_gee(readings, family="poisson", corstr="ar1")
print(result["robust_se"])
Notes#
The iteration is the standard GEE/IRLS loop: solve the (penalised) GLS for the current \(R(\alpha)\), re-estimate
alphaand the dispersionphi, repeat until the relative spectrum update is belowtolerance(or the projected iteration stalls on an active set).Non-negativity is enforced by the standard bssunfold clipping convention (GEE itself is unconstrained, like the R package).
PURE NumPy: with 10-30 spheres the
m x mworking-correlation algebra is negligible.