CounterfactualEvaluator#
- class pymc_marketing.mmm.counterfactual.CounterfactualEvaluator(*, pymc_model, posterior, response_vars, frozen_deterministics, dates, intervention_target='channel_data', intervention_mode='replace', expected_aux_values=None)[source]#
Compiled batched evaluator for the nodes a counterfactual intervention reaches.
Applies the intervention with
pymc.do(), conditions the intervened model’s graph on posterior draws, swaps every date-indexedpm.Datathe evaluation needs for a batched input, and compiles one function returning all requested nodes. Extracting the nodes together matters:channel_contributionand a mediated effect read the same spend data through the same adstock, and a single extraction keeps that subgraph shared instead of computing it once per node.The intervention is a single
(target, mode)pair for now. The direct-effect estimand – holding a mediator at its factual value while spend moves – needs simultaneous interventions and will generalize this to a mapping; the pair is threaded through the private helpers as one unit so that change stays local.The batched inputs are what make a window evaluation possible. Every date-indexed input in the graph has to be cut to the same window in lockstep, or the graph is handed a
max_window-long spend array and ann_dates-long mediator array. This class discovers those inputs from the graph and cuts them itself.Every result is transposed to
(sample, date, *non_date_dims)before it is returned. A node’s own axis order is whatever the operations that built it happened to produce – a panel model’s linear predictor comes out(country, date)while itschannel_contributioncomes out(date, country, channel)– and callers that add those two together cannot each rediscover that.- Parameters:
- pymc_model
pm.Model The fitted model whose graph is evaluated.
- posterior
xr.Dataset Posterior samples (already subsampled). Draws are flattened into a single
sampleaxis in chain-major order.- response_varssequence of
strorVariable Nodes to evaluate, in the order the results are keyed by. A node is accepted directly for a quantity the model does not register, such as the linear predictor under an identity link.
- frozen_deterministics
listofstr Deterministics to hold at their posterior values instead of recomputing.
- dates
pd.DatetimeIndex Dates of the fitted data, used to validate the discovered inputs.
- intervention_target
str, default"channel_data" Name of the model variable the counterfactual intervenes on: a data variable or a deterministic carrying a leading
datedimension. Random variables are refused – observed ones because intervening would silently delete the likelihood, free ones because a parameter is conditioned on, not intervened on.- intervention_mode
InterventionMode, default"replace" How the intervention grafts onto the target; see
InterventionMode. Under"scale", asking for the target itself as a response variable returns the intervened value, symmetric with"replace"where the evaluator’s input is that value.- expected_aux_values
mappingofstrtoxr.DataArray, optional Fit-time values of date-indexed inputs, keyed by variable name – typically
idata.constant_data. Every auxiliary input discovered in the graph whose name appears here has its live value, read off the model’s own shared variable, checked against the stored one instead of trusted outright. A mismatch means the model was mutated after fitting – byMMM.sample_posterior_predictive(..., clone_model=False)or a directpm.set_datacall – and is refused rather than silently evaluated on a hybrid of fitted and mutated state. A name absent from the mapping falls back to the live snapshot, unchecked, which keeps this optional: an evaluator built without fit-time values behaves as before.time_indexis checked the same way when present, but against the fabricatednp.arange(n_dates)rather than a live value, since the evaluator never reads a livetime_index.
- pymc_model
- Attributes:
- non_date_dims
dict Per response variable, the dimensions of its result after
sampleanddate, which is the node’s own dimension order withdateremoved.windowed_data_varstupleofstrNames of the auxiliary date-indexed inputs discovered in the graph.
- target_dtype
dtype Dtype the intervention values are cast to;
channel_dtypeis its alias for the default spend target.
- non_date_dims
- Raises:
ValueErrorIf the intervention target does not exist, is a random variable, is frozen, is not of a floating dtype, or lacks a leading
datedimension; if no response variable depends on the target; if a discovered date-indexed input does not span the fitted date axis; if a response variable has no name (an anonymous node such as a raw arithmetic expression, unless.namewas set on it); if two response variables share a name; or if a value in expected_aux_values – an auxiliary input, or the fabricatedtime_index– disagrees with what the live model or the fabrication would produce, meaning the model was mutated after fitting.
Methods
CounterfactualEvaluator.__init__(*, ...[, ...])Evaluate every node on one set of intervention values, over the full date axis.
Evaluate every node on all counterfactual scenarios.
Attributes
BATCH_DIMDimension the scenario axis is carried on through the vectorized graph.
CHANNEL_DATAMAX_BATCH_ELEMENTSOutput elements one evaluation may produce before it is split in two.
TIME_INDEXchannel_dtypeAlias of
target_dtypeunder the default spend target.windowed_data_varsNames of the auxiliary date-indexed inputs discovered in the graph.