TransferFunctionARRegression#
- class causalpy.pymc_models.TransferFunctionARRegression[source]#
Bayesian Transfer Function model with AR(1) errors for Graded Intervention Time Series.
This model extends the Transfer Function framework by explicitly modeling autocorrelation in the errors using an AR(1) process implemented via quasi-differencing. This approach properly accounts for temporal correlation in the residuals while jointly estimating transform parameters (adstock, saturation) and regression coefficients.
Mathematical Framework#
The standard regression model with AR(1) errors is:
\[y[t] = \mu[t] + \epsilon[t] \epsilon[t] = \rho \cdot \epsilon[t-1] + \nu[t] \nu[t] \sim N(0, \sigma_\nu^2)\]where \(\mu[t]\) is the regression mean (baseline + transformed treatment effects), \(\rho\) is the AR(1) coefficient (|ρ| < 1), and \(\nu[t]\) is white noise.
Quasi-Differencing Transformation#
To enable Bayesian inference, we apply quasi-differencing:
\[y[t] - \rho \cdot y[t-1] = \mu[t] - \rho \cdot \mu[t-1] + \nu[t]\]This transforms the model into one with independent errors \(\nu[t]\), which can be directly sampled in PyMC. The quasi-differenced likelihood is:
For t=0: \(y[0] \sim N(\mu[0], \sigma_\nu / \sqrt{1-\rho^2})\) (stationary initial condition)
For t>0: \(y[t] - \rho \cdot y[t-1] \sim N(\mu[t] - \rho \cdot \mu[t-1], \sigma_\nu)\)
Advantages Over Independent Errors#
Proper uncertainty quantification: Accounts for temporal correlation in credible intervals
More efficient inference: Correctly models the error structure
Better parameter recovery: Avoids bias from ignoring autocorrelation
Diagnostic information: The \(\rho\) parameter indicates strength of temporal dependence
When to Use#
Use this model when:
Time series data exhibits autocorrelation in residuals
Standard transfer function model shows diagnostic issues (e.g., correlated residuals)
You need proper uncertainty propagation with temporal dependence
Use the standard TransferFunctionLinearRegression when:
Residuals show minimal autocorrelation
Computational efficiency is critical (AR model is slower)
You want a simpler baseline model for comparison
- type saturation_type:
- param saturation_type:
Type of saturation transform. Options: “hill”, “logistic”, “michaelis_menten”, None. If None, no saturation is applied.
- type saturation_type:
str or None
- type adstock_config:
- param adstock_config:
Configuration for adstock transform. Required keys: - “half_life_prior”: dict with prior specification (e.g., {“dist”: “Gamma”, “alpha”: 4, “beta”: 2}) - “l_max”: int, maximum lag - “normalize”: bool, whether to normalize weights If None, no adstock is applied.
- type adstock_config:
dict or None
- type saturation_config:
- param saturation_config:
Configuration for saturation transform. Structure depends on saturation_type: - For “hill”: {“slope_prior”: {…}, “kappa_prior”: {…}} - For “logistic”: {“lam_prior”: {…}} - For “michaelis_menten”: {“alpha_prior”: {…}, “lam_prior”: {…}}
- type saturation_config:
dict or None
- type coef_constraint:
- param coef_constraint:
Constraint on treatment coefficients: “nonnegative” or “unconstrained”.
- type coef_constraint:
str, default=”unconstrained”
- type sample_kwargs:
- param sample_kwargs:
Additional kwargs passed to pm.sample().
- type sample_kwargs:
dict, optional
Notes
The AR(1) coefficient \(\rho\) has a Uniform(-0.99, 0.99) prior by default
The quasi-differencing approach ensures the model remains computationally tractable
Posterior predictive sampling requires forward simulation of the AR process
Convergence can be slower than the independent errors model; consider increasing tune/draws
Prior Customization:
Priors are managed using the
Priorclass frompymc_extrasand can be customized via thepriorsparameter:from pymc_extras.prior import Prior model = cp.pymc_models.TransferFunctionARRegression( saturation_type=None, adstock_config={...}, priors={ "beta": Prior( "Normal", mu=0, sigma=100, dims=["treated_units", "coeffs"] ), "rho": Prior( "Uniform", lower=-0.95, upper=0.95, dims=["treated_units"] ), }, )
By default, data-informed priors are set automatically via
priors_from_data():Baseline coefficients (
beta):Normal(0, 5 * std(y))Treatment coefficients (
theta_treatment):Normal(0, 2 * std(y))orHalfNormal(2 * std(y))Error std (
sigma):HalfNormal(2 * std(y))AR(1) coefficient (
rho):Uniform(-0.99, 0.99)
This adaptive approach ensures priors are reasonable regardless of data scale.
Examples
Basic usage:
import causalpy as cp model = cp.pymc_models.TransferFunctionARRegression( saturation_type=None, adstock_config={ "half_life_prior": {"dist": "Gamma", "alpha": 4, "beta": 2}, "l_max": 8, "normalize": True, }, sample_kwargs={"chains": 4, "draws": 2000, "tune": 1000}, ) result = cp.GradedInterventionTimeSeries( data=df, y_column="outcome", treatment_names=["treatment"], base_formula="1 + time + covariate", model=model, )
References
Methods
Initialize TransferFunctionARRegression model.
Register a dimension coordinate with the model.
Vectorized version of
Model.add_coord.Add a random graph variable to the named variables of the model.
Build the PyMC model with transforms and AR(1) errors using quasi-differencing.
TransferFunctionARRegression.calculate_cumulative_impact(impact)Calculate the causal impact as the difference between observed and predicted values.
Check that the logp is defined and finite at the starting point.
Compiled log probability density hessian function.
Compiled log probability density gradient function.
Compiles a PyTensor function.
Compiled log probability density function.
Clone the model.
Create a
TensorVariablethat will be used as the random variable's "value" in log-likelihood graphs.TransferFunctionARRegression.d2logp([vars, ...])Hessian of the models log-probability w.r.t.
TransferFunctionARRegression.debug([point, ...])Debug model function at point.
TransferFunctionARRegression.dlogp([vars, ...])Gradient of the models log-probability w.r.t.
Evaluate shapes of untransformed AND transformed free variables.
TransferFunctionARRegression.fit(X, y, ...)Fit the Transfer Function AR(1) model.
Compute the initial point of the model.
TransferFunctionARRegression.logp([vars, ...])Elemwise log-probability of the model.
Compile a PyTensor function that computes logp and gradient.
Create a TensorVariable for an observed random variable.
Check if name has prefix and adds if needed.
Check if name has prefix and deletes if needed.
Compute the log probability of point for all random variables in the model.
Predict data given input data X
Generate data-informed priors including AR(1) coefficient.
TransferFunctionARRegression.profile(outs, *)Compile and profile a PyTensor function which returns
outsand takes values of model vars as a dict as an argument.Register a data variable with the model.
Register an (un)observed random variable with the model.
Clone and replace random variables in graphs with their value variables.
Score the Bayesian \(R^2\) given inputs
Xand outputsy.TransferFunctionARRegression.set_data(name, ...)Change the values of a data variable in the model.
TransferFunctionARRegression.set_dim(name, ...)Update a mutable dimension.
Set an initial value (strategy) for a random variable.
Produce a graphviz Digraph from a PyMC model.
Attributes
basic_RVsList of random variables the model is defined in terms of.
continuous_value_varsAll the continuous value variables in the model.
coordsCoordinate values for model dimensions.
datalogpPyTensor scalar of log-probability of the observed variables and potential terms.
default_priorsdim_lengthsThe symbolic lengths of dimensions in the model.
discrete_value_varsAll the discrete value variables in the model.
isrootobservedlogpPyTensor scalar of log-probability of the observed variables.
parentpotentiallogpPyTensor scalar of log-probability of the Potential terms.
prefixrootunobserved_RVsList of all random variables, including deterministic ones.
unobserved_value_varsList of all random variables (including untransformed projections), as well as deterministics used as inputs and outputs of the model's log-likelihood graph.
value_varsList of unobserved random variables used as inputs to the model's log-likelihood (which excludes deterministics).
varlogpPyTensor scalar of log-probability of the unobserved random variables (excluding deterministic).
varlogp_nojacPyTensor scalar of log-probability of the unobserved random variables (excluding deterministic) without jacobian term.
- __init__(saturation_type=None, adstock_config=None, saturation_config=None, coef_constraint='unconstrained', sample_kwargs=None, priors=None)[source]#
Initialize TransferFunctionARRegression model.
- classmethod __new__(*args, **kwargs)#