配置模型

您可以根据具体需求来自定义和配置 Meridian 基本模型设定,例如自定义投资回报率先验、根据季节性因素进行调整、设置延滞时长上限、使用覆盖面和频次等。如需详细了解 Meridian 基本模型和选项,请参阅 Meridian 模型部分。

默认模型设定

您可以使用以下默认模型设定开始创建自己的模型:

model_spec = spec.ModelSpec(
    prior=prior_distribution.PriorDistribution(),
    media_effects_dist='log_normal',
    hill_before_adstock=False,
    max_lag=8,
    unique_sigma_for_each_geo=False,
    media_prior_type='roi',
    roi_calibration_period=None,
    rf_prior_type='roi',
    rf_roi_calibration_period=None,
    organic_media_prior_type='contribution',
    organic_rf_prior_type='contribution',
    non_media_treatments_prior_type='contribution',
    knots=None,
    baseline_geo=None,
    holdout_id=None,
    control_population_scaling_id=None,
)

设置先验

您可以在默认模型设定中自定义先验。每个形参都具有自己的独立先验,可通过 Meridian ModelSpec 中的 prior 实参进行设置。如需了解先验和例外情况,请参阅默认先验分布

下例针对每个媒体渠道自定义了投资回报率先验分布。在此特定示例中,各个媒体渠道的投资回报率先验有所不同。

  • 渠道 1:LogNormal(0.2, 0.7)
  • 渠道 2:LogNormal(0.3, 0.9)
  • 渠道 3:LogNormal(0.4, 0.6)
  • 渠道 4:LogNormal(0.3, 0.7)
  • 渠道 5:LogNormal(0.3, 0.6)
  • 渠道 6:LogNormal(0.4, 0.5)
my_input_data = input_data.InputData( ... )
build_media_channel_args = my_input_data.get_paid_media_channels_argument_builder()

# Assuming Channel1,...,Channel6 are all media channels.
roi_m = build_media_channel_args(
  Channel1=(0.2, 0.7),
  Channel2=(0.3, 0.9),
  Channel3=(0.4, 0.6),
  Channel4=(0.3, 0.7),
  Channel5=(0.3, 0.6),
  Channel6=(0.4, 0.5),
) # This creates a list of channel-ordered (mu, sigma) tuples.
roi_m_mu, roi_m_sigma = zip(*roi_m)

prior = prior_distribution.PriorDistribution(
    roi_m=tfp.distributions.LogNormal(
        roi_m_mu, roi_m_sigma, name=constants.ROI_M
    )
)
model_spec = spec.ModelSpec(prior=prior)

其中,ModelSpec 中的 prior 是一个 PriorDistribution 对象,用于指定每组模型形参的先验分布。每个形参都具有自己的独立先验,可通过 prior_distribution.PriorDistribution() 构造函数进行设置。

带有 m 下标的模型形参(例如 roi_m)可以具有与媒体渠道数量相等的维数,也可以是一维的。如果维数与媒体渠道数量相等,则自定义先验中形参值的顺序与 data.media_channel 中形参值的顺序一致,表示为每个媒体渠道都设置了自定义先验。如果您无法为某些媒体渠道确定自定义先验,可考虑手动使用默认的 tfd.LogNormal(0.2, 0.9)。传递一维先验后,该单一维度将用于所有媒体渠道。

为带有 c 下标的模型形参(例如 gamma_c)设置先验的逻辑与为带有 m 下标的模型形参设置先验的逻辑相同。对于带有 c 下标的模型形参,维数可以与控制变量数量相等,也可以是一维的。如果维数与控制变量数量相等,则自定义先验中形参值的顺序与 data.control_variable 中形参值的顺序一致,表示为每个控制变量都设置了自定义先验。

下例使用单个数字为每个渠道设置了相同的投资回报率先验。在此特定示例中,两个媒体渠道的投资回报率先验完全相同,均表示为 LogNormal(0.2, 0.9)

roi_mu = 0.2
roi_sigma = 0.9
prior = prior_distribution.PriorDistribution(
    roi_m=tfp.distributions.LogNormal(roi_mu, roi_sigma, name=constants.ROI_M)
)
model_spec = spec.ModelSpec(prior=prior)

请务必注意,Meridian 针对具有覆盖面和频次数据的渠道提供了不同的投资回报率形参 (roi_rf) 和 beta 形参 (beta_rf)。因此,在特定渠道具有覆盖面和频次数据的情况下,需要对之前提到的代码段进行一些修改。在此示例中,渠道 4 和渠道 5 具有覆盖面和频次数据。

  • 如需为每个媒体渠道自定义投资回报率先验分布,请参考以下代码:

    # ROI prior for channels without R&F data
    build_media_channel_args = my_input_data.get_paid_media_channels_argument_builder()
    roi_m = build_media_channel_args(
      Channel1=(0.2, 0.7),
      Channel2=(0.3, 0.9),
      Channel3=(0.4, 0.6),
      Channel4=(0.3, 0.7),
    )
    roi_m_mu, roi_m_sigma = zip(*roi_m)
    
    # ROI prior for channels with R&F data
    build_rf_channel_args = my_input_data.get_paid_rf_channels_argument_builder()
    roi_rf = build_rf_channel_args(
      Channel5=(0.3, 0.6),
      Channel6=(0.4, 0.5),
    ]
    roi_rf_mu, roi_rf_sigma = zip(*roi_rf)
    
    prior = prior_distribution.PriorDistribution(
        roi_m=tfp.distributions.LogNormal(
            roi_m_mu, roi_m_sigma, name=constants.ROI_M
        ),
        roi_rf=tfp.distributions.LogNormal(
            roi_rf_mu, roi_rf_sigma, name=constants.ROI_RF
        ),
    )
    model_spec = spec.ModelSpec(prior=prior)
    

请注意,roi_rf_muroi_rf_sigma 中形参值的顺序必须与 data.rf_channel 中形参值的顺序一致。

  • 如需为所有媒体渠道设置相同的投资回报率先验,请参考以下代码:

    roi_mu = 0.2
    roi_sigma = 0.9
    prior = prior_distribution.PriorDistribution(
        roi_m=tfp.distributions.LogNormal(
            roi_mu, roi_sigma, name=constants.ROI_M),
        roi_rf=tfp.distributions.LogNormal(
            roi_mu, roi_sigma, name=constants.ROI_RF
        ),
    )
    model_spec = spec.ModelSpec(prior=prior)
    

拆分训练数据和测试数据(可选)

建议您拆分训练数据和测试数据,以帮助避免过拟合,并确保模型在新数据上有良好的泛化能力。这可以通过使用 holdout_id 来实现。这是一个可选步骤。

下例中的 holdout_id 实参会随机将 20% 的数据设置为测试组:

np.random.seed(1)
test_pct = 0.2  # 20% of data are held out
n_geos = len(data.geo)
n_times = len(data.time)
holdout_id = np.full([n_geos, n_times], False)
for i in range(n_geos):
  holdout_id[
    i,
    np.random.choice(
      n_times,
      int(np.round(test_pct * n_times)),
    )
  ] = True
model_spec = spec.ModelSpec(holdout_id=holdout_id)

其中,holdout_id 是一个可选的布尔值张量,维度可以是 (n_geos x n_times) 或 (n_times),用于指示将哪些观测数据排除在训练样本之外。只有响应变量会被排除在训练样本之外,媒体变量仍包含在内,因为它们可能会对未来几周的 Adstock 产生影响。默认值:None(表示无任何留出地理位置和时间)。

对自动化季节性调整进行调优(可选)

Meridian 采用时变截距方法来应用自动化季节性调整。您可以通过调整 knots 的值来调整效应。如需了解详情,请参阅 knots 实参的运作方式

knots 是一个可选的整数或整数列表,表示用于估计时间效应的结。如果 knots 是一个整数列表,则该列表提供的是结的位置,其中 0 表示第一个时间段的结,1 表示第二个时间段的结,依此类推,(n_times - 1) 表示最后一个时间段的结。

如果 knots 是一个整数,则表示有相应数量的结,这些结的位置在各个时间段中均匀分布,包括位于 0 和 (n_times - 1) 的结。如果 knots1,则表示所有时间段都使用一个通用的回归系数。

如果 knots 设置为 None,则所使用的结数与地理位置级模型中的时间段数一致。这相当于每个时间段都有自己的回归系数。对于国家级模型,如果 knots 设置为 None,则所使用的结数为 1。默认情况下,该值会设置为 None

如需了解如何为模型中的时间效应选择结数,请参阅为模型中的时间效应选择结数

示例

  • knots 设置为 1,这样系统便不会自动进行季节性调整。在这种情况下,建议您将自己的季节性虚拟变量或节假日虚拟变量添加为控制变量:

    model_spec = spec.ModelSpec(knots=1)
    
  • knots 设置为相对较大的数字:

    knots = round(0.8 * n_times)
    model_spec = spec.ModelSpec(knots=knots)
    
  • 以每 4 个时间点为单位设置 knots:

    knots = np.arange(0, n_times, 4).tolist()
    model_spec = spec.ModelSpec(knots=knots)
    
  • 设置 knots,使 11 月和 12 月各有一个结,但其他时间点的结相对较少。为了使此示例易于理解,假设只有 12 个数据点,并且数据是按月统计的(此假设不切实际,也不推荐使用)。下表对此示例进行了总结:

    按月设置 knots

  • 如需将 knots 设置在索引 0361011 处,请执行以下操作:

    knots = [0, 3, 6, 10, 11]
    model_spec = spec.ModelSpec(knots=knots)
    

您可以使用类似方法,帮助确保重大节假日期间有结。

对投资回报率校准进行调优(可选)

Meridian 引入了一种投资回报率校准方法,该方法将投资回报率重新参数化为一个模型形参。如需了解详情,请参阅用于校准的投资回报率先验

默认情况下,所有媒体渠道都会应用相同的非信息性投资回报率先验。您可以采取以下任一做法来对此功能进行调优:

  • 停用投资回报率校准
  • 设置投资回报率校准周期

停用投资回报率校准

您可以使用 media_prior_type='coefficient'rf_prior_type='coefficient' 来停用投资回报率校准功能:

model_spec = spec.ModelSpec(
    media_prior_type='coefficient',
    rf_prior_type='coefficient',
)

media_prior_type 实参用于指明要在 PriorDistribution 中使用 roi_mmroi_m 还是 beta_m 的先验。默认值:'roi'(推荐)

设置投资回报率校准周期

虽然媒体效应回归系数不会产生时变效应,但存在一个用于设置投资回报率(或边际投资回报率)先验的校准窗口实参。这是因为指定时间的投资回报率(或边际投资回报率)取决于可能会随时间而变化的其他因素:

  • Hill 曲线模拟了媒体执行的非线性递减回报。因此,在特定时间的媒体执行量可能会影响投资回报率。
  • 在具有不同效果的各个地理位置进行媒体分配。
  • 媒体执行费用。

如果实验结果无法反映 MMM 旨在衡量的纳入模型中的广告支出回报率 (ROAS),您可以使用一部分数据对 MMM 进行校准。例如,实验时间范围与 MMM 数据时间范围不一致。如需了解详情,请参阅使用贝叶斯先验进行媒体组合模型校准投资回报率先验和校准

下例展示了如何为渠道 1 指定投资回报率校准周期(从 '2021-11-01''2021-12-20')。未在 roi_period 中指定的所有媒体渠道都将利用所有可用周期进行投资回报率校准。

roi_period = {
  'Channel1': [
    '2021-11-01',
    '2021-11-08',
    '2021-11-15',
    '2021-11-22',
    '2021-11-29',
    '2021-12-06',
    '2021-12-13',
    '2021-12-20',
  ],
}

roi_calibration_period = np.zeros((len(data.time), len(data.media_channel)))
for i in roi_period.items():
  roi_calibration_period[
      np.isin(data.time.values, i[1]), data.media_channel.values == i[0]
  ] = 1

roi_calibration_period[
    :, ~np.isin(data.media_channel.values, list(roi_period.keys()))
] = 1

model_spec = spec.ModelSpec(roi_calibration_period=roi_calibration_period)

其中,roi_calibration_period 是一个可选的布尔值数组,格式为 (n_media_times, n_media_channels),可指明用于媒体投资回报率校准的 time 子集。如果设置为 None,则所有时间都将用于媒体投资回报率校准。默认值:None

请注意,Meridian 针对具有覆盖面和频次数据的渠道提供了不同的形参(即 rf_roi_calibration_period)。下例展示了如何为渠道 5 指定投资回报率校准周期(从 '2021-11-01''2021-12-20'),该渠道使用覆盖面和频次数据作为输入。

roi_period = {
  'Channel5': [
    '2021-11-01',
    '2021-11-08',
    '2021-11-15',
    '2021-11-22',
    '2021-11-29',
    '2021-12-06',
    '2021-12-13',
    '2021-12-20',
  ],
}

rf_roi_calibration_period = np.zeros(len(data.time), len(data.rf_channel))
for i in roi_period.items():
  rf_roi_calibration_period[
      np.isin(data.time.values, i[1]), data.rf_channel.values == i[0]
  ] = 1

rf_roi_calibration_period[
    :, ~np.isin(data.rf_channel.values, list(roi_period.keys()))
] = 1

model_spec = spec.ModelSpec(rf_roi_calibration_period=rf_roi_calibration_period)

其中 rf_roi_calibration_period 是一个可选的布尔值数组,格式为 (n_media_times, n_rf_channels)。如果设置为 None,则所有时间和地理位置都将用于媒体投资回报率校准。默认值:None

设置其他属性(可选)

您可以根据需要更改默认模型设定中的任何其余属性。本部分对其余属性进行了介绍,并举例说明了如何更改它们的值。

baseline_geo

一个可选的整数或字符串,表示基准地理位置。在对地理位置进行虚拟编码时,基准地理位置会被视为参考地理位置。非基准地理位置具有相应的 tau_g 指标变量,这意味着它们的先验方差高于基准地理位置。设置为 None 时,系统会将人口最多的地理位置用作基准。默认值:None

下例中的基准地理位置设置为 'Geo10'

model_spec = spec.ModelSpec(baseline_geo='Geo10')

hill_before_adstock

一个布尔值,用于指明是否在 Adstock 函数之前应用 Hill 函数,默认顺序与此相反,是在 Hill 函数之前应用 Adstock 函数。默认值:False

下例中的该属性值设置为 True,因此将先应用 Hill 函数:

model_spec = spec.ModelSpec(hill_before_adstock=True)

max_lag

一个整数,用于指示 Adstock 计算中包含的滞后期数上限 (>= 0)。也可以将该属性设置为 None,这相当于整个纳入模型中的周期。默认值:8

下例中该值更改为 4

model_spec = spec.ModelSpec(max_lag=4)

media_effects_dist

一个字符串,用于指定媒体随机效应在各个地理位置的分布情况。 允许使用的值有:'normal''log_normal'默认值:'log_normal'

其中:

  • media_effects_dist='log_normal' 为 \(\beta m,g\ {_\sim^{iid}} Lognormal(\beta m, \eta ^2m)\)

  • media_effects_dist='normal' 为 \(\beta m,g\ {_\sim^{iid}} Normal (\beta m, \eta ^2m)\)

下例展示了如何将值更改为 'normal'

model_spec = spec.ModelSpec(media_effects_dist='normal')

control_population_scaling_id

一个可选的布尔值张量,维度为 (n_controls),用于指明哪些控制变量的控制值将根据人口进行缩放。默认值:None

下例中指定,索引 1 处的控制变量将根据人口进行缩放:

control_population_scaling_id = np.full([n_controls], False)
control_population_scaling_id[1] = True
model_spec = spec.ModelSpec(
  control_population_scaling_id=control_population_scaling_id
)

unique_sigma_for_each_geo

一个布尔值,用于指明是否要针对每个地理位置使用唯一的残差方差。如果值为 False,则单个残差方差将用于所有地理位置。默认值:False

下例将模型设置为针对每个地理位置使用唯一的残差方差:

model_spec = spec.ModelSpec(unique_sigma_for_each_geo=True)