metacausal.aggregation.QAggregation

class metacausal.aggregation.QAggregation(split=<factory>, propensity_model=None, outcome_model=None, propensity_trim=0.01, fit_nuisance_fn=None, nu=0.5, beta=0.0, prior=None, greedy=False, pseudo_outcome_fn=None)[source]

Bases: SupervisedStrategy

Doubly Robust Q-Aggregation (Lan & Syrgkanis, 2024).

Finds a convex combination of component CATEs by minimising a modified DR loss with an optional KL penalty on the simplex.

The modified loss interpolates between the ensemble loss (ν=0) and the weighted average of individual model losses (ν=1):

L̃_i(θ) = (1-ν)(Γ_i - θ·τ(x_i))² + ν Σ_k θ_k (Γ_i - τ_k(x_i))²

The full objective adds a cross-entropy regulariser:

L(θ) = (1/m) Σ_i L̃_i(θ) + (β/m) Σ_k θ_k log(1/π_k)

Note on β: With the default uniform prior, log(1/π_k) = log K is constant on the simplex and β has no effect on the optimisation. β only changes the solution when a non-uniform prior is supplied. Set β > 0 and pass a custom prior to encode domain knowledge about which models are likely better.

Parameters:
  • split (CrossFitSplit or TrainAvgSplit) – Data splitting strategy. Default: 5-fold cross-fitting.

  • propensity_model (sklearn classifier or None) – Model for P(T=1|X). None selects HistGradientBoostingClassifier.

  • outcome_model (sklearn regressor / classifier or None) – Model for E[Y|X, T]. For continuous Y, must be a regressor; for binary Y, must be a classifier (predict_proba). None selects an outcome-type-appropriate default (HistGradientBoostingRegressor or HistGradientBoostingClassifier).

  • propensity_trim (float) – Clip propensity scores to [trim, 1-trim].

  • fit_nuisance_fn (callable or None) – Optional replacement for the default nuisance fitting procedure. See SupervisedStrategy.fit_nuisance_fn for the required signature.

  • nu (float) – Interpolation parameter ν ∈ [0, 1]. Lan & Syrgkanis (2024) recommend ν = 0.5 (default). ν=0 gives the Causal Stacking objective.

  • beta (float) – KL penalty temperature. Default 0 (no penalty). Only effective when a non-uniform prior is supplied — see note above.

  • prior (array-like of shape (K,) or None) – Prior over the K component models. None (default) → uniform prior. Must be strictly positive; normalised internally.

  • greedy (bool) – If True, use the greedy approximation (Algorithm 1 in the paper): at most 2 nonzero weights via O(K) closed-form 1D line searches. Achieves the same theoretical guarantee as the full solver. Default False (full SLSQP solver).

  • pseudo_outcome_fn (callable or None) –

    Optional replacement for dr_pseudo_outcome. Must have signature:

    pseudo_outcome_fn(Y, T, nuisance) -> ndarray of shape (m,)
    

    Use this to inject targeted-learning influence functions or other semiparametric pseudo-outcome constructions. None (default) uses the standard AIPW form.

Examples

>>> from sklearn.linear_model import LinearRegression
>>> from sklearn.ensemble import HistGradientBoostingRegressor as HGBR
>>> from metacausal import CausalEnsemble
>>> from metacausal.adapters import GenericCATEAdapter
>>> from metacausal.aggregation import QAggregation
>>> from metacausal.datasets import load_lalonde
>>> X, T, Y = load_lalonde()
>>> def fit_linear(X, T, Y, **kwargs):
...     treated = T == 1
...     m1 = LinearRegression().fit(X[treated], Y[treated])
...     m0 = LinearRegression().fit(X[~treated], Y[~treated])
...     return (m1, m0)
>>> def fit_hgb(X, T, Y, **kwargs):
...     treated = T == 1
...     m1 = HGBR(max_iter=20).fit(X[treated], Y[treated])
...     m0 = HGBR(max_iter=20).fit(X[~treated], Y[~treated])
...     return (m1, m0)
>>> def cate_fn(state, X):
...     m1, m0 = state
...     return m1.predict(X) - m0.predict(X)
>>> methods = [
...     GenericCATEAdapter(fit_linear, cate_fn, name="linear"),
...     GenericCATEAdapter(fit_hgb, cate_fn, name="hgb"),
... ]
>>> ens = CausalEnsemble(methods=methods, aggregation=QAggregation())
>>> _ = ens.fit(X, T, Y, random_state=42)
>>> ens.ate()
AteEstimate(ate=..., n_methods=2, aggregation='QAggregation', spread=...)

Methods

__init__

aggregate

Aggregate component CATEs using stored weights.

fit_weights

Compute Q-aggregation weights from OOF predictions and nuisance estimates.

Attributes

beta

ensemble_weights

Ensemble weights computed during fit().

fit_nuisance_fn

greedy

nu

outcome_model

prior

propensity_model

propensity_trim

pseudo_outcome_fn

strategy_family

split

Details

fit_weights(cate_predictions, Y, T, X, nuisance)[source]

Compute Q-aggregation weights from OOF predictions and nuisance estimates.

Parameters:
  • cate_predictions (array of shape (K, m))

  • Y (arrays of shape (m,))

  • T (arrays of shape (m,))

  • X (array of shape (m, p))

  • nuisance (NuisanceEstimates)

Returns:

EnsembleWeights (model_names populated by _fit_supervised).

Return type:

EnsembleWeights

beta: float = 0.0
greedy: bool = False
nu: float = 0.5
prior: Any = None
pseudo_outcome_fn: Any = None