Sie können die Spezifikation des Meridian-Basismodells an Ihre spezifischen Bedürfnisse anpassen und entsprechend konfigurieren, z. B. indem Sie die ROI-Priors anpassen, saisonale Schwankungen berücksichtigen, die maximale Dauer für den Carryover-Effekt festlegen oder Daten zu Reichweite und Häufigkeit nutzen. Weitere Informationen zum Meridian-Basismodell und zu den Optionen finden Sie im Abschnitt Das Meridian-Modell.
Standardmodellspezifikation
Sie können die folgende Standardmodellspezifikation verwenden, um mit dem Erstellen Ihres Modells zu beginnen:
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,
)
Priors festlegen
Sie können die Priors in der Standardmodellspezifikation anpassen. Jeder Parameter erhält einen eigenen, unabhängigen Prior, der mit dem prior
-Argument in der ModelSpec
von Meridian festgelegt wird. Informationen zu den Priors und Ausnahmen finden Sie unter Standard-Prior-Verteilungen.
Im folgenden Beispiel werden die ROI-Prior-Verteilungen für jeden Media-Channel angepasst. In diesem Fall unterscheiden sich die ROI-Priors für die einzelnen Media-Channels.
- Channel 1:
LogNormal(0.2, 0.7)
- Channel 2:
LogNormal(0.3, 0.9)
- Channel 3:
LogNormal(0.4, 0.6)
- Channel 4:
LogNormal(0.3, 0.7)
- Channel 5:
LogNormal(0.3, 0.6)
- Channel 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)
Dabei ist prior
in ModelSpec
ein PriorDistribution
-Objekt, das die Prior-Verteilung für jede Gruppe von Modellparametern angibt. Für jeden Parameter wird ein eigener unabhängiger Prior mit dem prior_distribution.PriorDistribution()
-Konstruktor festgelegt.
Modellparameter mit einem m
nach dem Unterstrich (z. B. roi_m
) können entweder mehrdimensional (für jeden Media-Channel gibt es einen eigenen Wert) oder eindimensional sein.
Wenn die Dimensionalität der Anzahl der Media-Channels entspricht, stimmt die Reihenfolge der Parameterwerte in der benutzerdefinierten Prior-Verteilung mit der in data.media_channel
überein. Das bedeutet, dass für jeden Media-Channel eine benutzerdefinierte Prior-Verteilung festgelegt wird. Wenn Sie für einige der Media-Channels keine benutzerdefinierte Prior-Verteilung festlegen können, können Sie stattdessen die Standardverteilung tfd.LogNormal(0.2, 0.9)
verwenden. Wird ein eindimensionaler Prior übergeben, wird die einzelne Dimension für alle Media-Channels verwendet.
Die Logik zum Festlegen von Priors für Modellparameter mit einem c
nach dem Unterstrich (z. B. gamma_c
) ist dieselbe wie für das m
. Beim c
nach dem Unterstrich kann die Dimensionalität entweder der Anzahl der Kontrollvariablen entsprechen oder eindimensional sein. Wenn die Dimensionalität der Anzahl der Kontrollvariablen entspricht, stimmt die Reihenfolge der Parameterwerte in der benutzerdefinierten Prior-Verteilung mit der in data.control_variable
überein. Das bedeutet, dass für jede Kontrollvariable eine benutzerdefinierte Prior-Verteilung festgelegt wird.
Im folgenden Beispiel wird nur eine Zahl verwendet, um für jeden Channel denselben ROI-Prior festzulegen. In diesem Fall sind die ROI-Priors für die zwei Media-Channels identisch, wobei beide als LogNormal(0.2, 0.9)
dargestellt sind.
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)
Wichtig: Meridian verwendet einen separaten ROI-Parameter (roi_rf
) und einen separaten Beta-Parameter (beta_rf
) für die Channels mit Daten zu Reichweite und Häufigkeit. Für entsprechende Channels sind daher einige Änderungen an den zuvor genannten Code-Snippets erforderlich. In diesem Beispiel enthalten Channel 4 und Channel 5 Daten zu Reichweite und Häufigkeit.
So passen Sie die ROI-Prior-Verteilungen für die einzelnen Media-Channels an:
# 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)
Die Reihenfolge der Parameterwerte in roi_rf_mu
und roi_rf_sigma
muss mit data.rf_channel
übereinstimmen.
So legen Sie dieselben ROI-Priors für alle Media-Channels fest:
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)
Trainings- und Testdaten aufteilen (optional)
Wir empfehlen, Trainings- und Testdaten zu trennen, um Überanpassung zu vermeiden und sicherzustellen, dass das Modell gut mit neuen Daten generalisiert. Dazu kann holdout_id
verwendet werden. Dieser Schritt ist optional.
Im folgenden Beispiel wird ein holdout_id
-Argument verwendet, mit dem 20 % der Daten zufällig als Testgruppe festgelegt werden:
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)
Dabei ist holdout_id
ein optionaler boolescher Tensor mit den Dimensionen (n_geos
× n_times
) oder (n_times
), der angibt, welche Beobachtungen aus der Trainingsstichprobe ausgeschlossen werden. Nur die Antwortvariable wird aus der Trainingsstichprobe ausgeschlossen. Die Media-Variablen sind weiterhin enthalten, da sie sich auf den Adstock der Folgewochen auswirken können. Standard: None
(d. h. es gibt keine geografischen und zeitlichen Ausschlüsse)
Automatische saisonale Anpassung abstimmen (optional)
Meridian wendet eine automatische saisonale Anpassung durch einen zeitvariablen Schnittpunktansatz an. Die Auswirkungen können durch Anpassung des Werts von knots
optimiert werden.
Weitere Informationen finden Sie unter Funktionsweise des Arguments knots
.
knots
ist eine optionale Ganzzahl oder Liste mit Ganzzahlen, die die Knoten angibt, die zur Schätzung der Zeiteffekte verwendet werden. Wenn knots
eine Liste von Ganzzahlen ist, werden die Knotenpositionen durch diese Liste angegeben. Dabei entspricht „0“ einem Knoten im ersten Zeitraum, „1“ einem Knoten im zweiten Zeitraum usw., wobei (n_times - 1
) einem Knoten im letzten Zeitraum entspricht.
Ist knots
eine Ganzzahl, gibt es eine entsprechende Anzahl von Knoten, deren Positionen gleichmäßig über die Zeiträume hinweg verteilt sind, einschließlich Knoten bei null und (n_times - 1
). Wenn knots
gleich 1
ist, wird für alle Zeiträume ein gemeinsamer Regressionskoeffizient verwendet.
Wenn knots
auf None
festgelegt ist, entspricht die Anzahl der verwendeten Knoten bei einem geografischen Modell der Anzahl der Zeiträume. Das bedeutet, dass jeder Zeitraum einen eigenen Regressionskoeffizienten hat. Wenn knots
für nationale Modelle auf None
gesetzt ist, ist die Anzahl der Knoten 1
. Standardmäßig ist der Wert auf None
gesetzt.
Weitere Informationen finden Sie unter Anzahl der Knoten für Zeiteffekte im Modell auswählen.
Beispiele
Wenn Sie
knots
auf1
setzen, findet keine automatische saisonale Anpassung statt. In diesem Fall empfehlen wir, eigene Dummy-Variablen für saisonale Schwankungen oder Feiertage als Kontrollvariablen hinzuzufügen:model_spec = spec.ModelSpec(knots=1)
Wenn Sie
knots
auf eine relativ große Zahl festlegen:knots = round(0.8 * n_times) model_spec = spec.ModelSpec(knots=knots)
Knoten jeweils nach 4 Zeitpunkten setzen:
knots = np.arange(0, n_times, 4).tolist() model_spec = spec.ModelSpec(knots=knots)
Knoten so setzen, dass es im November und Dezember spezifische Knoten gibt, außerhalb dieser Monate aber relativ wenige Knoten gesetzt werden. Um dieses Beispiel nachvollziehbarer zu machen, nehmen wir an, dass es nur 12 Datenpunkte gibt und dass die Daten monatlich sind (diese Annahme ist nicht realistisch oder empfehlenswert). Dieses Beispiel ist in der folgenden Tabelle zusammengefasst:
So setzen Sie Knoten an den Indexen
0
,3
,6
,10
und11
:knots = [0, 3, 6, 10, 11] model_spec = spec.ModelSpec(knots=knots)
Sie können einen ähnlichen Ansatz nutzen, um Knoten für wichtige Feiertage zu setzen.
ROI-Abstimmung optimieren (optional)
Meridian führt eine Methode zur ROI-Abstimmung ein, mit der der ROI als Modellparameter neu parametrisiert wird. Weitere Informationen finden Sie unter ROI-Priors für die Abstimmung.
Standardmäßig wird für alle Media-Channels derselbe nicht informative Prior für den ROI verwendet. Sie haben folgende Möglichkeiten, diese Funktion anzupassen:
- ROI-Abstimmung deaktivieren
- Zeitraum für die ROI-Abstimmung festlegen
ROI-Abstimmung deaktivieren
Sie können die Funktion zur ROI-Abstimmung mit media_prior_type='coefficient'
und rf_prior_type='coefficient'
deaktivieren:
model_spec = spec.ModelSpec(
media_prior_type='coefficient',
rf_prior_type='coefficient',
)
Das Argument media_prior_type
gibt an, ob ein Prior für roi_m
, mroi_m
oder beta_m
in der PriorDistribution
verwendet werden soll. Standard: 'roi'
(empfohlen)
Zeitraum für ROI-Abstimmung festlegen
Obwohl die Regressionskoeffizienten des Media-Effekts keine zeitabhängigen Auswirkungen haben, spricht einiges dafür, ein Abstimmungsfenster für die Festlegung des ROI-Prior (oder Grenz-ROI-Prior) festzulegen. Das liegt daran, dass der ROI (oder Grenz-ROI) zu einem bestimmten Zeitpunkt von zusätzlichen Faktoren abhängt, die sich im Laufe der Zeit ändern können:
- Die Hill-Kurven modellieren die nicht linearen, sinkenden Renditen der Media-Ausführung. Daher kann die Anzahl der Media-Ausführungen zu einem bestimmten Zeitpunkt den ROI beeinflussen.
- Media-Verteilung über geografische Einheiten mit unterschiedlicher Effektivität.
- Kosten für die Media-Ausführung.
Sie können das MMM mit einer Teilmenge der Daten abstimmen, wenn die Testergebnisse nicht den modellierten ROAS (Return on Advertising Spend) widerspiegeln, den das MMM messen soll. Zum Beispiel wird der Zeitraum des Tests nicht mit dem Zeitraum der MMM-Daten abgestimmt. Weitere Informationen finden Sie unter Media-Mix-Modell mit bayesschen Priors abstimmen und ROI-Priors und ‑Abstimmung.
Im folgenden Beispiel sehen Sie, wie Sie den Zeitraum für die ROI-Abstimmung für Channel 1 vom
'2021-11-01'
bis zum '2021-12-20'
festlegen. Für alle Media-Channels, die nicht in roi_period
angegeben sind, werden alle verfügbaren Zeiträume für die ROI-Abstimmung verwendet.
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)
Dabei ist roi_calibration_period
ein optionales boolesches Array der Form (n_media_times, n_media_channels)
, das die Teilmenge time
für die ROI-Abstimmung von Media angibt. Wenn None
festgelegt ist, werden alle Zeiträume für die ROI-Abstimmung für Media verwendet.
Standard: None
.
In Meridian wird für Channels mit Daten zu Reichweite und Häufigkeit ein anderer Parameter verwendet:
rf_roi_calibration_period
.
Im folgenden Beispiel sehen Sie, wie Sie den Zeitraum für die ROI-Abstimmung für Channel 5 vom '2021-11-01'
bis zum '2021-12-20'
festlegen, wobei Reichweite und Häufigkeit als Eingaben verwendet werden.
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)
Dabei ist rf_roi_calibration_period
ein optionales boolesches Array der Form
(n_media_times, n_rf_channels)
. Wenn None
festgelegt ist, werden alle Zeiträume und geografischen Einheiten für die ROI-Abstimmung für Media verwendet.
Standard: None
.
Zusätzliche Attribute festlegen (optional)
Sie können alle verbleibenden Attribute in der Standardmodellspezifikation nach Bedarf ändern. In diesem Abschnitt werden die verbleibenden Attribute beschrieben und Beispiele dafür gegeben, wie die Werte geändert werden können.
baseline_geo
Optionale Ganzzahl oder String für die geografische Baseline. Die geografische Baseline wird bei der Dummy-Codierung von geografischen Einheiten als Referenz behandelt. Andere geografische Einheiten (nicht Baseline) haben eine entsprechende tau_g
-Indikatorvariable. Sie haben also eine höhere Prior-Varianz als die geografische Baseline. Ist None
festgelegt, wird die geografische Einheit mit der größten Bevölkerung als Baseline verwendet. Standard: None
.
Im folgenden Beispiel ist die geografische Baseline auf 'Geo10'
gesetzt:
model_spec = spec.ModelSpec(baseline_geo='Geo10')
hill_before_adstock
Ein boolescher Wert, der angibt, ob die Hill-Funktion vor der Adstock-Funktion angewendet werden soll, im Gegensatz zur Standardreihenfolge von Adstock vor Hill. Standard: False
.
In den folgenden Beispielen wird die Hill-Funktion zuerst angewendet. Dazu wird der Wert auf True
gesetzt:
model_spec = spec.ModelSpec(hill_before_adstock=True)
max_lag
Eine Ganzzahl, die die maximale Anzahl der Verzögerungszeiträume angibt, die in die Adstock-Berechnung einbezogen werden sollen (>= 0). Sie kann auch auf None
gesetzt werden, was dem gesamten Modellierungszeitraum entspricht. Standard: 8
.
Im folgenden Beispiel wird der Wert in 4
geändert:
model_spec = spec.ModelSpec(max_lag=4)
media_effects_dist
Ein String, mit dem die Verteilung der zufälligen Media-Effekte über verschiedene geografische Einheiten angegeben wird.
Zulässige Werte: 'normal'
oder 'log_normal'
. Standard: 'log_normal'
.
Dabei gilt:
media_effects_dist='log_normal'
ist \(\beta m,g\ {_\sim^{iid}} Lognormal(\beta m, \eta ^2m)\)media_effects_dist='normal'
ist \(\beta m,g\ {_\sim^{iid}} Normal (\beta m, \eta ^2m)\)
Im folgenden Beispiel sehen Sie, wie der Wert in 'normal'
geändert wird:
model_spec = spec.ModelSpec(media_effects_dist='normal')
control_population_scaling_id
Optionaler boolescher Tensor der Dimension (n_controls
), der die Kontrollvariablen angibt, für die der Kontrollwert nach Bevölkerung skaliert wird. Standard: None
.
Im folgenden Beispiel wird die Kontrollvariable an der zweiten Position (Index 1
) nach Bevölkerung skaliert:
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
Boolescher Wert, der angibt, ob für jede geografische Einheit eine eigene Residualvarianz verwendet werden soll. Wenn
False
festgelegt ist, wird für alle geografischen Einheiten eine gemeinsame Residualvarianz verwendet. Standard: False
.
Im folgenden Beispiel wird das Modell so konfiguriert, dass für jede geografische Einheit eine eigene Residualvarianz verwendet wird:
model_spec = spec.ModelSpec(unique_sigma_for_each_geo=True)