Zhenyu (Zach) Wang
Home Blog Teaching
← All posts

Confidence intervals in high dimensions, in one R package: SIHR

The R Journal · with Prabrisha Rakshit (equal contribution), T. Tony Cai, Zijian Guo · arXiv:2109.03365 · package

The short version

Problem
The \(\ell_1\) penalty that makes the Lasso work in \(p \gg n\) also biases it. The bias is of the same order as the standard error, so naive confidence intervals are not merely imprecise — they are invalid.
Fix
Estimate the bias and subtract it. The corrected estimator splits into an asymptotically normal term plus a provably negligible remainder, which restores honest intervals.
The engine
One construction — a projection direction \(\widehat u\) from a small constrained quadratic program, plus a correction term — serves every target, in both linear and logistic models.
What's packaged
Five inference targets behind one interface: coefficients and predictions, quadratic functionals for group signal, treatment effects, and two-sample inner products and distances.
Why bother
Debiasing is target-specific, fiddly, and scattered across a decade of papers. SIHR turns it into a few lines of R, debiasing once per target rather than \(p\) times.

The problem: a point estimate is not a finding

When a regression has more variables than observations, penalized estimators like the Lasso are the workhorse. Consider the penalized maximum likelihood estimator for a generalized linear model, \(\mathbb E(y_i \mid X_{i\cdot}) = f(X_{i\cdot}^\top\beta)\) with \(f(z) = z\) (linear) or \(f(z) = e^z/(1+e^z)\) (logistic):

\[ \widehat\beta \;=\; \arg\min_{\beta}\ \ell(\beta) \;+\; \lambda_0 \sum_{j=2}^{p} \frac{\|X_{\cdot j}\|_2}{\sqrt n}\,|\beta_j|, \qquad \lambda_0 \asymp \sqrt{\log p / n}. \]

This attains optimal estimation rates and selects variables well. What it cannot do is support inference. The penalty shrinks coefficients toward zero, and that shrinkage is a bias whose magnitude is comparable to — or larger than — the estimator's standard error. Report \(\widehat\beta_j\) with a naive standard error and the resulting interval is centred in the wrong place. Its coverage does not converge to the nominal level; it converges to something else entirely. In genomics, economics, and biostatistics — the fields that live in high dimensions — a point estimate without honest uncertainty is often not enough to make a claim.

The fix: debias, then infer

Take a target like \(x_{\mathrm{new}}^\top\beta\), a prediction at a new covariate value (set \(x_{\mathrm{new}} = e_j\) and you get the individual coefficient \(\beta_j\)). The plug-in \(x_{\mathrm{new}}^\top\widehat\beta\) carries the bias; the correction adds back an estimate of it, weighted by a projection direction \(\widehat u\):

\[ \widehat{x_{\mathrm{new}}^\top\beta} \;=\; x_{\mathrm{new}}^\top\widehat\beta \;+\; \widehat u^\top\, \frac1n\sum_{i=1}^{n} X_{i\cdot}\big(y_i - X_{i\cdot}^\top\widehat\beta\big). \]

Why does this help? Because the error of the corrected estimator decomposes exactly into a term we understand and a term we can control:

\[ \widehat{x_{\mathrm{new}}^\top\beta} - x_{\mathrm{new}}^\top\beta \;=\; \underbrace{\widehat u^\top \tfrac1n\textstyle\sum_i X_{i\cdot}\,\epsilon_i}_{\text{asymptotically normal}} \;+\; \underbrace{(\widehat\Sigma\widehat u - x_{\mathrm{new}})^\top(\beta - \widehat\beta)}_{\text{remaining bias}} . \]

The second term is a product of two small things, and it is small provided \(\widehat\Sigma\widehat u\) is close to \(x_{\mathrm{new}}\). That is precisely what \(\widehat u\) is chosen to arrange, while keeping the variance \(u^\top\widehat\Sigma u\) of the first term as small as possible:

\[ \widehat u = \arg\min_{u}\ u^\top\widehat\Sigma u \quad\text{s.t.}\quad \underbrace{\|\widehat\Sigma u - x_{\mathrm{new}}\|_\infty \le \|x_{\mathrm{new}}\|_2\,\lambda}_{\text{controls the bias}}, \quad \underbrace{\big|x_{\mathrm{new}}^\top\widehat\Sigma u - \|x_{\mathrm{new}}\|_2^2\big| \le \|x_{\mathrm{new}}\|_2^2\,\lambda}_{\text{makes the normal term dominate}} . \]

The first constraint is the familiar one. The second is the crucial one: the paper describes it as what ensures asymptotic normality for any loading \(x_{\mathrm{new}}\), rather than only for the sparse loadings (like \(e_j\)) that coordinate-wise debiasing was built for. With both in force, \(\big(\widehat{x_{\mathrm{new}}^\top\beta} \pm z_{\alpha/2}\sqrt{\widehat V}\big)\) is an honest interval, with \(\widehat V = \tfrac{\widehat\sigma^2}{n}\widehat u^\top\widehat\Sigma\widehat u\).

The same machinery covers logistic regression once a weight \(\omega(\cdot)\) is inserted, so that a single implementation serves all supported models:

\[ \widehat{x_{\mathrm{new}}^\top \beta} = x_{\mathrm{new}}^\top \widehat\beta + \widehat u^\top \frac1n \sum_{i=1}^n \omega\big(X_{i\cdot}^\top\widehat\beta\big)\big(y_i - f(X_{i\cdot}^\top\widehat\beta)\big) X_{i\cdot}. \]
Model\(f(z)\)\(f'(z)\)weight \(\omega(z)\)
linear\(z\)\(1\)\(1\)
logistic\(e^z/(1+e^z)\)\(e^z/(1+e^z)^2\)\((1+e^z)^2/e^z\)
logistic_alter\(e^z/(1+e^z)\)\(e^z/(1+e^z)^2\)\(1\)

The two logistic options implement different theoretical routes: logistic uses the linearization weighting, logistic_alter the link-specific one. For a case probability \(f(x_{\mathrm{new}}^\top\beta)\), apply \(f\) to the endpoints of the interval for \(x_{\mathrm{new}}^\top\beta\).

One engine, five targets

Here is the design idea that makes the package more than a wrapper. Many quantities of scientific interest are not linear in \(\beta\), yet their plug-in bias is. Take a quadratic functional \(Q_A = \beta_G^\top A \beta_G\), the natural measure of how much signal a group \(G\) of variables carries. Its plug-in bias is dominated by \(2\,\widehat\beta_G^\top A(\widehat\beta_G - \beta_G)\) — which is a linear functional with loading \(x_{\mathrm{new}} = (\widehat\beta_G^\top A, \mathbf 0^\top)^\top\). So you debias once more, with the machinery you already have:

\[ \widehat Q_A \;=\; \widehat\beta_G^\top A \widehat\beta_G \;+\; 2\,\widehat u_A^\top \Big[\frac1n\sum_i \omega\big(X_{i\cdot}^\top\widehat\beta\big)\big(y_i - f(X_{i\cdot}^\top\widehat\beta)\big)X_{i\cdot}\Big], \]

truncated at zero. The same trick — recognize the leading bias as a linear functional, then reuse LF() — generates treatment effects, two-sample inner products, and distances between regression vectors. The variance for the quadratic targets gains a term \(\tau/n\) that upper-bounds the discarded second-order piece \((\widehat\beta_G - \beta_G)^\top A(\widehat\beta_G - \beta_G)\); it also guards against super-efficiency when \(Q_A \approx 0\), which is exactly the null you usually want to test.

debias onceprojection direction û+ correction termLF()xnew βcoefficients, predictions, case probabilitiesQF()βG A βGgroup signal strength, heritabilityCATE()f(xβ(2)) − f(xβ(1))treatment effect at a covariate valueInnProd()βG(1) A βG(2)similarity of two populations’ modelsDist()γG A γG, γ = β(2)− β(1)heterogeneity between two populationsEach call returns a bias-corrected estimate, a standard error, and a confidence interval.
Figure 1. The package's five estimating functions. Each reduces to the same debiasing step — find a projection direction, add a correction — applied once, or twice for the two-sample targets. Debiasing once per target, rather than once per coordinate, is what separates SIHR from coordinate-wise debiased-Lasso packages: for a linear functional those need \(p\) separate optimizations.
FunctionTargetTypical use
LF()\(x_{\mathrm{new}}^\top\beta\)a coefficient, a prediction, a case probability
QF()\(\beta_G^\top A\,\beta_G\) or \(\beta_G^\top\Sigma_{G,G}\beta_G\)group significance, heritability, explained variance
CATE()\(f(x_{\mathrm{new}}^\top\beta^{(2)}) - f(x_{\mathrm{new}}^\top\beta^{(1)})\)conditional average treatment effect
InnProd()\(\beta_G^{(1)\top} A\,\beta_G^{(2)}\)similarity of two populations' models (e.g. genetic relatedness)
Dist()\(\gamma_G^\top A\,\gamma_G,\ \ \gamma = \beta^{(2)}-\beta^{(1)}\)heterogeneity between populations; transfer learning

Companion methods ci() and summary() return the interval, and the plug-in estimate, bias-corrected estimate, standard error, z-value and p-value respectively.

In practice the whole thing is two lines. The columns of loading.mat are the loadings \(x_{\mathrm{new}}\) you care about, evaluated in a single call:

# n = 100, p = 120; two loadings evaluated at once
Est = LF(X, y, loading.mat, model = 'linear')
ci(Est)
summary(Est)

Does it work?

A word on what evidence exists. The paper is a software article: it does not carry a simulation study reporting coverage percentages or timing benchmarks, and its comparisons with hdi, DoubleML and selectiveInference are argued conceptually rather than measured. What it does provide is six worked examples with known ground truth, and two real analyses. The examples make the point cleanly — in every one, the plug-in is visibly shrunk toward zero and the debiased interval covers the truth.

0-3-2-112linear, loading 1linear, loading 2logistic, loading 1logistic, loading 2plug-in Lassodebiased + 95% CItruthEvery debiased interval covers the truth; every plug-in point is shrunk toward zero.
Figure 2. The paper's Examples 1 and 2, exactly as reported. Linear model: \(n=100\), \(p=120\), targets \(1.5\) and \(-1.25\). Logistic model: \(n=300\), \(p=120\), targets \(2\) and \(-2.5\), where the authors describe the plug-ins as "severely biased" — \(1.340\) for a truth of \(2\). The bias always points toward zero, the debiased point moves back out, and all four intervals cover.
ExampleTargetTruthPlug-inDebiased95% CI
LF, linear\(x_{\mathrm{new}}^\top\beta\)1.51.2681.522(1.168, 1.875)
LF, logistic\(x_{\mathrm{new}}^\top\beta\)21.3401.875(1.258, 2.492)
QF, linear\(\beta_G^\top\Sigma_{G,G}\beta_G\)1.160.9041.139(0.812, 1.466)
CATE, logistic_alter\(x_{\mathrm{new}}^\top(\beta^{(2)}-\beta^{(1)})\)2.6(1.614, 4.515)
InnProd, linear\(\beta^{(1)\top}A\beta^{(2)}\)1.6(0.743, 2.490)
Dist, linear\(\gamma_G^\top\Sigma_{G,G}\gamma_G\)0.3410.4270.356(0.028, 0.683)

Every interval covers its truth. For QF, InnProd and Dist the CI shown uses \(\tau = 0.25\); larger \(\tau\) widens it (for Dist, \(\tau = 0.5\) already truncates the lower endpoint at 0 and the effect stops being significant at the 5% level — \(p = 0.055\) versus \(p = 0.033\)). Note that Dist's plug-in is biased away from zero, as a squared quantity should be.

The two applications show the interface doing real work. In motif regression — predicting transcription-factor binding intensity from \(p = 666\) candidate motifs over \(n = 2{,}587\) genes — one call to LF() with loading.mat = diag(p) returns all 666 intervals; 25 lie entirely above zero and 23 entirely below, isolating 48 significant motifs. In a fasting-glucose GWAS on 1,269 heterogeneous-stock mice, the response is dichotomized at 11.1 mmol/L and the markers pruned from 10,346 to 2,341 (pairwise \(|\text{correlation}| < 0.75\)), with gender and age as baseline covariates; a logistic LF() call yields 13 intervals entirely above zero and 16 entirely below.

1 vs \(p\)Debiasing optimizations needed for a linear functional: SIHR debiases once, coordinate-wise packages once per variable
666 → 48Motif intervals returned in one call; 48 exclude zero
2,341Markers with simultaneous logistic intervals in the mouse glucose analysis

Why it matters

Debiased inference had strong theory and a high implementation barrier — the corrections are target-specific, the projection direction needs its own tuning, and the details live in a decade of separate papers. Most applied users never got past that. SIHR collapses the barrier: a handful of functions, a consistent interface, valid intervals for the functionals people actually want, and both linear and logistic models. The broader lesson is worth stating plainly — the debiasing step is a reusable primitive, not a one-off trick for individual coefficients. Once you see that a quadratic functional's leading bias is itself a linear functional, the same engine covers group signal, treatment effects, and cross-population comparisons.

Caveats to keep in view. Validity rests on the usual high-dimensional assumptions: a sparse \(\beta\), a correctly specified link, and tuning at \(\lambda \asymp \sqrt{\log p/n}\). The intervals are mildly conservative by design — rescale = 1.1 inflates standard errors to absorb finite-sample bias. Quadratic and two-sample targets depend on the tuning parameter \(\tau\), and the package deliberately reports a vector of intervals across \(\tau\) rather than hiding the choice; treat it as a conservative variance inflation, and note that conclusions can change with it, as Dist above shows. Logistic inference relies on prob.filter to drop observations with fitted probabilities near 0 or 1, and QF(split = TRUE) needs a larger \(n\). Finally, the comparisons against other packages are conceptual: the paper reports no head-to-head coverage or timing table.

© 2026 Zhenyu (Zach) Wang 王振宇