This vignette canonizes the T-learner AMM-side causal
bridge introduced in Sub-phase 8.5.A. It is the operative
continuation of vignette("v08_cate_ite_positioning"): where
v08 places AMM relative to the CATE/ITE literature (Proposition 8A: AMM
is a predictive object, CATE is a counterfactual object), this addendum
specifies the one explicit construction that turns a pair of
independent AMM fits into a CATE estimator. The construction follows the
T-learner of Kuenzel et al. (2019), specialized to the
AMM-side.
The exported entry point is the function
gdpar_causal_bridge(fit_treat, fit_ctrl, newdata, ...). The
function is not an argument of gdpar(); it
is a separate function that consumes two gdpar_fit objects
already produced by gdpar(). This API choice preserves the
strict separation between AMM as a generic predictive framework and CATE
as a causal-identification overlay (Proposition 8A); it also keeps the
bridge decoupled from the inference machinery so that S-learner,
X-learner, doubly-robust and double-machine-learning extensions can be
added in later sub-phases without disturbing the AMM core.
What this addendum is. A formal definition of the T-learner AMM-side, the identification assumptions it inherits from v02 plus the residual no-confounding assumption that it introduces, the posterior-difference estimator and its credible bounds, and the structural compatibility contract the bridge enforces between the two fits. The minimum reproducible example of §8 exercises the whole API; the limitations and open questions of §9 and §10 anchor the deferred extensions in Block 9.
What this addendum is not. It is not a tutorial on causal inference (Imbens-Rubin 2015 remains the canonical reference); it is not a comparator with external meta-learners (Sub-phase 8.5.B); it is not a guide to specifying AMM models (v00, v01, vop01-vop05 cover that).
For full statements see
vignette("v08_cate_ite_positioning") §2 and Appendix A. The
minimal table needed here:
| Symbol | Meaning |
|---|---|
| \(T_i \in \{0, 1\}\) | Treatment indicator |
| \((Y_i(0), Y_i(1))\) | Potential outcomes (Rubin 1974) |
| \(Y_i = T_i Y_i(1) + (1 - T_i) Y_i(0)\) | Observed outcome under (CONS) |
| \(\mu_t(x) = \mathbb{E}[Y(t) \mid X = x]\) | Conditional potential-outcome means |
| \(\tau(x) = \mu_1(x) - \mu_0(x)\) | CATE function |
| \(e(x) = \Pr(T = 1 \mid X = x)\) | Propensity score |
| \(\theta_i^{(t)} = \theta_{\text{ref}}^{(t)} + \Delta^{(t)}(x_i, \theta_{\text{ref}}^{(t)})\) | AMM parameter under arm \(t \in \{0, 1\}\) |
| \((\text{IGN})\) | Ignorability: \((Y(0), Y(1)) \perp T \mid X\) |
| \((\text{OVL})\) | Overlap: \(0 < e(x) < 1\) for \(\mu\)-a.e. \(x\) |
| \((\text{CONS})\) | Consistency / SUTVA |
The superscript \((t)\) on AMM objects refers to the arm under which the fit was produced (treatment arm \(t = 1\), control arm \(t = 0\)). The T-learner fits one AMM model per arm independently; the per-arm parameters \(\theta_i^{(t)}\) are different objects of estimation, and there is no parameter shared between the two fits.
Definition 8.5.A-1 (T-learner AMM-side). Let \(\mathcal{D}_1 = \{(x_i, y_i) : T_i = 1\}\) and \(\mathcal{D}_0 = \{(x_i, y_i) : T_i = 0\}\) be the treatment and control sub-samples. Fix one AMM specification \(\mathcal{A}\) (formula, family with link \(g\), anchor, AMM level, modulating basis) and use it for both arms. The T-learner AMM-side bridge is:
- Fit \(\widehat{\theta}^{(1)} = \texttt{gdpar}(\mathcal{D}_1, \mathcal{A})\).
- Fit \(\widehat{\theta}^{(0)} = \texttt{gdpar}(\mathcal{D}_0, \mathcal{A})\).
- For every \(x \in \mathcal{X}_{\text{new}}\), define the per-arm response-scale prediction \(\widehat\mu_t(x) = g^{-1}\!\left( \widehat\theta^{(t)}(x) \right)\) on the inverse link of each arm’s predicted individual parameter.
- The bridge estimator of the CATE at \(x\) is \[\widehat\tau(x) \;=\; \widehat\mu_1(x) - \widehat\mu_0(x).\]
The definition makes three architectural commitments explicit:
Structural symmetry between arms. The two arms
share the same AMM specification \(\mathcal{A}\). The bridge does not
entertain asymmetric specifications (treatment with one AMM level,
control with another); such asymmetry would break the comparability of
the two arms’ predictive objects on which the T-learner depends.
gdpar_causal_bridge enforces this with structural
compatibility checks (see §5 and the function’s
@details).
No parameter sharing. Unlike the S-learner (which fits one model on the pooled data with \(T\) as a covariate) the T-learner fits two independent models. The joint posterior of \((\theta^{(0)}, \theta^{(1)})\) factorizes: \[p\!\left(\theta^{(0)}, \theta^{(1)} \mid \mathcal{D}_0 \cup \mathcal{D}_1\right) \;=\; p\!\left(\theta^{(0)} \mid \mathcal{D}_0\right)\, p\!\left(\theta^{(1)} \mid \mathcal{D}_1\right),\] a direct consequence of \(\mathcal{D}_0 \cap \mathcal{D}_1 = \emptyset\) and the independence of the two priors (gdpar uses the same prior distribution for both arms by default, but the random variables drawn from those distributions are independent across arms). This is the raison d’être of the per-draw difference of §6.
Response-scale CATE by default. Step (3) applies
the inverse link before the difference, so \(\widehat\tau(x)\) is on the natural scale
of the response (mean for Gaussian, rate for Poisson, success
probability for Bernoulli, etc.). The package also exposes the
linear-predictor scale (type = "theta_i") for users who
prefer to report differences on the link-transformed scale; the
trade-off is that the linear-predictor difference is in units of the
link, which are not always interpretable as treatment effects.
The bridge is agnostic to the AMM Path. Definition
8.5.A-1 is stated in terms of the fitted parameter \(\widehat\theta^{(t)}\) without reference to
the path that produced it; Path 1 (Bayesian) is the only path
implemented in 0.0.0.9001 (Sub-phase 8.5.A constrains the bridge to
path = "bayes" and aborts otherwise). Paths 2 and 3 are
mapped to the same construction in §10’s open questions.
The bridge inherits the AMM identifiability hypotheses of Block 1 (applied to each arm) and the gnoseological validity hypotheses of v02 (applied to each arm). On top of those, the T-learner requires the classical causal-identification hypotheses of v08 §2.1, restated here for self-containment, plus one additional structural assumption that is specific to the per-arm decomposition.
Under (IGN)+(OVL)+(CONS), Imbens-Rubin (2015, Theorem 12.1) gives the identifying formula \(\mu_t(x) = \mathbb{E}[Y \mid X = x, T = t]\). The right-hand side is the per-arm conditional expectation that each AMM fit estimates: \(\widehat\mu_t(x) = g^{-1}(\widehat\theta^{(t)}(x))\). The identification of the CATE at \(x\) thus reduces to the identification of each arm’s per-arm conditional expectation, which is exactly the AMM identification problem of Block 1.
The T-learner additionally requires what we call (NCR) Residual no-confounding within each arm:
(NCR). Within each arm \(t \in \{0, 1\}\), the AMM specification \(\mathcal{A}\) contains all covariates necessary to make the conditional expectation \(\mathbb{E}[Y \mid X = x, T = t]\) identifiable from the arm’s sub-sample. Equivalently, no unmeasured confounder of the outcome-treatment relationship is omitted from the AMM components \((a, b, W, x_{\text{vars}})\) at the level of each arm.
(NCR) is not a new substantive assumption beyond (IGN): if (IGN) holds at \(x\) and \(X\) is fully observed, the arm-specific conditional expectation is by definition identifiable. (NCR) merely makes the operational responsibility explicit: the user must include in the AMM specification all the covariates whose omission would create within-arm confounding. A common failure mode is to omit interactions with \(T\) that, under the pooled S-learner specification, would be absorbed by the treatment-indicator coefficient; the T-learner has no treatment indicator (each arm is fit separately), so omitted interactions contaminate the within-arm conditional expectation directly.
The bridge does not — and cannot — verify (IGN) or (NCR) from the data alone; they are causal assumptions and require domain knowledge or design (randomization, instrumental variables, regression discontinuities) to underwrite them. The bridge does verify the structural pre-conditions that make the T-learner construction well-defined: family, link, AMM level, anchor, covariate column structure (see §5).
The bridge is constructed by
gdpar_causal_bridge(fit_treat, fit_ctrl, newdata, type, level).
The structural pre-conditions enforced at construction time are:
path = "bayes".stan_data$use_groups == 0L. The grouped regime of Block 6.5
introduces per-group anchors whose treatment under the T-learner
difference is not defined in the canonical formulation; grouped bridges
are queued for a future sub-phase (see §10).family$name and family$link, and the per-slot
family identifiers when \(K >
1\).K and
p.amm$level (or per-slot levels when \(K > 1\)) and amm$W$type
(polynomial or B-spline).a, b, and
x_vars (per coordinate / slot when multi-dimensional).Any violation aborts with
gdpar_unsupported_feature_error. The intent of the strict
compatibility contract is to refuse meaningless bridges loudly rather
than silently produce CATE estimates whose decomposition mixes
incompatible AMM objects.
When the structural pre-conditions hold, the bridge calls
predict.gdpar_fit(fit_treat, newdata, type, summary = "draws")
and
predict.gdpar_fit(fit_ctrl, newdata, type, summary = "draws"),
aligns their draws (see §6), and computes the per-draw, per-observation
difference:
\[\widehat{\tau}^{(s)}_i \;=\; \widehat{\mu}^{(s)}_{1}(x_i) \;-\; \widehat{\mu}^{(s)}_{0}(x_i), \qquad s = 1, \ldots, S, \ i = 1, \ldots, n_{\text{new}}.\]
The matrix \(\widehat{\tau} \in
\mathbb{R}^{S \times n_{\text{new}}}\) is stored in the returned
object as cate_draws. For multivariate (\(p > 1\)) or K-individual (\(K > 1\)) fits,
predict.gdpar_fit returns a 3-array of shape \(S \times n \times \dim\); the bridge
computes the elementwise difference and stores it as a 3-array of the
same shape.
The two fits are sampled from disjoint sub-samples and are therefore
posteriori independent: the joint posterior of \((\theta^{(0)}, \theta^{(1)})\) factorizes
(§3 (b)). Any draw \((\widehat{\theta}^{(0),
s_0}, \widehat{\theta}^{(1), s_1})\) with \(s_0\) and \(s_1\) drawn independently from each
marginal is a valid sample from the joint. The bridge implements this by
pairing the \(s\)-th draw of one arm
with the \(s\)-th draw of the other
arm, which — under the Monte Carlo exchangeability of draws within a
chain — is a uniformly distributed pairing. When the two fits have
different numbers of draws \(S_t \ne
S_c\), the bridge trims the longer arm to \(S = \min(S_t, S_c)\) and emits a
gdpar_diagnostic_warning.
The per-observation posterior of the CATE at \(x_i\) is summarized by:
cate_mean.cate_ci (default \(\mathrm{level} = 0.95\)).The summary uses empirical quantiles, not a normal-approximation interval, because the per-arm posteriors are not necessarily Gaussian (small-sample, non-Gaussian families) and the difference of two near-Gaussian distributions can have meaningfully heavy tails when the two marginals have different scales.
Marginal ATE. The bridge’s summary()
method also reports the marginal average treatment effect (ATE) over the
evaluation grid:
\[\widehat{\text{ATE}} \;=\; \frac{1}{n_{\text{new}}} \sum_{i = 1}^{n_{\text{new}}} \overline{\tau}_i.\]
The credible bounds of the ATE are computed by first averaging the per-draw CATE over the evaluation grid (giving an \(S\)-vector of per-draw ATEs) and then taking the empirical quantiles of that vector. This ordering preserves the posterior shape of the ATE; it is not equivalent to averaging the per-observation credible bounds. The latter would underestimate the width of the ATE interval by ignoring the cross-observation correlation introduced by parameter sharing within each arm.
The bridge inherits the AMM identifiability machinery of Block 1 and
the (C1)-(C6) static identifiability conditions of v01. Each arm is
fitted by gdpar(), which runs the pre-flight
identifiability check internally and populates the
identifiability_report slot of the fit. The bridge records
both reports as id_check = list(treat = ..., ctrl = ...) in
the returned object; failures in either arm propagate as failures of the
bridge construction (the upstream gdpar() call would have
refused to fit if (C1)-(C6) were violated).
(C7) anti-aliasing of Block 6.5 (the grouped-anchor
condition) is structurally moot in Sub-phase 8.5.A because the
bridge aborts on hierarchical fits (§5, use_groups == 0L is
required on both arms). The design contract is documented here for
forward compatibility: when a future sub-phase extends the bridge to
hierarchical fits, the canonical treatment will invoke
gdpar:::.check_group_aliasing_c7() on each arm’s design
separately, and a violation in either arm will abort the construction.
The per-arm invocation, rather than a joint invocation, is necessary
because the two arms have independent group-anchor columns (the
per-group anchors \(\theta_{\text{ref}}^{(t)}[g]\) are
independent across arms).
The example below is a CRAN-valid demonstration of the bridge on synthetic data. The treatment effect is heterogeneous in \(x_1\) (\(\tau(x) = 1 + 0.5 x_1\)); the example fits both arms, constructs the bridge on a coarse evaluation grid, and prints the bridge and its summary.
library(gdpar)
set.seed(20260524)
n_per_arm <- 300L
beta0 <- 0.2; beta1 <- 0.8
tau0 <- 1.0; tau1 <- 0.5 # true CATE: tau(x) = tau0 + tau1 * x
df_treat <- data.frame(
x1 = rnorm(n_per_arm),
y = NA_real_
)
df_treat$y <- (beta0 + tau0) +
(beta1 + tau1) * df_treat$x1 + rnorm(n_per_arm, sd = 0.4)
df_ctrl <- data.frame(
x1 = rnorm(n_per_arm),
y = NA_real_
)
df_ctrl$y <- beta0 + beta1 * df_ctrl$x1 + rnorm(n_per_arm, sd = 0.4)fit_treat <- gdpar(
formula = y ~ x1,
family = gdpar_family("gaussian"),
amm = amm_spec(a = ~ x1),
data = df_treat,
chains = 2L,
iter_warmup = 500L,
iter_sampling = 500L,
refresh = 0L,
verbose = FALSE
)
fit_ctrl <- gdpar(
formula = y ~ x1,
family = gdpar_family("gaussian"),
amm = amm_spec(a = ~ x1),
data = df_ctrl,
chains = 2L,
iter_warmup = 500L,
iter_sampling = 500L,
refresh = 0L,
verbose = FALSE
)grid <- data.frame(x1 = seq(-2, 2, length.out = 21L))
bridge <- gdpar_causal_bridge(fit_treat, fit_ctrl, newdata = grid)
print(bridge)
summary(bridge)The expected output is a gdpar_causal_bridge object
whose per-observation cate_mean traces the linear function
\(1 + 0.5 \cdot x_1\) to within
posterior credible bounds. The marginal ATE on the symmetric grid \([-2, 2]\) is close to \(1.0\) (the constant term of the
heterogeneous CATE).
To re-evaluate the bridge on a fresh grid without re-running the
compatibility checks, use predict.gdpar_causal_bridge:
grid2 <- data.frame(x1 = seq(-1, 1, length.out = 11L))
re <- predict(bridge, newdata = grid2)
str(re, max.level = 1L)The T-learner is the most direct meta-learner from a structural standpoint (one arm equals one fit equals one model), but it is not universally optimal. The principal limitations are well-known (Kuenzel et al. 2019 §3.4):
Regularization-induced bias in unbalanced samples. When one arm is much larger than the other, the smaller arm’s posterior is more diffuse and the bridge’s CATE estimate inherits that diffusion asymmetrically. The T-learner has no mechanism to borrow strength across arms; the S-learner and X-learner do (the former by pooling in a single model, the latter by an explicit cross-arm correction). The diffusion is faithfully transmitted to the credible bounds, so the bridge does not understate uncertainty — but the point estimate may be biased toward the more diffuse arm’s prior.
No common feature representation. The two arms have independent AMM fits and therefore independent posterior estimates of the basis coefficients \(a\), \(c_b\), \(W_{\text{raw}}\). Any feature that is informative only in combination with treatment is not modeled as such (the treatment indicator is absent from each arm’s specification by construction); the two arms simply do not have a common feature space at the parameter level.
Sensitivity to mis-specification of the conditional mean. Like all conditional-mean estimators, the T-learner relies on the correct specification of \(\mu_t(x)\). AMM mitigates this via the explicit additive-multiplicative-modulated decomposition and the identifiability diagnostics of Block 2, but the underlying sensitivity remains: a mis-specified AMM in either arm produces a biased CATE.
Deferred alternatives. S-learner, X-learner,
doubly-robust (DR), and double-machine-learning (DML) constructions are
queued for Block 9. They will be added as separate functions
(gdpar_causal_s_learner,
gdpar_causal_x_learner, gdpar_causal_dr, etc.)
following the same S3-friendly pattern as
gdpar_causal_bridge, never as arguments of
gdpar(); the principle of strict separation between AMM as
predictive framework and CATE as causal overlay (§1) is preserved across
all the deferred constructions.
The following questions are deferred to Block 9 sub-phases or to Sub-phase 8.5.B. Each is anchored to a specific Path or external dependency.
(O1-CATE) Paths 2 and 3. Extension of the T-learner AMM-side to the varying-coefficient model (Path 2) and the amortized hypernetwork (Path 3). The construction of Definition 8.5.A-1 is path-agnostic at the level of the fitted parameter \(\widehat\theta^{(t)}(x)\), but the posterior of \(\theta\) in Paths 2 and 3 is structurally different (penalized-spline posterior in Path 2; amortized variational posterior in Path 3) and the credible bounds of §6 need adaptation. Queued for Block 9.
(O2-CATE) Hierarchical bridges. Extension to fits with
use_groups == 1L. The canonical treatment will invoke.check_group_aliasing_c7()per arm (§7) and decompose the CATE into a between-group and a within-group component. The decomposition is non-trivial because the per-group anchors \(\theta_{\text{ref}}^{(t)}[g]\) are correlated across observations within the same group but independent across arms.
(O3-CATE) Comparator against external meta-learners. Sub-phase 8.5.B will add
gdpar_compare_meta_learnersas an opt-in benchmark againstgrf,causalForest, and EconML (viareticulate). The charter of 8.5.B is opened only after 8.5.A closes; the dependency on Python (EconML) is the principal architectural reason for the sub-division.
(O4-CATE) S-learner and X-learner AMM-side. Both meta-learners map naturally to the AMM pipeline: S-learner adds \(T\) as a covariate in a single AMM specification and reads the CATE from the contrast between \(T = 1\) and \(T = 0\); X-learner imputes counterfactual outcomes by cross-arm prediction and refits. Both are queued for Block 9. The functions will be
gdpar_causal_s_learnerandgdpar_causal_x_learner.
(O5-CATE) Doubly-robust and double-machine-learning AMM-side. DR and DML add a propensity-score model that the T-learner does not require. The propensity-score model can be a separate
gdparfit on the binary outcome \(T_i\), or an external estimator passed via an argument. Queued for Block 9.
(O6-CATE) Diagnostics for the bridge. A bridge-specific diagnostic battery (overlap plots, posterior-predictive checks per arm, ATE sensitivity to leave-one-out exclusion) would complement the existing per-fit diagnostics. The diagnostic module would consume a
gdpar_causal_bridgeobject. Queued for Block 9.
For readers familiar with the meta-learner literature, the following table maps Kuenzel et al.’s notation to the AMM-side construction of this addendum. Items marked “n/a” are concepts of Kuenzel et al. that have no direct AMM-side analog or that are deferred to a later sub-phase.
| Kuenzel et al. (2019) | This addendum (gdpar) |
|---|---|
| Base learner \(M_t\) | fit_treat and fit_ctrl (a
pair of gdpar_fit objects) |
| T-learner construction \(\widehat\tau_T(x) = M_1(x) - M_0(x)\) | gdpar_causal_bridge(fit_treat, fit_ctrl, newdata) |
| Plug-in CATE estimate | bridge$cate_mean |
| Bootstrap or asymptotic CI for CATE | Posterior credible bounds bridge$cate_ci
(per-observation), summary(bridge)$ate_ci (marginal
ATE) |
| Cross-arm imputation (X-learner) | n/a in 8.5.A; queued as (O4-CATE) |
| Propensity-score model | n/a in 8.5.A; queued as (O5-CATE) for DR/DML |
| Treatment indicator \(W_i\) (in their Section 2) | Determined extensionally by membership in
fit_treat$data or fit_ctrl$data; the bridge
does not see a treatment indicator |
The correspondence is structural, not numerical: the per-arm point estimates of \(M_t(x)\) depend on the base learner used (Kuenzel et al. use random forests; this addendum uses AMM via gdpar); when the base learners coincide the two formulations agree on the CATE.
The bridge is decoupled from any external meta-learner. The principal integration points for Sub-phase 8.5.B will be:
A common evaluation grid. External meta-learners
consume the same newdata data frame as
gdpar_causal_bridge and return a per-observation CATE
estimate (typically a vector of length \(n_{\text{new}}\) with optional CIs). The
8.5.B comparator wraps each meta-learner in an adapter that returns a
list with cate_mean, cate_ci, and a
method tag.
No assumption on the comparator’s posterior.
Most external meta-learners do not produce a posterior; their CIs are
obtained by bootstrap or by asymptotic approximation. The 8.5.B
comparator does not equate cate_ci across methods of
different inferential origin; the comparator reports the discrepancy in
cate_mean and in cate_ci separately, leaving
the interpretation to the user.
No Python dependency in 8.5.A. The optional
EconML integration requires reticulate and a working Python
environment with EconML installed. The dependency is isolated in
Sub-phase 8.5.B’s Suggests block and does not contaminate
the core package Depends / Imports.
End of Theoretical Addendum – Block 8.5.A.