モデルを構成する

メリディアンのベースモデルの仕様は、ROI 事前分布のカスタマイズや、季節性の調整、最大繰り越し期間の設定、リーチとフリークエンシーの使用など、具体的なニーズに合わせてカスタマイズして構成できます。メリディアンのベースモデルとオプションの詳細については、メリディアン モデルをご確認ください。

デフォルトのモデル仕様

モデルの作成を開始する際は、次のデフォルトのモデル仕様を使用できます。

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,
)

事前分布を設定する

事前分布は、デフォルトのモデル仕様でカスタマイズできます。すべてのパラメータに、メリディアンの prior 引数で設定できる独立した事前分布が割り当てられます。事前分布と例外の詳細については、デフォルトの事前分布をご覧ください。

次の例では、各メディア チャネルの ROI 事前分布をカスタマイズしています。この例では、各メディア チャネルの ROI 事前分布が異なっています。

  • チャネル 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)

ここで、ModelSpecprior は、各モデル パラメータ セットの事前分布を指定する PriorDistribution オブジェクトです。すべてのパラメータに、prior_distribution.PriorDistribution() コンストラクタで設定できる独立した事前分布が割り当てられます。

添字 m を含むモデル パラメータ(roi_m など)は、次元をメディア チャネルの数と同一にするか、1 次元にすることができます。次元がメディア チャネルの数と同一の場合、カスタムの事前分布におけるパラメータ値の順序は data.media_channel の順序に対応し、各メディア チャネルに設定されたカスタムの事前分布を表します。カスタムの事前分布を特定できないメディア チャネルがある場合は、デフォルトの tfd.LogNormal(0.2, 0.9) を手動で使用することをおすすめします。1 次元の事前分布を渡すと、単一のディメンションがすべてのメディア チャネルで使用されます。

添字 c を含むモデル パラメータ(gamma_c など)の事前分布を設定する際のロジックは、添字 m の場合と同じです。添字 c の場合、次元は制御変数の数と同じか、1 次元にすることができます。次元が制御変数の数と同一の場合、カスタムの事前分布におけるパラメータ値の順序は data.control_variable の順序に対応し、各制御変数に設定されたカスタムの事前分布を表します。

次の例では、1 つの数値を使用して、各チャネルに同じ ROI 事前分布を設定しています。この例では、2 つのメディア チャネルの ROI 事前分布が同一であり、どちらも 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)

メリディアンには、リーチとフリークエンシーのデータを含むチャネル用に、ROI パラメータ(roi_rf)とベータ パラメータ(beta_rf)があることに注意してください。そのため、リーチとフリークエンシーのデータを含むチャネルがある場合は、前述のコード スニペットに変更を加える必要があります。この例では、チャネル 4 とチャネル 5 にリーチとフリークエンシーのデータがあります。

  • 各メディア チャネルの ROI 事前分布をカスタマイズする方法は次のとおりです。

    # 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 事前分布を設定する方法は次のとおりです。

    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 を使用します。この手順は任意です。

次の例は、データの 20% をランダムに抽出し、テストグループとして設定する holdout_id 引数を示しています。

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 × n_times または n_times)のブール値テンソルです(省略可)。応答変数のみがトレーニング サンプルから除外されます。メディア変数は、以降の週の Adstock に影響する可能性があるため除外されません。デフォルト: None(ホールドアウトの地域と時間がないことを意味します)

季節性の自動調整をチューニングする(省略可)

メリディアンでは、時変切片のアプローチにより、季節性の自動調整が適用されます。その効果は、knots の値を変更することでチューニングできます。詳細については、knots 引数の仕組みをご覧ください。

knots は、時間効果の推定に使用されるノットを示す整数または整数のリストで、省略可能です。knots が整数のリストの場合、ノットの位置はそのリストによって指定されます。0 は最初の期間のノット、1 は 2 番目の期間のノットに対応します。n_times - 1 は最後の期間のノットに対応します。

knots が整数の場合は、対応する数のノットが期間全体に等間隔で配置されます(0 のノットと n_times - 1 のノットを含む)。knots1 の場合、すべての期間で共通の回帰係数が 1 つ使用されます。

knotsNone に設定されている場合、使用されるノット数は、地域モデルにおける期間の数と同じです。これは、各期間に独自の回帰係数がある場合と同じです。国モデルで knotsNone に設定されている場合、使用されるノット数は 1 です。デフォルトでは、値は None に設定されます。

モデル内の時間効果のノット数を選択する方法については、モデル内の時間効果のノット数を選択するをご覧ください。

  • knots1 に設定して、季節性の自動調整が行われないようにします。この場合は、制御変数として独自の季節性またはホリデー シーズン用ダミーを含めることをおすすめします。

    model_spec = spec.ModelSpec(knots=1)
    
  • knots を比較的大きな数に設定します。

    knots = round(0.8 * n_times)
    model_spec = spec.ModelSpec(knots=knots)
    
  • 4 つの時間ポイントごとにノットを設定します。

    knots = np.arange(0, n_times, 4).tolist()
    model_spec = spec.ModelSpec(knots=knots)
    
  • 11 月と 12 月にノットを設定しますが、それ以外の期間は比較的まばらになるようにします。この例ではわかりやすくするため、データポイントは 12 個のみで、データは月単位であるとします(この前提は現実的ではなく、推奨されません)。この例を次の表にまとめます。

    月単位でノットを設定する

  • インデックス 0361011 にノットを設定する方法は次のとおりです。

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

同様の手法で、主要なホリデー シーズンにもノットを設定します。

ROI の調整をチューニングする(省略可)

メリディアンでは、ROI をモデル パラメータとして再パラメータ化する ROI の調整メソッドが導入されます。詳細については、調整対象の ROI 事前分布をご覧ください。

デフォルトでは、ROI に関する同じ無情報事前分布がすべてのメディア チャネルに適用されます。この機能は、次のいずれかの方法でチューニングできます。

  • ROI の調整をオフにする
  • ROI の調整期間を設定する

ROI の調整をオフにする

ROI の調整機能をオフにするには、media_prior_type='coefficient'rf_prior_type='coefficient' を使用します。

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

media_prior_type 引数は、PriorDistributionroi_mmroi_mbeta_m のいずれの事前分布を使用するかを示します。デフォルト: 'roi'(推奨)

ROI の調整期間を設定する

メディア効果の回帰係数には時間とともに変化する効果は含まれませんが、ROI(または mROI)事前分布を設定するための調整期間の引数があります。これは、特定の時点での ROI(または mROI)は、時間とともに変化する可能性がある他の要因に依存するためです。

  • Hill 曲線は、メディア施策の非線形の収穫逓減をモデル化したものです。そのため、特定の時点でのメディア施策の量が ROI に影響する可能性があります。
  • 有効性が異なる地域へのメディアの割り当て。
  • メディア施策の費用。

MMM による測定対象の広告費用対効果(ROAS)のモデリングがテスト結果に反映されていない場合は、データのサブセットを使用して MMM を調整できます。たとえば、テスト期間が MMM のデータの期間と一致していない場合です。詳しくは、ベイズ事前分布を使用したメディア ミックス モデルの調整ROI 事前分布と調整をご覧ください。

次の例は、チャネル 1 の ROI の調整期間を '2021-11-01' から '2021-12-20' に指定する方法を示しています。roi_period 内で指定されていないメディア チャネルは、利用可能なすべての期間で ROI の調整を行います。

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 は、メディアの ROI の調整に使用する time のサブセットを示す、形状 (n_media_times, n_media_channels) のブール値配列(省略可)です。None に設定した場合、すべての時間がメディアの費用対効果の調整に使用されます。デフォルト: None

メリディアンには、リーチとフリークエンシーのデータを含むチャネル用に、別のパラメータ(rf_roi_calibration_period)があります。次の例は、リーチとフリークエンシーのデータを入力として使用するチャネル 5 を対象に、ROI の調整期間を '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 に設定すると、すべての時間と地域がメディアの ROI の調整に使用されます。デフォルト: 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)