Puedes personalizar y configurar la especificación del modelo base de Meridian según tus necesidades específicas, como personalizar las distribuciones a priori del ROI, ajustar la estacionalidad, establecer la duración máxima de transferencia, usar datos de alcance y frecuencia, y mucho más. Para obtener más información sobre el modelo base y las opciones de Meridian, consulta la sección El modelo Meridian.
Especificaciones del modelo predeterminado
Puedes usar la siguiente especificación del modelo predeterminado para comenzar a crear tu propio modelo:
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,
)
Cómo establecer las distribuciones a priori
Puedes personalizar las distribuciones a priori de la especificación del modelo predeterminado. Cada parámetro obtiene su propia distribución a priori independiente, la cual se puede establecer con el argumento prior
en ModelSpec
de Meridian. Para obtener información sobre las distribuciones a priori y las excepciones, consulta Distribuciones a priori predeterminadas.
En el siguiente ejemplo, se personalizan las distribuciones a priori del ROI para cada canal de medios. En este caso en particular, las distribuciones a priori del ROI difieren para cada canal de medios.
- 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)
Aquí prior
en ModelSpec
es un objeto PriorDistribution
que especifica la distribución a priori de cada conjunto de parámetros del modelo. Cada parámetro obtiene su propia distribución a priori independiente, la cual se puede establecer con el constructor prior_distribution.PriorDistribution()
.
Los parámetros del modelo con el subíndice m
(por ejemplo, roi_m
) pueden tener una dimensionalidad igual a la cantidad de canales de medios o ser unidimensionales.
Cuando la dimensionalidad es igual a la cantidad de canales de medios, el orden de los valores de los parámetros en la distribución a priori personalizada coincide con el de data.media_channel
. Esto representa una distribución a priori personalizada para cada uno de los respectivos canales de medios. Si no puedes determinar una distribución a priori personalizada para algunos de los canales de medios, considera usar la configuración predeterminada tfd.LogNormal(0.2, 0.9)
de forma manual. Cuando se pasa una distribución a priori unidimensional, se usa una única dimensión para todos los canales de medios.
La lógica para establecer las distribuciones a priori para los parámetros del modelo con el subíndice c
(por ejemplo, gamma_c
) es la misma que para el subíndice m
. Los parámetros con el subíndice c
pueden tener una dimensionalidad igual a la cantidad de variables de control o ser unidimensionales. Cuando la dimensionalidad es igual a la cantidad de variables de control, el orden de los valores de los parámetros en la distribución a priori personalizada coincide con el de data.control_variable
. Esto representa una distribución a priori personalizada para cada una de las respectivas variables de control.
En el siguiente ejemplo, se utiliza un único número para establecer la misma distribución a priori del ROI en cada canal. En este caso en particular, las distribuciones a priori del ROI de los dos canales de medios son idénticas y ambas se representan como 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)
Es importante destacar que Meridian ofrece dos parámetros distintos, uno de ROI (roi_rf
) y otro beta (beta_rf
), para los canales con datos de alcance y frecuencia. En consecuencia, se deben hacer algunas modificaciones en los fragmentos de código antes mencionados cuando ciertos canales tengan datos de alcance y frecuencia. En este ejemplo, los canales 4 y 5 tienen datos de alcance y frecuencia.
Si deseas personalizar las distribuciones a priori del ROI para cada canal de medios, consulta esta información:
# 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)
Ten en cuenta que el orden de los valores de los parámetros en roi_rf_mu
y roi_rf_sigma
debe coincidir con el de data.rf_channel
.
Si deseas establecer las mismas distribuciones a priori del ROI para todos los canales de medios, consulta esta información:
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)
Cómo usar una división de datos de entrenamiento y prueba (opcional)
Te recomendamos que utilices una división de datos de entrenamiento y prueba para evitar el sobreajuste y asegurarte de que el modelo se generalice bien cuando haya datos nuevos. Esto se puede hacer con holdout_id
. Este paso es opcional.
En el siguiente ejemplo, se muestra un argumento holdout_id
que establece de forma aleatoria el 20% de los datos como el grupo de prueba:
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)
Aquí holdout_id
es un tensor booleano opcional de las dimensiones (n_geos
× n_times
) o (n_times
) que indica qué observaciones se excluyen de la muestra de entrenamiento. Solo la variable de respuesta se excluye de la muestra de entrenamiento. Las variables de medios permanecen incluidas, ya que pueden afectar el Adstock de las semanas posteriores. La configuración predeterminada es None
, lo que significa que no se excluye ninguna ubicación geográfica ni período.
Cómo configurar el ajuste de estacionalidad automático (opcional)
Meridian aplica un ajuste de estacionalidad automático a través de un enfoque de intersección que varía con el tiempo. Los efectos pueden ajustarse modificando el valor de knots
.
Para obtener más información, consulta Cómo funciona el argumento knots
.
knots
es un número entero o una lista de números enteros opcionales que indican los nudos utilizados para estimar los efectos del tiempo. Cuando knots
es una lista de números enteros, las ubicaciones de los nudos se proporcionan en esa lista, donde cero corresponde a un nudo en el primer período, uno corresponde a un nudo en el segundo período y así sucesivamente, mientras que (n_times - 1
) es el nudo en el último período.
Cuando knots
es un número entero, hay esa cantidad de nudos con ubicaciones equidistantes en los períodos, incluidos los nudos en cero y (n_times - 1
). Cuando knots
es 1
, hay un único coeficiente de regresión común que se usa para todos los períodos.
En el caso de los modelos geográficos, si knots
se establece en None
, la cantidad de nudos utilizados es igual a la cantidad de períodos. Esto equivale a que cada período tenga su propio coeficiente de regresión. En el caso de los modelos nacionales, si knots
se establece en None
, la cantidad de nudos utilizados es 1
. De forma predeterminada, su valor se establece en None
.
Consulta Cómo elegir la cantidad de nudos para los efectos del tiempo en el modelo para obtener información al respecto.
Ejemplos
Puedes establecer
knots
en1
para que no haya un ajuste de estacionalidad automático. En este caso, te recomendamos incluir tus propias pseudovariables de estacionalidad o de días festivos como variables de control:model_spec = spec.ModelSpec(knots=1)
Puedes establecer
knots
en un número relativamente grande:knots = round(0.8 * n_times) model_spec = spec.ModelSpec(knots=knots)
Puedes establecer nudos cada 4 puntos temporales:
knots = np.arange(0, n_times, 4).tolist() model_spec = spec.ModelSpec(knots=knots)
Puedes establecer los nudos para que haya uno en noviembre y otro en diciembre, pero relativamente menos en otros momentos. Para no complejizar demasiado el ejemplo, supongamos que solo hay 12 datos mensuales (esta suposición no es realista ni se recomienda). Este ejemplo se resume en la siguiente tabla:
Para establecer nudos en los índices
0
,3
,6
,10
y11
, haz lo siguiente:knots = [0, 3, 6, 10, 11] model_spec = spec.ModelSpec(knots=knots)
Puedes usar un enfoque similar para asegurarte de que haya nudos en los días festivos más importantes.
Cómo ajustar la calibración del ROI (opcional)
Meridian presenta un método de calibración del ROI que permite reparametrizar el ROI como parámetro del modelo. Para obtener más información, consulta Distribuciones a priori del ROI para la calibración.
De forma predeterminada, se aplica la misma distribución a priori no informativa del ROI a todos los canales de medios. Hay dos acciones que te permiten ajustar esta función:
- Desactivar la calibración del ROI
- Establecer el período de calibración del ROI
Cómo desactivar la calibración del ROI
Puedes desactivar la función de calibración del ROI utilizando media_prior_type='coefficient'
y rf_prior_type='coefficient'
:
model_spec = spec.ModelSpec(
media_prior_type='coefficient',
rf_prior_type='coefficient',
)
El argumento media_prior_type
indica si se debe usar una distribución a priori en roi_m
, mroi_m
o beta_m
en PriorDistribution
. Configuración predeterminada: 'roi'
(recomendada).
Cómo establecer el período de calibración del ROI
Aunque los coeficientes de regresión de los efectos de los medios no tienen efectos que varíen con el tiempo, hay un argumento de período de calibración para establecer la distribución a priori del ROI (o del mROI). Esto se debe a que el ROI (o el mROI) en un momento determinado depende de factores adicionales que pueden variar con el tiempo:
- Las curvas de Hill modelan la disminución no lineal de los retornos asociados con la ejecución de los medios. Por lo tanto, el grado de ejecución de los medios en un momento determinado puede afectar el ROI.
- La asignación de medios en las diferentes ubicaciones geográficas y su efectividad pueden variar.
- El costo de la ejecución de medios puede variar.
Puedes calibrar el MMM con un subconjunto de datos cuando los resultados experimentales no reflejen el retorno de la inversión publicitaria (ROAS) modelado que el MMM intenta medir. Por ejemplo, el período del experimento no coincide con el período de los datos del MMM. Para obtener más información, consulta Calibración del modelo de combinación de medios con distribuciones a priori bayesianas y Distribuciones a priori y calibración del ROI.
En el siguiente ejemplo, se muestra cómo especificar el período de calibración del ROI del '2021-11-01'
al '2021-12-20'
para el canal 1. Los canales de medios que no se especifiquen en roi_period
utilizarán todos los períodos disponibles para la calibración del 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)
Aquí roi_calibration_period
es un array booleano opcional con la forma (n_media_times, n_media_channels)
que indica el subconjunto de time
para la calibración del ROI de los medios. Si se establece en None
, se utilizarán todos los períodos para la calibración del ROI de los medios.
Configuración predeterminada: None
.
Es importante destacar que Meridian ofrece un parámetro diferente, rf_roi_calibration_period
, para los canales con datos de alcance y frecuencia.
En el siguiente ejemplo, se muestra cómo especificar el período de calibración del ROI del '2021-11-01'
al '2021-12-20'
para el canal 5, que usa datos de entrada de alcance y frecuencia.
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)
Aquí rf_roi_calibration_period
es un array booleano opcional con la forma (n_media_times, n_rf_channels)
. Si se establece en None
, se utilizarán todos los períodos y ubicaciones geográficas para la calibración del ROI de los medios.
La configuración predeterminada es None
.
Cómo establecer atributos adicionales (opcional)
Puedes cambiar los atributos restantes de la especificación del modelo predeterminado según sea necesario. En esta sección, se describen los atributos restantes y ejemplos de cómo cambiar los valores.
baseline_geo
Es un número entero o una cadena opcionales que indican la ubicación geográfica de referencia. Esta ubicación se usa como referencia en la pseudocodificación de ubicaciones geográficas. Las ubicaciones geográficas que no son de referencia tienen una variable de indicador tau_g
correspondiente, lo que significa que tienen una varianza a priori más alta que las de referencia. Cuando se establece en None
, se utiliza la ubicación geográfica con la mayor población como referencia. La configuración predeterminada es None
.
En el siguiente ejemplo, se muestra la ubicación geográfica de referencia establecida en 'Geo10'
:
model_spec = spec.ModelSpec(baseline_geo='Geo10')
hill_before_adstock
Es un valor booleano que indica si se debe aplicar la función de Hill antes que la función de Adstock, lo que se opone al orden predeterminado (Adstock antes que Hill). La configuración predeterminada es False
.
En los siguientes ejemplos, se muestra que la función de Hill se aplicará primero, ya que el valor se establece en True
:
model_spec = spec.ModelSpec(hill_before_adstock=True)
max_lag
Es un número entero que indica la cantidad máxima de períodos de retraso (≥ 0) que se deben incluir en el cálculo de Adstock. También se puede establecer en None
, lo que equivale a todo el período de modelado. La configuración predeterminada es 8
.
En el siguiente ejemplo, se cambia el valor a 4
:
model_spec = spec.ModelSpec(max_lag=4)
media_effects_dist
Es una cadena que permite especificar la distribución de los efectos aleatorios de los medios en las ubicaciones geográficas.
Los valores permitidos son 'normal'
o 'log_normal'
. La configuración predeterminada es 'log_normal'
.
Aquí ocurre lo siguiente:
media_effects_dist='log_normal'
es \(\beta m,g\ {_\sim^{iid}} Lognormal(\beta m, \eta ^2m)\).media_effects_dist='normal'
es \(\beta m,g\ {_\sim^{iid}} Normal (\beta m, \eta ^2m)\).
En el siguiente ejemplo, se muestra cómo cambiar el valor a 'normal'
:
model_spec = spec.ModelSpec(media_effects_dist='normal')
control_population_scaling_id
Es un tensor booleano opcional de dimensión (n_controls
) que indica las variables de control para las que se ajustará el valor de control según la población. La configuración predeterminada es None
.
En el siguiente ejemplo, se especifica que la variable de control en el índice 1
se debe ajustar según la población:
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
Es un valor booleano que indica si se debe usar una varianza residual única para cada ubicación geográfica. Si es False
, se usa una sola varianza residual para todas las ubicaciones geográficas. La configuración predeterminada es False
.
En el siguiente ejemplo, se establece el modelo para que use una varianza residual única para cada ubicación geográfica:
model_spec = spec.ModelSpec(unique_sigma_for_each_geo=True)