google-meridian 1.0.9__py3-none-any.whl → 1.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -68,147 +68,6 @@ class PriorDistributionSampler:
68
68
  def __init__(self, meridian: "model.Meridian"):
69
69
  self._meridian = meridian
70
70
 
71
- def get_roi_prior_beta_m_value(
72
- self,
73
- alpha_m: tf.Tensor,
74
- beta_gm_dev: tf.Tensor,
75
- ec_m: tf.Tensor,
76
- eta_m: tf.Tensor,
77
- roi_or_mroi_m: tf.Tensor,
78
- slope_m: tf.Tensor,
79
- media_transformed: tf.Tensor,
80
- ) -> tf.Tensor:
81
- """Returns a tensor to be used in `beta_m`."""
82
- mmm = self._meridian
83
-
84
- # The `roi_or_mroi_m` parameter represents either ROI or mROI. For reach &
85
- # frequency channels, marginal ROI priors are defined as "mROI by reach",
86
- # which is equivalent to ROI.
87
- media_spend = mmm.media_tensors.media_spend
88
- media_spend_counterfactual = mmm.media_tensors.media_spend_counterfactual
89
- media_counterfactual_scaled = mmm.media_tensors.media_counterfactual_scaled
90
- # If we got here, then we should already have media tensors derived from
91
- # non-None InputData.media data.
92
- assert media_spend is not None
93
- assert media_spend_counterfactual is not None
94
- assert media_counterfactual_scaled is not None
95
-
96
- # Use absolute value here because this difference will be negative for
97
- # marginal ROI priors.
98
- inc_revenue_m = roi_or_mroi_m * tf.reduce_sum(
99
- tf.abs(media_spend - media_spend_counterfactual),
100
- range(media_spend.ndim - 1),
101
- )
102
-
103
- if (
104
- mmm.model_spec.roi_calibration_period is None
105
- and mmm.model_spec.paid_media_prior_type
106
- == constants.PAID_MEDIA_PRIOR_TYPE_ROI
107
- ):
108
- # We can skip the adstock/hill computation step in this case.
109
- media_counterfactual_transformed = tf.zeros_like(media_transformed)
110
- else:
111
- media_counterfactual_transformed = mmm.adstock_hill_media(
112
- media=media_counterfactual_scaled,
113
- alpha=alpha_m,
114
- ec=ec_m,
115
- slope=slope_m,
116
- )
117
-
118
- revenue_per_kpi = mmm.revenue_per_kpi
119
- if mmm.input_data.revenue_per_kpi is None:
120
- revenue_per_kpi = tf.ones([mmm.n_geos, mmm.n_times], dtype=tf.float32)
121
- # Note: use absolute value here because this difference will be negative for
122
- # marginal ROI priors.
123
- media_contrib_gm = tf.einsum(
124
- "...gtm,g,,gt->...gm",
125
- tf.abs(media_transformed - media_counterfactual_transformed),
126
- mmm.population,
127
- mmm.kpi_transformer.population_scaled_stdev,
128
- revenue_per_kpi,
129
- )
130
-
131
- if mmm.media_effects_dist == constants.MEDIA_EFFECTS_NORMAL:
132
- media_contrib_m = tf.einsum("...gm->...m", media_contrib_gm)
133
- random_effect_m = tf.einsum(
134
- "...m,...gm,...gm->...m", eta_m, beta_gm_dev, media_contrib_gm
135
- )
136
- return (inc_revenue_m - random_effect_m) / media_contrib_m
137
- else:
138
- # For log_normal, beta_m and eta_m are not mean & std.
139
- # The parameterization is beta_gm ~ exp(beta_m + eta_m * N(0, 1)).
140
- random_effect_m = tf.einsum(
141
- "...gm,...gm->...m",
142
- tf.math.exp(beta_gm_dev * eta_m[..., tf.newaxis, :]),
143
- media_contrib_gm,
144
- )
145
- return tf.math.log(inc_revenue_m) - tf.math.log(random_effect_m)
146
-
147
- def get_roi_prior_beta_rf_value(
148
- self,
149
- alpha_rf: tf.Tensor,
150
- beta_grf_dev: tf.Tensor,
151
- ec_rf: tf.Tensor,
152
- eta_rf: tf.Tensor,
153
- roi_or_mroi_rf: tf.Tensor,
154
- slope_rf: tf.Tensor,
155
- rf_transformed: tf.Tensor,
156
- ) -> tf.Tensor:
157
- """Returns a tensor to be used in `beta_rf`."""
158
- mmm = self._meridian
159
-
160
- rf_spend = mmm.rf_tensors.rf_spend
161
- rf_spend_counterfactual = mmm.rf_tensors.rf_spend_counterfactual
162
- reach_counterfactual_scaled = mmm.rf_tensors.reach_counterfactual_scaled
163
- frequency = mmm.rf_tensors.frequency
164
- # If we got here, then we should already have RF media tensors derived from
165
- # non-None InputData.reach data.
166
- assert rf_spend is not None
167
- assert rf_spend_counterfactual is not None
168
- assert reach_counterfactual_scaled is not None
169
- assert frequency is not None
170
-
171
- inc_revenue_rf = roi_or_mroi_rf * tf.reduce_sum(
172
- rf_spend - rf_spend_counterfactual,
173
- range(rf_spend.ndim - 1),
174
- )
175
- if mmm.model_spec.rf_roi_calibration_period is not None:
176
- rf_counterfactual_transformed = mmm.adstock_hill_rf(
177
- reach=reach_counterfactual_scaled,
178
- frequency=frequency,
179
- alpha=alpha_rf,
180
- ec=ec_rf,
181
- slope=slope_rf,
182
- )
183
- else:
184
- rf_counterfactual_transformed = tf.zeros_like(rf_transformed)
185
- revenue_per_kpi = mmm.revenue_per_kpi
186
- if mmm.input_data.revenue_per_kpi is None:
187
- revenue_per_kpi = tf.ones([mmm.n_geos, mmm.n_times], dtype=tf.float32)
188
-
189
- media_contrib_grf = tf.einsum(
190
- "...gtm,g,,gt->...gm",
191
- rf_transformed - rf_counterfactual_transformed,
192
- mmm.population,
193
- mmm.kpi_transformer.population_scaled_stdev,
194
- revenue_per_kpi,
195
- )
196
- if mmm.media_effects_dist == constants.MEDIA_EFFECTS_NORMAL:
197
- media_contrib_rf = tf.einsum("...gm->...m", media_contrib_grf)
198
- random_effect_rf = tf.einsum(
199
- "...m,...gm,...gm->...m", eta_rf, beta_grf_dev, media_contrib_grf
200
- )
201
- return (inc_revenue_rf - random_effect_rf) / media_contrib_rf
202
- else:
203
- # For log_normal, beta_rf and eta_rf are not mean & std.
204
- # The parameterization is beta_grf ~ exp(beta_rf + eta_rf * N(0, 1)).
205
- random_effect_rf = tf.einsum(
206
- "...gm,...gm->...m",
207
- tf.math.exp(beta_grf_dev * eta_rf[..., tf.newaxis, :]),
208
- media_contrib_grf,
209
- )
210
- return tf.math.log(inc_revenue_rf) - tf.math.log(random_effect_rf)
211
-
212
71
  def _sample_media_priors(
213
72
  self,
214
73
  n_draws: int,
@@ -243,40 +102,49 @@ class PriorDistributionSampler:
243
102
  [mmm.n_geos, mmm.n_media_channels],
244
103
  name=constants.BETA_GM_DEV,
245
104
  ).sample(**sample_kwargs)
246
- media_transformed = mmm.adstock_hill_media(
247
- media=mmm.media_tensors.media_scaled,
248
- alpha=media_vars[constants.ALPHA_M],
249
- ec=media_vars[constants.EC_M],
250
- slope=media_vars[constants.SLOPE_M],
251
- )
252
105
 
253
- prior_type = mmm.model_spec.paid_media_prior_type
254
- if prior_type == constants.PAID_MEDIA_PRIOR_TYPE_ROI:
255
- roi_m = prior.roi_m.sample(**sample_kwargs)
256
- beta_m_value = self.get_roi_prior_beta_m_value(
257
- beta_gm_dev=beta_gm_dev,
258
- media_transformed=media_transformed,
259
- roi_or_mroi_m=roi_m,
260
- **media_vars,
106
+ prior_type = mmm.model_spec.effective_media_prior_type
107
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_COEFFICIENT:
108
+ media_vars[constants.BETA_M] = prior.beta_m.sample(**sample_kwargs)
109
+ else:
110
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_ROI:
111
+ treatment_parameter_m = prior.roi_m.sample(**sample_kwargs)
112
+ media_vars[constants.ROI_M] = treatment_parameter_m
113
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_MROI:
114
+ treatment_parameter_m = prior.mroi_m.sample(**sample_kwargs)
115
+ media_vars[constants.MROI_M] = treatment_parameter_m
116
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_CONTRIBUTION:
117
+ treatment_parameter_m = prior.contribution_m.sample(**sample_kwargs)
118
+ media_vars[constants.CONTRIBUTION_M] = treatment_parameter_m
119
+ else:
120
+ raise ValueError(f"Unsupported prior type: {prior_type}")
121
+ incremental_outcome_m = (
122
+ treatment_parameter_m * mmm.media_tensors.prior_denominator
261
123
  )
262
- media_vars[constants.ROI_M] = roi_m
263
- media_vars[constants.BETA_M] = tfp.distributions.Deterministic(
264
- beta_m_value, name=constants.BETA_M
265
- ).sample()
266
- elif prior_type == constants.PAID_MEDIA_PRIOR_TYPE_MROI:
267
- mroi_m = prior.mroi_m.sample(**sample_kwargs)
268
- beta_m_value = self.get_roi_prior_beta_m_value(
269
- beta_gm_dev=beta_gm_dev,
270
- media_transformed=media_transformed,
271
- roi_or_mroi_m=mroi_m,
272
- **media_vars,
124
+ media_transformed = mmm.adstock_hill_media(
125
+ media=mmm.media_tensors.media_scaled,
126
+ alpha=media_vars[constants.ALPHA_M],
127
+ ec=media_vars[constants.EC_M],
128
+ slope=media_vars[constants.SLOPE_M],
129
+ )
130
+ linear_predictor_counterfactual_difference = (
131
+ mmm.linear_predictor_counterfactual_difference_media(
132
+ media_transformed=media_transformed,
133
+ alpha_m=media_vars[constants.ALPHA_M],
134
+ ec_m=media_vars[constants.EC_M],
135
+ slope_m=media_vars[constants.SLOPE_M],
136
+ )
137
+ )
138
+ beta_m_value = mmm.calculate_beta_x(
139
+ is_non_media=False,
140
+ incremental_outcome_x=incremental_outcome_m,
141
+ linear_predictor_counterfactual_difference=linear_predictor_counterfactual_difference,
142
+ eta_x=media_vars[constants.ETA_M],
143
+ beta_gx_dev=beta_gm_dev,
273
144
  )
274
- media_vars[constants.MROI_M] = mroi_m
275
145
  media_vars[constants.BETA_M] = tfp.distributions.Deterministic(
276
146
  beta_m_value, name=constants.BETA_M
277
147
  ).sample()
278
- else:
279
- media_vars[constants.BETA_M] = prior.beta_m.sample(**sample_kwargs)
280
148
 
281
149
  beta_eta_combined = (
282
150
  media_vars[constants.BETA_M][..., tf.newaxis, :]
@@ -326,43 +194,51 @@ class PriorDistributionSampler:
326
194
  [mmm.n_geos, mmm.n_rf_channels],
327
195
  name=constants.BETA_GRF_DEV,
328
196
  ).sample(**sample_kwargs)
329
- rf_transformed = mmm.adstock_hill_rf(
330
- reach=mmm.rf_tensors.reach_scaled,
331
- frequency=mmm.rf_tensors.frequency,
332
- alpha=rf_vars[constants.ALPHA_RF],
333
- ec=rf_vars[constants.EC_RF],
334
- slope=rf_vars[constants.SLOPE_RF],
335
- )
336
197
 
337
- prior_type = mmm.model_spec.paid_media_prior_type
338
- if prior_type == constants.PAID_MEDIA_PRIOR_TYPE_ROI:
339
- roi_rf = prior.roi_rf.sample(**sample_kwargs)
340
- beta_rf_value = self.get_roi_prior_beta_rf_value(
341
- beta_grf_dev=beta_grf_dev,
342
- rf_transformed=rf_transformed,
343
- roi_or_mroi_rf=roi_rf,
344
- **rf_vars,
198
+ prior_type = mmm.model_spec.effective_rf_prior_type
199
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_COEFFICIENT:
200
+ rf_vars[constants.BETA_RF] = prior.beta_rf.sample(**sample_kwargs)
201
+ else:
202
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_ROI:
203
+ treatment_parameter_rf = prior.roi_rf.sample(**sample_kwargs)
204
+ rf_vars[constants.ROI_RF] = treatment_parameter_rf
205
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_MROI:
206
+ treatment_parameter_rf = prior.mroi_rf.sample(**sample_kwargs)
207
+ rf_vars[constants.MROI_RF] = treatment_parameter_rf
208
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_CONTRIBUTION:
209
+ treatment_parameter_rf = prior.contribution_rf.sample(**sample_kwargs)
210
+ rf_vars[constants.CONTRIBUTION_RF] = treatment_parameter_rf
211
+ else:
212
+ raise ValueError(f"Unsupported prior type: {prior_type}")
213
+ incremental_outcome_rf = (
214
+ treatment_parameter_rf * mmm.rf_tensors.prior_denominator
345
215
  )
346
- rf_vars[constants.ROI_RF] = roi_rf
347
- rf_vars[constants.BETA_RF] = tfp.distributions.Deterministic(
348
- beta_rf_value,
349
- name=constants.BETA_RF,
350
- ).sample()
351
- elif prior_type == constants.PAID_MEDIA_PRIOR_TYPE_MROI:
352
- mroi_rf = prior.mroi_rf.sample(**sample_kwargs)
353
- beta_rf_value = self.get_roi_prior_beta_rf_value(
354
- beta_grf_dev=beta_grf_dev,
355
- rf_transformed=rf_transformed,
356
- roi_or_mroi_rf=mroi_rf,
357
- **rf_vars,
216
+ rf_transformed = mmm.adstock_hill_rf(
217
+ reach=mmm.rf_tensors.reach_scaled,
218
+ frequency=mmm.rf_tensors.frequency,
219
+ alpha=rf_vars[constants.ALPHA_RF],
220
+ ec=rf_vars[constants.EC_RF],
221
+ slope=rf_vars[constants.SLOPE_RF],
222
+ )
223
+ linear_predictor_counterfactual_difference = (
224
+ mmm.linear_predictor_counterfactual_difference_rf(
225
+ rf_transformed=rf_transformed,
226
+ alpha_rf=rf_vars[constants.ALPHA_RF],
227
+ ec_rf=rf_vars[constants.EC_RF],
228
+ slope_rf=rf_vars[constants.SLOPE_RF],
229
+ )
230
+ )
231
+ beta_rf_value = mmm.calculate_beta_x(
232
+ is_non_media=False,
233
+ incremental_outcome_x=incremental_outcome_rf,
234
+ linear_predictor_counterfactual_difference=linear_predictor_counterfactual_difference,
235
+ eta_x=rf_vars[constants.ETA_RF],
236
+ beta_gx_dev=beta_grf_dev,
358
237
  )
359
- rf_vars[constants.MROI_RF] = mroi_rf
360
238
  rf_vars[constants.BETA_RF] = tfp.distributions.Deterministic(
361
239
  beta_rf_value,
362
240
  name=constants.BETA_RF,
363
241
  ).sample()
364
- else:
365
- rf_vars[constants.BETA_RF] = prior.beta_rf.sample(**sample_kwargs)
366
242
 
367
243
  beta_eta_combined = (
368
244
  rf_vars[constants.BETA_RF][..., tf.newaxis, :]
@@ -414,9 +290,37 @@ class PriorDistributionSampler:
414
290
  name=constants.BETA_GOM_DEV,
415
291
  ).sample(**sample_kwargs)
416
292
 
417
- organic_media_vars[constants.BETA_OM] = prior.beta_om.sample(
418
- **sample_kwargs
419
- )
293
+ prior_type = mmm.model_spec.organic_media_prior_type
294
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_COEFFICIENT:
295
+ organic_media_vars[constants.BETA_OM] = prior.beta_om.sample(
296
+ **sample_kwargs
297
+ )
298
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_CONTRIBUTION:
299
+ organic_media_vars[constants.CONTRIBUTION_OM] = (
300
+ prior.contribution_om.sample(**sample_kwargs)
301
+ )
302
+ incremental_outcome_om = (
303
+ organic_media_vars[constants.CONTRIBUTION_OM] * mmm.total_outcome
304
+ )
305
+ organic_media_transformed = mmm.adstock_hill_media(
306
+ media=mmm.organic_media_tensors.organic_media_scaled,
307
+ alpha=organic_media_vars[constants.ALPHA_OM],
308
+ ec=organic_media_vars[constants.EC_OM],
309
+ slope=organic_media_vars[constants.SLOPE_OM],
310
+ )
311
+ beta_om_value = mmm.calculate_beta_x(
312
+ is_non_media=False,
313
+ incremental_outcome_x=incremental_outcome_om,
314
+ linear_predictor_counterfactual_difference=organic_media_transformed,
315
+ eta_x=organic_media_vars[constants.ETA_OM],
316
+ beta_gx_dev=beta_gom_dev,
317
+ )
318
+ organic_media_vars[constants.BETA_OM] = tfp.distributions.Deterministic(
319
+ beta_om_value,
320
+ name=constants.BETA_OM,
321
+ ).sample()
322
+ else:
323
+ raise ValueError(f"Unsupported prior type: {prior_type}")
420
324
 
421
325
  beta_eta_combined = (
422
326
  organic_media_vars[constants.BETA_OM][..., tf.newaxis, :]
@@ -469,7 +373,38 @@ class PriorDistributionSampler:
469
373
  name=constants.BETA_GORF_DEV,
470
374
  ).sample(**sample_kwargs)
471
375
 
472
- organic_rf_vars[constants.BETA_ORF] = prior.beta_orf.sample(**sample_kwargs)
376
+ prior_type = mmm.model_spec.organic_media_prior_type
377
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_COEFFICIENT:
378
+ organic_rf_vars[constants.BETA_ORF] = prior.beta_orf.sample(
379
+ **sample_kwargs
380
+ )
381
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_CONTRIBUTION:
382
+ organic_rf_vars[constants.CONTRIBUTION_ORF] = (
383
+ prior.contribution_orf.sample(**sample_kwargs)
384
+ )
385
+ incremental_outcome_orf = (
386
+ organic_rf_vars[constants.CONTRIBUTION_ORF] * mmm.total_outcome
387
+ )
388
+ organic_rf_transformed = mmm.adstock_hill_rf(
389
+ reach=mmm.organic_rf_tensors.organic_reach_scaled,
390
+ frequency=mmm.organic_rf_tensors.organic_frequency,
391
+ alpha=organic_rf_vars[constants.ALPHA_ORF],
392
+ ec=organic_rf_vars[constants.EC_ORF],
393
+ slope=organic_rf_vars[constants.SLOPE_ORF],
394
+ )
395
+ beta_orf_value = mmm.calculate_beta_x(
396
+ is_non_media=False,
397
+ incremental_outcome_x=incremental_outcome_orf,
398
+ linear_predictor_counterfactual_difference=organic_rf_transformed,
399
+ eta_x=organic_rf_vars[constants.ETA_ORF],
400
+ beta_gx_dev=beta_gorf_dev,
401
+ )
402
+ organic_rf_vars[constants.BETA_ORF] = tfp.distributions.Deterministic(
403
+ beta_orf_value,
404
+ name=constants.BETA_ORF,
405
+ ).sample()
406
+ else:
407
+ raise ValueError(f"Unsupported prior type: {prior_type}")
473
408
 
474
409
  beta_eta_combined = (
475
410
  organic_rf_vars[constants.BETA_ORF][..., tf.newaxis, :]
@@ -511,7 +446,6 @@ class PriorDistributionSampler:
511
446
  sample_shape = [1, n_draws]
512
447
  sample_kwargs = {constants.SAMPLE_SHAPE: sample_shape, constants.SEED: seed}
513
448
  non_media_treatments_vars = {
514
- constants.GAMMA_N: prior.gamma_n.sample(**sample_kwargs),
515
449
  constants.XI_N: prior.xi_n.sample(**sample_kwargs),
516
450
  }
517
451
  gamma_gn_dev = tfp.distributions.Sample(
@@ -519,6 +453,40 @@ class PriorDistributionSampler:
519
453
  [mmm.n_geos, mmm.n_non_media_channels],
520
454
  name=constants.GAMMA_GN_DEV,
521
455
  ).sample(**sample_kwargs)
456
+ prior_type = mmm.model_spec.non_media_treatments_prior_type
457
+ if prior_type == constants.TREATMENT_PRIOR_TYPE_COEFFICIENT:
458
+ non_media_treatments_vars[constants.GAMMA_N] = prior.gamma_n.sample(
459
+ **sample_kwargs
460
+ )
461
+ elif prior_type == constants.TREATMENT_PRIOR_TYPE_CONTRIBUTION:
462
+ non_media_treatments_vars[constants.CONTRIBUTION_N] = (
463
+ prior.contribution_n.sample(**sample_kwargs)
464
+ )
465
+ incremental_outcome_n = (
466
+ non_media_treatments_vars[constants.CONTRIBUTION_N]
467
+ * mmm.total_outcome
468
+ )
469
+ baseline_scaled = mmm.non_media_transformer.forward( # pytype: disable=attribute-error
470
+ mmm.compute_non_media_treatments_baseline()
471
+ )
472
+ linear_predictor_counterfactual_difference = (
473
+ mmm.non_media_treatments_normalized
474
+ - baseline_scaled
475
+ )
476
+ gamma_n_value = mmm.calculate_beta_x(
477
+ is_non_media=True,
478
+ incremental_outcome_x=incremental_outcome_n,
479
+ linear_predictor_counterfactual_difference=linear_predictor_counterfactual_difference,
480
+ eta_x=non_media_treatments_vars[constants.XI_N],
481
+ beta_gx_dev=gamma_gn_dev,
482
+ )
483
+ non_media_treatments_vars[constants.GAMMA_N] = (
484
+ tfp.distributions.Deterministic(
485
+ gamma_n_value, name=constants.GAMMA_N
486
+ ).sample()
487
+ )
488
+ else:
489
+ raise ValueError(f"Unsupported prior type: {prior_type}")
522
490
  non_media_treatments_vars[constants.GAMMA_GN] = (
523
491
  tfp.distributions.Deterministic(
524
492
  non_media_treatments_vars[constants.GAMMA_N][..., tf.newaxis, :]
@@ -552,10 +520,12 @@ class PriorDistributionSampler:
552
520
  constants.GAMMA_C: prior.gamma_c.sample(**sample_kwargs),
553
521
  constants.XI_C: prior.xi_c.sample(**sample_kwargs),
554
522
  constants.SIGMA: prior.sigma.sample(**sample_kwargs),
555
- constants.TAU_G: _get_tau_g(
556
- tau_g_excl_baseline=tau_g_excl_baseline,
557
- baseline_geo_idx=mmm.baseline_geo_idx,
558
- ).sample(),
523
+ constants.TAU_G: (
524
+ _get_tau_g(
525
+ tau_g_excl_baseline=tau_g_excl_baseline,
526
+ baseline_geo_idx=mmm.baseline_geo_idx,
527
+ ).sample()
528
+ ),
559
529
  }
560
530
  base_vars[constants.MU_T] = tfp.distributions.Deterministic(
561
531
  tf.einsum(
@@ -599,7 +569,7 @@ class PriorDistributionSampler:
599
569
  )
600
570
  non_media_treatments_vars = (
601
571
  self._sample_non_media_treatments_priors(n_draws, seed)
602
- if mmm.non_media_treatments_scaled is not None
572
+ if mmm.non_media_treatments_normalized is not None
603
573
  else {}
604
574
  )
605
575