Vous pouvez personnaliser et configurer la spécification du modèle de base Meridian selon vos besoins spécifiques, par exemple en personnalisant les a priori du ROI, en ajustant la saisonnalité, en définissant la durée maximale de report, en utilisant la couverture et la fréquence, et plus encore. Pour en savoir plus sur le modèle de base et les options de Meridian, consultez la section Le modèle Meridian.
Spécification de modèle par défaut
Vous pouvez utiliser la spécification de modèle par défaut suivante pour commencer à créer votre modèle :
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,
)
Définir les a priori
Vous pouvez personnaliser les a priori dans la spécification de modèle par défaut. Chaque paramètre dispose de son propre a priori indépendant, qui peut être défini par l'argument prior
dans la ModelSpec
de Meridian. Pour en savoir plus sur les a priori et les exceptions, consultez Distributions a priori par défaut.
L'exemple suivant personnalise les distributions a priori du ROI pour chaque canal média. Dans cet exemple, les a priori du ROI pour les canaux média sont différents.
- Canal 1 :
LogNormal(0.2, 0.7)
- Canal 2 :
LogNormal(0.3, 0.9)
- Canal 3 :
LogNormal(0.4, 0.6)
- Canal 4 :
LogNormal(0.3, 0.7)
- Canal 5 :
LogNormal(0.3, 0.6)
- Canal 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)
Où le prior
dans ModelSpec
est un objet PriorDistribution
spécifiant la distribution a priori de chaque ensemble de paramètres de modèle. Chaque paramètre dispose de son propre a priori indépendant, qui peut être défini par le constructeur prior_distribution.PriorDistribution()
.
Les paramètres de modèle avec un indice m
(par exemple, roi_m
) peuvent avoir une dimensionnalité égale au nombre de canaux média ou être unidimensionnels.
Lorsque la dimensionnalité est égale au nombre de canaux média, l'ordre des valeurs de paramètre dans l'a priori personnalisé correspond à l'ordre dans data.media_channel
(un a priori personnalisé est donc défini pour chaque canal média respectif). Si vous ne parvenez pas à déterminer un a priori personnalisé pour certains canaux média, vous pouvez utiliser manuellement la valeur tfd.LogNormal(0.2, 0.9)
par défaut. Lorsqu'un a priori unidimensionnel est transmis, la dimension unique est utilisée pour tous les canaux média.
La logique de définition des a priori pour les paramètres de modèle avec un indice c
(par exemple, gamma_c
) est identique à celle de l'indice m
. Pour les indices c
, la dimensionnalité peut être égale au nombre de variables de contrôle ou unidimensionnelle. Lorsque la dimensionnalité est égale au nombre de variables de contrôle, l'ordre des valeurs de paramètre dans l'a priori personnalisé correspond à l'ordre dans data.control_variable
(un a priori personnalisé est donc défini pour chaque variable de contrôle respective).
L'exemple suivant montre qu'un seul chiffre est utilisé pour définir le même a priori du ROI pour chaque canal. Dans cet exemple, les a priori du ROI pour les deux canaux média sont identiques, et sont tous deux représentés par 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)
Important : Notez que Meridian dispose d'un paramètre ROI (roi_rf
) et d'un paramètre bêta (beta_rf
) distincts pour les canaux qui comportent des données de couverture et de fréquence. Par conséquent, il est nécessaire d'apporter certaines modifications aux extraits de code mentionnés précédemment lorsque des canaux spécifiques disposent de telles données. Dans cet exemple, les canaux 4 et 5 comportent des données de couverture et de fréquence.
Afin de personnaliser les distributions a priori du ROI pour chaque canal média :
# 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)
Notez que l'ordre des valeurs de paramètre dans roi_rf_mu
et roi_rf_sigma
doit correspondre à data.rf_channel
.
Afin de définir les mêmes a priori du ROI pour tous les canaux média :
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)
Utiliser une répartition entre données d'entraînement et de test (facultatif)
Nous vous recommandons d'utiliser une répartition entre données d'entraînement et de test pour éviter le surapprentissage et vous assurer que le modèle se généralise correctement avec les nouvelles données. Pour ce faire, utilisez holdout_id
. Il s'agit d'une étape facultative.
L'exemple suivant montre un argument holdout_id
qui définit de manière aléatoire 20 % des données en tant que groupe test :
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)
Où holdout_id
est un tenseur booléen facultatif de dimensions (n_geos
x n_times
) ou (n_times
), qui indique les observations exclues de l'échantillon d'entraînement. Seule la variable de réponse est exclue de l'échantillon d'entraînement, et les variables média sont toujours incluses, car elles peuvent affecter l'adstock des semaines suivantes. Par défaut : None
(ce qui signifie qu'il n'y a pas de zones géographiques ni de périodes de validation).
Affiner l'ajustement de saisonnalité automatique (facultatif)
Meridian applique un ajustement de saisonnalité automatique à l'aide d'une approche à intercept aléatoire. Vous pouvez affiner les effets en ajustant la valeur de knots
.
Pour en savoir plus, consultez Fonctionnement de l'argument knots
.
knots
est un entier ou une liste d'entiers facultatifs indiquant les nœuds utilisés pour estimer les effets temporels. Lorsque knots
est une liste d'entiers, les emplacements des nœuds sont fournis par cette liste, où 0 correspond à un nœud dans la première période, 1 à un nœud dans la deuxième période, etc., et (n_times - 1
) correspond à un nœud dans la dernière période.
Lorsque knots
est un entier, il existe un nombre correspondant de nœuds avec des emplacements à intervalles égaux sur les périodes, y compris des nœuds à 0 et (n_times - 1
). Lorsque knots
correspond à 1
, un seul coefficient de régression commun est utilisé pour toutes les périodes.
Si knots
est défini sur None
, le nombre de nœuds utilisés est égal au nombre de périodes dans le cas d'un modèle géographique. Cela revient à ce que chaque période dispose de son propre coefficient de régression. Pour les modèles nationaux, si knots
est défini sur None
, le nombre de nœuds utilisé est 1
. Par défaut, sa valeur est définie sur None
.
Pour en savoir plus, consultez Choisir le nombre de nœuds pour les effets temporels dans le modèle.
Exemples
Définissez
knots
sur1
pour qu'il n'y ait pas d'ajustement de saisonnalité automatique. Dans ce cas, nous vous recommandons d'inclure vos propres variables indicatrices de saisonnalité ou de jours fériés en tant que variables de contrôle :model_spec = spec.ModelSpec(knots=1)
Définissez
knots
sur un nombre relativement élevé :knots = round(0.8 * n_times) model_spec = spec.ModelSpec(knots=knots)
Définissez des nœuds tous les quatre points temporels :
knots = np.arange(0, n_times, 4).tolist() model_spec = spec.ModelSpec(knots=knots)
Définissez des nœuds pour qu'il y ait un nœud en novembre et en décembre, mais pour qu'ils soient relativement rares ailleurs. Pour que cet exemple soit plus pratique, nous partons du principe qu'il n'y a que 12 points de données et que les données sont mensuelles (cette hypothèse n'est ni réaliste, ni recommandée). Cet exemple est résumé dans le tableau suivant :
Pour définir des nœuds au niveau des indices
0
,3
,6
,10
et11
:knots = [0, 3, 6, 10, 11] model_spec = spec.ModelSpec(knots=knots)
Vous pouvez utiliser une approche similaire pour assurer la présence de nœuds pendant les principaux jours fériés.
Ajuster la calibration du ROI (facultatif)
Meridian introduit une méthode de calibration du ROI qui reconfigure le ROI en tant que paramètre de modèle. Pour en savoir plus, consultez A priori du ROI pour la calibration.
Par défaut, le même a priori non informatif sur le ROI est appliqué à tous les canaux média. Vous pouvez ajuster cette fonctionnalité en procédant comme suit :
- Désactiver la calibration du ROI
- Définir la période de calibration du ROI
Désactiver la calibration du ROI
Vous pouvez désactiver la fonctionnalité de calibration du ROI à l'aide de media_prior_type='coefficient'
et rf_prior_type='coefficient'
:
model_spec = spec.ModelSpec(
media_prior_type='coefficient',
rf_prior_type='coefficient',
)
L'argument media_prior_type
indique si vous devez utiliser un a priori sur roi_m
, mroi_m
ou beta_m
dans PriorDistribution
. Par défaut : 'roi'
(recommandé)
Définir la période de calibration du ROI
Bien que les coefficients de régression de l'effet du média n'aient pas d'effets qui varient dans le temps, il existe un argument de fenêtre de calibration pour définir l'a priori du ROI (ou du ROIm). En effet, à un moment donné, le ROI (ou le ROIm) dépend de facteurs supplémentaires qui peuvent varier dans le temps :
- Les courbes de Hill modélisent les rendements décroissants non linéaires de l'exécution média. Par conséquent, le volume d'exécution média à un moment donné peut avoir un impact sur le ROI.
- Affectation des médias à différentes zones géographiques avec des niveaux d'efficacité différents.
- Coût de l'exécution média.
Vous pouvez calibrer la MMM à l'aide d'un sous-ensemble de données lorsque les résultats des tests ne reflètent pas le retour sur les dépenses publicitaires (ROAS) de modélisation que la MMM vise à mesurer. Par exemple, la période de test n'est pas alignée sur la période des données de la MMM. Pour en savoir plus, consultez Calibration du modèle mix média avec des a priori bayésiens et A priori et calibration du ROI.
L'exemple suivant montre comment spécifier la période de calibration du ROI du '2021-11-01'
au '2021-12-20'
pour le canal 1. Tous les canaux média non spécifiés dans la roi_period
utiliseront toutes les périodes disponibles pour la calibration du 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)
Où roi_calibration_period
est un tableau booléen facultatif de forme (n_media_times, n_media_channels)
indiquant le sous-ensemble time
pour la calibration du ROI média. Si la valeur est None
, toutes les périodes sont utilisées pour la calibration du ROI média.
Par défaut : None
.
Notez que Meridian utilise un paramètre différent (rf_roi_calibration_period
) pour les canaux qui comportent des données de couverture et de fréquence.
L'exemple suivant montre comment spécifier la période de calibration du ROI du '2021-11-01'
au '2021-12-20'
pour le canal 5, qui utilise la couverture et la fréquence comme entrées.
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)
Où rf_roi_calibration_period
est un tableau booléen facultatif de forme (n_media_times, n_rf_channels)
. Si la valeur est None
, toutes les périodes et zones géographiques sont utilisées pour la calibration du ROI média.
Par défaut : None
.
Définir des attributs supplémentaires (facultatif)
Si nécessaire, vous pouvez modifier les attributs restants dans la spécification de modèle par défaut. Cette section décrit les attributs restants et fournit des exemples illustrant comment modifier les valeurs.
baseline_geo
Entier facultatif ou chaîne pour la zone géographique de référence. Celle-ci est traitée comme la zone géographique de référence dans l'encodage factice des zones géographiques. Les zones géographiques qui ne sont pas de référence ont une variable d'indicateur tau_g
correspondante. Cela signifie qu'elles présentent une variance a priori plus élevée que la zone géographique de référence. Lorsque la valeur est définie sur None
, la zone géographique la plus peuplée est utilisée comme référence. Par défaut : None
L'exemple suivant montre la zone géographique de référence définie sur 'Geo10'
:
model_spec = spec.ModelSpec(baseline_geo='Geo10')
hill_before_adstock
Cette valeur booléenne indique si la fonction Hill doit être appliquée avant la fonction Adstock, contrairement à l'ordre par défaut (Adstock avant Hill). Par défaut : False
Les exemples suivants montrent que la fonction Hill sera appliquée en premier, la valeur étant définie sur True
:
model_spec = spec.ModelSpec(hill_before_adstock=True)
max_lag
Cet entier indique le nombre maximal de périodes de décalage (>= 0) à inclure dans le calcul de l'adstock. La valeur peut aussi être définie sur None
, ce qui équivaut à l'intégralité de la période de modélisation. Par défaut : 8
L'exemple suivant remplace la valeur par 4
:
model_spec = spec.ModelSpec(max_lag=4)
media_effects_dist
Cette chaîne permet de spécifier la répartition des effets aléatoires des médias dans différentes zones géographiques.
Les valeurs autorisées sont 'normal'
ou 'log_normal'
. Par défaut : 'log_normal'
Où :
media_effects_dist='log_normal'
correspond à \(\beta m,g\ {_\sim^{iid}} Lognormal(\beta m, \eta ^2m)\)media_effects_dist='normal'
correspond à \(\beta m,g\ {_\sim^{iid}} Normal (\beta m, \eta ^2m)\)
L'exemple suivant montre comment remplacer la valeur par 'normal'
:
model_spec = spec.ModelSpec(media_effects_dist='normal')
control_population_scaling_id
Ce tenseur booléen facultatif de dimension (n_controls
) indique les variables de contrôle pour lesquelles la valeur de contrôle sera ajustée selon la population. Par défaut : None
L'exemple suivant spécifie que la variable de contrôle à l'index 1
doit être ajustée selon la population :
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
Cette valeur booléenne indique si une variance résiduelle unique doit être utilisée pour chaque zone géographique. Si la valeur est False
, une seule variance résiduelle est utilisée pour toutes les zones géographiques. Par défaut : False
L'exemple suivant définit le modèle pour qu'il utilise une variance résiduelle unique pour chaque zone géographique :
model_spec = spec.ModelSpec(unique_sigma_for_each_geo=True)