SpendProbe#

class pymc_marketing.mmm.spend_reach.SpendProbe(*, evaluator, baseline, baseline_array, counterfactual_spend_factor)[source]#

Single-date spend perturbations, and the two facts read off them.

A probe is an impulse: spend at one interior date is scaled, every other date left alone, and the whole graph re-evaluated on the untruncated axis. Comparing that against the baseline makes observable what the evaluation otherwise has to assume – how far forward a change in spend still moves each node, whether any node moves backwards in time, whether the nodes being evaluated account for the whole move in the linear predictor, and (on request, see mixes_channels()) whether one channel’s spend moves another channel’s contribution.

One probe suffices only if every channel spends at the probed date, because an effect is free to read a subset of channels. When no single date covers every spending channel, one probe per channel is taken instead – see _select_probe_indices() – and each fact is read off all of them.

Parameters:
evaluatorCounterfactualEvaluator

Compiled evaluator over the accounted nodes. Reused rather than recompiled: each probe is one more call to a function that already exists. Presumed to be a default-configuration evaluator – spend as the intervention target, in "replace" mode – since the probe’s perturbations are spend arrays.

baselinedict

Unperturbed evaluation on the full date axis, per node.

baseline_arraynp.ndarray

Actual spend, (n_dates, *extra_shape).

counterfactual_spend_factorfloat

The factor the caller will apply, so the measurement is taken where the analysis will be run. A factor of exactly 1.0 perturbs nothing, so the probe falls back to zeroing the date out.

Attributes:
probe_indiceslist of int

Indices of the perturbed dates, empty if no date could be perturbed – see _select_probe_indices().

probesdict

Per probed date, the evaluation of the perturbed spend.

Raises:
ValueError

If baseline or any probe evaluation contains a non-finite value (NaN or infinity) in any node. Checked eagerly, in __init__, because a non-finite cell otherwise reaches measure() or assert_increment_is_complete() and misfires their guards with an unrelated IndexError or a misleading NotImplementedError that blames unattributed spend for what is really a non-finite prediction.

Methods

SpendProbe.__init__(*, evaluator, baseline, ...)

SpendProbe.assert_increment_is_complete(*, ...)

Check the evaluated nodes account for the whole move in the predictor.

SpendProbe.measure(*, effects, l_max)

Measure how far in time a change in spend moves the evaluated nodes.

SpendProbe.mixes_channels(*, non_date_dims)

Measure whether one channel's spend moves another channel's column.

Attributes

COMPLETENESS_TOLERANCE

Relative slack allowed between the predictor's move and the accounted one.

REACH_TOLERANCE

Relative size below which a probed move counts as no move at all.