[PyMC-Marketing] Saturation function and prior setting

  1. Logistic Saturation Function

PyMC-Marketing is using a Logistic Saturation function to apply diminishing returns to the channel variables. why use a logistic saturation function?

It seems that most libraries and articles discussing diminishing returns applied to MMM choose to use a Hill function

def hill_transform(x, ec, slope):
    return 1 / (1 + (x / ec)**(-slope))

or the more simple saturation, which gives an easier interpretation to the parameter being estimated.

def simple_saturation(x,inflection_point):
    return (1 - np.exp(-x / (inflection_point * max(x))))

I’d love to better understand this choice so i can better use it.


  1. Setting strict priors for saturation.

I wanted to set the diminishing returns of a specific channel variable to 3.

To achieve that, I applied [90000.0, 30000.0] as parameters for the priors of the Gamma distribution in that specific channel, instead of the [3,1] set in the default_model_config.

i expected this new prior distribution (which has a mean of 3 and variance of 0.0001) to return a value of 3 when looking at the prior sample means of that specific channel. However that is not what’s happening.

Am i misunderstanding how the prior setting for the diminishing returns work?

As a further example, if i want to set the saturation of x1 to 4 using the priors in the MMM example notebook, i’d expect the following model_config to give me that:

my_model_config={'intercept': {'mu': 0, 'sigma': 2},
 'beta_channel': {'sigma': 2, 'dims': ('channel',)},
 'alpha': {'alpha': 1, 'beta': 3, 'dims': ('channel',)},
 'lam': {'alpha': [160000,3], 'beta': [4000.0,1], 'dims': ('channel',)},
 'sigma': {'sigma': 2},
 'gamma_control': {'mu': 0, 'sigma': 2, 'dims': ('control',)},
 'mu': {'dims': ('date',)},
 'likelihood': {'dims': ('date',)},
 'gamma_fourier': {'mu': 0, 'b': 1, 'dims': 'fourier_mode'}}

Where [16000,4000] are the parameters of a Gamma Distribution with mean 4 and very low variance.

Howerver, this config returns a lam of 39.99 to x1.

az.extract(data=mmm.fit_result,
                     group="prior",
                     var_names='lam'
                     ).mean("sample")[0].values

>>> array(39.99204239)
  1. Channels with no diminishing return currently?

Setting prior for channels with no adstock is as simple as setting the priors to zero. However that doesn’t seem to be an option with the current Diminishing return function? what priors would better represent that?