domingo, 27 de julio de 2025

RCA de tienda online

 

Blog de código abierto de AWS

Análisis de causa raíz con Dowhy, una biblioteca de Python de código abierto para el aprendizaje automático causal

 

Identificar las causas raíz de los cambios observados en los sistemas complejos puede ser una tarea difícil que requiere un conocimiento de dominio profundo y potencialmente horas de trabajo manual. Por ejemplo, es posible que deseemos analizar una caída inesperada en las ganancias de un producto vendido en una tienda en línea, donde varios factores entrelazados pueden afectar la ganancia general del producto de manera sutil.

¿No sería bueno si tuviéramos herramientas automatizadas para simplificar y acelerar esta tarea? ¿Una biblioteca que puede identificar automáticamente las causas raíz de un efecto observado con algunas líneas de código?

Esta es la idea detrás de las características del análisis de causa raíz (RCA) de la Dowhy , a las que AWS contribuyó con un gran conjunto de nuevos algoritmos de aprendizaje automático causal (ML) el año pasado. Estos algoritmos son el resultado de años de investigación de Amazon en modelos causales gráficos y se lanzaron en Dowhy V0.8 en julio del año pasado. Además, AWS unió fuerzas con Microsoft para formar una nueva organización llamada Pywhy , ahora hogar de Dowhy. La misión de Pywhy, según la Carta, es "construir un ecosistema de código abierto para el aprendizaje automático causal que avanza el estado de la técnica y lo pone a disposición de los profesionales e investigadores. Construimos y organizamos bibliotecas interoperables, herramientas y otros recursos que abarcan una variedad de tareas y aplicaciones causales, conectados a través de una API común sobre las operaciones causales fundacionales y el enfoque en el fin a la canal de análisis". "

En este artículo, veremos más de cerca estos algoritmos. Específicamente, queremos demostrar su aplicabilidad en el contexto del análisis de causa raíz en sistemas complejos.

Aplicar los algoritmos ML causales de Dowhy a este tipo de problema puede reducir el tiempo para encontrar una causa raíz significativamente. Para demostrar esto, profundizaremos en un escenario de ejemplo basado en datos sintéticos generados aleatoriamente donde conocemos la verdad del suelo.

El escenario

Supongamos que estamos vendiendo un teléfono inteligente en una tienda en línea con un precio minorista de $ 999. El beneficio general del producto depende de varios factores, como el número de unidades vendidas, costos operativos o gasto publicitario. Por otro lado, el número de unidades vendidas, por ejemplo, depende del número de visitantes en la página del producto, el precio en sí y las posibles promociones continuas. Supongamos que observamos una ganancia constante de nuestro producto durante el año 2021, pero de repente, hay una caída significativa en las ganancias a principios de 2022. ¿Por qué?

En el siguiente escenario, utilizaremos Dowhy para comprender mejor los impactos causales de los factores que influyen en las ganancias e identificar las causas de la caída de ganancias. Para analizar nuestro problema en cuestión, primero debemos definir nuestra creencia sobre las relaciones causales. Para esto, recopilamos diarios de los diferentes factores que afectan las ganancias. Estos factores son:

  • ¿Evento de compra? : Un valor binario que indica si tuvo lugar un evento de compra especial, como las ventas de Black Friday o Cyber Monday.
  • Gasto publicitario : gasto en campañas publicitarias.
  • Vistas de la página : Número de visitas en la página Detalle del producto.
  • Precio unitario : precio del dispositivo, que podría variar debido a descuentos temporales.
  • Unidades vendidas : número de teléfonos vendidos.
  • Ingresos : ingresos diarios.
  • Costo operativo : gastos operativos diarios que incluyen costos de producción, gastos en anuncios, gastos administrativos, etc.
  • Beneficio : ganancia diaria.

Al observar estos atributos, podemos usar nuestro conocimiento de dominio para describir las relaciones de causa-efecto en forma de un gráfico acíclico dirigido, que representa nuestro gráfico causal a continuación. El gráfico se muestra aquí:

Gráfico causal
Una flecha de x a y, x → y En este diagrama describe una relación causal directa, donde x es la causa de Y. En este escenario sabemos lo siguiente:

¿Evento de compra? Impactos:
Gasto publicitario : para promocionar el producto en eventos de compras especiales, requerimos un gasto publicitario adicional.
Vistas de la página : los eventos de compra generalmente atraen a una gran cantidad de visitantes a un minorista en línea debido a descuentos y diversas ofertas.
Precio unitario : generalmente, los minoristas ofrecen un descuento en el precio minorista habitual en días con un evento de compra.
Unidades vendidas : los eventos de compra a menudo tienen lugar durante las celebraciones anuales como la Navidad, el Día del Padre, etc., cuando las personas a menudo compran más de lo habitual.

de gasto publicitario :
de página Vistas : cuanto más gastamos en anuncios, más probabilidades de las personas visitan la página del producto.
Costo operativo : el gasto en anuncios es parte del costo operativo.

Vistas de la página Impactos:
Unidades vendidas : cuantas más personas visiten la página del producto, más probable es que se compre el producto. Esto es bastante obvio ver que si nadie visitara la página, no habría ninguna venta.

del precio unitario :
Unidades vendidas : cuanto mayor/menor sea el precio, menos/más unidades se venden.
Ingresos : los ingresos diarios generalmente consisten en el producto del número de unidades vendidas y el precio unitario.

Unidades vendidas impactos:
Unidades vendidas : el mismo argumento que antes, el número de unidades vendidas influye en gran medida en los ingresos.
Costo operativo : hay un costo de fabricación para cada unidad que producimos y vendemos. Cuantas más unidades sean bien, mayores seremos los ingresos, pero también mayores serán los costos de fabricación.

de costos operativos :
Beneficio : la ganancia se basa en los ingresos generados menos el costo operativo.

de ingresos :
Beneficio : la misma razón que para el costo operativo.


Paso 1: Definir modelos causales

Ahora, modelemos estas relaciones causales con el módulo de modelo causal gráfico (GCM) de Dowhy. En el primer paso, necesitamos definir un llamado de S modelo causal (SCM) , que es una combinación del gráfico causal y los modelos generativos subyacentes que describen el proceso de generación de datos.

Para modelar la estructura de gráficos, utilizamos NetworkX , una popular biblioteca de gráficos Python de código abierto. En NetworkX, podemos representar nuestro gráfico causal de la siguiente manera: 

import networkx as nx

causal_graph = nx.DiGraph([('Page Views', 'Sold Units'),
                           ('Revenue', 'Profit'),
                           ('Unit Price', 'Sold Units'),
                           ('Unit Price', 'Revenue'),
                           ('Shopping Event?', 'Page Views'),
                           ('Shopping Event?', 'Sold Units'),
                           ('Shopping Event?', 'Unit Price'),
                           ('Shopping Event?', 'Ad Spend'),
                           ('Ad Spend', 'Page Views'),
                           ('Ad Spend', 'Operational Cost'),
                           ('Sold Units', 'Revenue'),
                           ('Sold Units', 'Operational Cost'),
                           ('Operational Cost', 'Profit')])

A continuación, miramos los datos de 2021: 

import pandas as pd

pd.options.display.float_format = '${:,.2f}'.format  # Format dollar columns
data_2021 = pd.read_csv('2021 Data.csv', index_col='Date')
data_2021.head()

Causal graph variables chart  

omo vemos, tenemos una muestra para cada día en 2021 con todas las variables en el gráfico causal. Tenga en cuenta que en los datos sintéticos que consideramos en esta publicación de blog, los eventos de compras también se generaron al azar.

Definimos el gráfico causal, pero aún necesitamos asignar modelos generativos a los nodos. Con Dowhy, podemos especificar manualmente esos modelos y configurarlos si es necesario, o inferir automáticamente modelos "apropiados" utilizando heurísticas de los datos. Aprovecharemos este último aquí:

from dowhy import gcm

# Create the structural causal model object
scm = gcm.StructuralCausalModel(causal_graph)

# Automatically assign generative models to each node based on the given data
gcm.auto.assign_causal_mechanisms(scm, data_2021)

Siempre que esté disponible, recomendamos asignar modelos basados en el conocimiento previo, ya que los modelos imitarían de cerca la física del dominio y no confiarían en los matices de los datos. Sin embargo, aquí le pedimos a Dowhy que hiciera esto por nosotros.

Paso 2: ajuste los modelos causales a los datos

Después de asignar un modelo a cada nodo, necesitamos aprender los parámetros del modelo:

gcm.fit(scm, data_2021)

El fit El método aprende los parámetros de los modelos generativos en cada nodo. El SCM ajustado ahora se puede usar para responder diferentes tipos de preguntas causales.

Paso 3: Responder preguntas causales

¿Cuáles son los factores clave que influyen en la varianza en las ganancias?

En este punto, queremos entender qué factores impulsan los cambios en las ganancias. Primero echemos un vistazo más de cerca a las ganancias con el tiempo. Para esto, estamos utilizando pandas para trazar las ganancias con el tiempo para 2021, donde la trama producida muestra las ganancias en dólares en el eje Y y el tiempo en el eje X.

data_2021['Profit'].plot(ylabel='Profit in $', figsize=(15,5), rot=45)
 Profit over time chart 
 

Vemos algunos picos significativos en las ganancias durante todo el año. Podemos cuantificar aún más mirando la desviación estándar, que podemos estimar utilizando el std() función de pandas:

data_2021['Profit'].std()
259247.66010978

La desviación estándar estimada de ~ 259247 dólares es bastante significativa. Al observar el gráfico causal, vemos que los ingresos y el costo operativo tienen un impacto directo en las ganancias, pero ¿cuál de ellos contribuye más a la varianza? Para descubrir esto, podemos hacer uso del de resistencia a la flecha directa algoritmo que cuantifica la influencia causal de una flecha específica en el gráfico:

import numpy as np


def convert_to_percentage(value_dictionary):
    total_absolute_sum = np.sum([abs(v) for v in value_dictionary.values()])
    return {k: abs(v) / total_absolute_sum * 100 for k, v in value_dictionary.items()}


arrow_strengths = gcm.arrow_strength(scm, target_node='Profit')

gcm.util.plot(causal_graph, 
              causal_strengths=convert_to_percentage(arrow_strengths), 
              figure_size=[15, 10]) 

causal graph that shows percent revenue 

En este gráfico causal, vemos cuánto contribuye cada nodo a la varianza en las ganancias. Por simplicidad, las contribuciones se convierten en porcentajes. Dado que la ganancia en sí es solo la diferencia entre los ingresos y el costo operativo, no esperamos más factores que influyan en la varianza. Como vemos, los ingresos contribuyen al 74.45 por ciento y tiene más impacto que el costo operativo que contribuye con el 25.54 por ciento. Esto tiene sentido ver que los ingresos generalmente varían más que el costo operativo debido a la mayor dependencia de la cantidad de unidades vendidas. Tenga en cuenta que Dowhy también admite otros tipos de medidas, por ejemplo, divergencia KL .

Si bien las influencias directas son útiles para comprender qué padres directos influyen más en la variación en las ganancias, esto confirma principalmente nuestra creencia previa. Sin embargo, la cuestión de qué factor ahora es responsable de esta alta varianza aún no está clara. Los ingresos en sí se basan simplemente en las unidades vendidas y el precio unitario. Aunque podríamos aplicar recursivamente la fuerza de flecha directa a todos los nodos, no obtendríamos una visión correctamente ponderada sobre la influencia de los nodos aguas arriba en la varianza.

¿Cuáles son los factores causales importantes que contribuyen a la varianza en las ganancias? Para descubrir esto, podemos usar de contribución causal intrínseca que atribuye la varianza en las ganancias a los nodos aguas arriba en el gráfico causal. Para esto, primero definimos una función para trazar los valores en una gráfica de barra y luego usamos esto para mostrar las contribuciones estimadas a la varianza como porcentajes:

import matplotlib.pyplot as plt


def bar_plot(value_dictionary, ylabel, uncertainty_attribs=None, figsize=(8, 5)):
    value_dictionary = {k: value_dictionary[k] for k in sorted(value_dictionary)}
    if uncertainty_attribs is None:
        uncertainty_attribs = {node: [value_dictionary[node], value_dictionary[node]] for node in value_dictionary}

    _, ax = plt.subplots(figsize=figsize)
    ci_plus = [uncertainty_attribs[node][1] - value_dictionary[node] for node in value_dictionary.keys()]
    ci_minus = [value_dictionary[node] - uncertainty_attribs[node][0] for node in value_dictionary.keys()]
    yerr = np.array([ci_minus, ci_plus])
    yerr[abs(yerr) < 10**-7] = 0
    plt.bar(value_dictionary.keys(), value_dictionary.values(), yerr=yerr, ecolor='#1E88E5', color='#ff0d57', width=0.8)
    plt.ylabel(ylabel)
    plt.xticks(rotation=45)
    ax.spines['right'].set_visible(False)
    ax.spines['top'].set_visible(False)

    plt.show()


iccs = gcm.intrinsic_causal_influence(scm, target_node='Profit', num_samples_randomization=500)

bar_plot(convert_to_percentage(iccs), ylabel='Variance attribution in %')

Bar chart showing variance attribution percentage for each variable  

Los puntajes que se muestran en este gráfico de barras son porcentajes que indican cuánta variación está contribuyendo cada nodo a las ganancias, sin heredar la varianza de sus padres en el gráfico causal. Como vemos con bastante claridad, el evento de compra tiene, con mucho, la mayor influencia en la variación en nuestros beneficios. Esto tiene sentido, al ver que las ventas se ven fuertemente afectadas durante los períodos de promoción como Black Friday o Prime Day y, por lo tanto, afectan la ganancia general. Sorprendentemente, también vemos que factores como el número de unidades vendidas o el número de vistas de páginas tienen una influencia bastante pequeña, es decir, la gran variación en las ganancias puede explicarse casi por completo por los eventos de compra. Vamos a ver esto visualmente marcando los días en que tuvimos un evento de compra. Para hacerlo, usamos la función de la trama Pandas nuevamente, pero también marcamos todos los puntos en la trama con un bar rojo vertical donde ocurrió un evento de compra: 

data_2021['Profit'].plot(ylabel='Profit in $', figsize=(15,5), rot=45)
plt.vlines(np.arange(0, data_2021.shape[0])[data_2021['Shopping Event?']], data_2021['Profit'].min(),
data_2021['Profit'].max(), linewidth=10, alpha=0.3, color='r')

Graph marked with peak shopping events and profit  

Vemos claramente que los eventos de compra coinciden con los altos picos en las ganancias. Si bien podríamos haber investigado esto manualmente al observar todo tipo de relaciones diferentes o usar el conocimiento del dominio, las tareas se vuelven mucho más difíciles a medida que aumenta la complejidad del sistema. Con algunas líneas de código, obtuvimos estas ideas de Dowhy.

¿Cuáles son los factores clave que explican la caída de ganancias en un día en particular?

Después de un año exitoso en términos de ganancias, las tecnologías más nuevas llegan al mercado y, por lo tanto, queremos mantener las ganancias y deshacerse del exceso de inventario vendiendo más dispositivos. Para aumentar la demanda, por lo tanto, bajamos el precio minorista en un 10% al comienzo de 2022. Según un análisis previo, sabemos que una disminución del 10% en el precio aumentaría aproximadamente la demanda en un 13.75%, un ligero excedente. Tras el de elasticidad de la demanda , esperamos un aumento de alrededor del 37.5% en el número de unidades vendidas. Echemos un vistazo si esto es cierto cargando los datos para el primer día en 2022 y tomando la fracción entre los números de unidades vendidas de ambos años para ese día:

first_day_2022 = pd.read_csv('2022 First Day.csv', index_col='Date')
(first_day_2022['Sold Units'][0] / data_2021['Sold Units'][0] - 1) * 100
18.946914113077252

Sorprendentemente, solo aumentamos el número de unidades vendidas en ~ 19%. Esto ciertamente afectará la ganancia dado que los ingresos son mucho más pequeños de lo esperado. Comparemos con el año anterior al mismo tiempo: 

(1 - first_day_2022['Profit'][0] / data_2021['Profit'][0]) * 100
8.57891513840979

De hecho, la ganancia disminuyó en ~ 8.5%. ¿Por qué es este el caso de ver que esperaríamos una demanda mucho mayor debido a la disminución del precio? Investigamos lo que está pasando aquí.

Para averiguar qué contribuyó a la caída de ganancias, podemos hacer uso de de atribución de anomalías . Aquí, solo necesitamos especificar el nodo objetivo que nos interesa (la ganancia) y la muestra de anomalía que queremos analizar (el primer día de 2022). Estos resultados se trazan en un gráfico de barras que indica las puntuaciones de atribución de cada nodo para la muestra de anomalía dada:

attributions = gcm.attribute_anomalies(scm, target_node='Profit', anomaly_samples=first_day_2022)

bar_plot({k: v[0] for k, v in attributions.items()}, ylabel='Anomaly attribution score')
Bar chart with attribution scores  

Una puntuación de atribución positiva significa que el nodo correspondiente contribuyó a la anomalía observada, que en nuestro caso es la caída de las ganancias. Una puntuación negativa de un nodo indica que el valor observado para el nodo en realidad está reduciendo la probabilidad de la anomalía (por ejemplo, una mayor demanda debido a la disminución del precio debería aumentar la ganancia). Se pueden encontrar más detalles sobre la interpretación de la puntuación en nuestro trabajo de investigación . Curiosamente, las vistas de la página se destacan como un factor que explica la caída de ganancias ese día como se indica en la tabla de barras que se muestra aquí.

Si bien este método nos da una estimación puntual de las atribuciones para los modelos y parámetros particulares que aprendimos, también podemos usar de intervalo de confianza , que incorpora incertidumbres sobre los parámetros del modelo ajustado y las aproximaciones algorítmicas:

median_attributions, confidence_intervals, = gcm.confidence_intervals(
    gcm.fit_and_compute(gcm.attribute_anomalies,
                        scm,
                        bootstrap_training_data=data_2021,
                        target_node='Profit',
                        anomaly_samples=first_day_2022),
    num_bootstrap_resamples=10)

bar_plot(median_attributions, 'Anomaly attribution score', confidence_intervals) 

Bar chart with confidence interval 

Tenga en cuenta que en este gráfico de barras vemos las atribuciones medianas en múltiples ejecuciones en conjuntos de datos más pequeños, donde cada ejecución vuelve a ajustar los modelos y reevalúa las atribuciones. Obtenemos una imagen similar a la de antes, pero el intervalo de confianza de la atribución a las unidades vendidas también contiene cero, lo que significa que su contribución es insignificante. Pero aún quedan algunas preguntas importantes: ¿fue esto solo una coincidencia y, si no, ¿qué parte de nuestro sistema ha cambiado? Para descubrir esto, necesitamos recopilar más datos.

¿Qué causó la caída de ganancias en el primer trimestre de 2022?

Si bien el análisis anterior se basa en una sola observación, veamos si esto era solo una coincidencia o si este es un problema persistente. Al preparar el informe comercial trimestral, tenemos algunos datos más disponibles de los primeros tres meses. Primero verificamos si la ganancia disminuyó en promedio en el primer trimestre de 2022 en comparación con 2021. Similar como antes, podemos hacer esto tomando la fracción entre la ganancia promedio de 2022 y 2021 para el primer trimestre:

data_first_quarter_2021 = data_2021[data_2021.index <= '2021-03-31']
data_first_quarter_2022 = pd.read_csv("2022 First Quarter.csv", index_col='Date')

(1 - data_first_quarter_2022['Profit'].mean() / data_first_quarter_2021['Profit'].mean()) * 100
13.0494881794224

De hecho, la caída de ganancias es persistente en el primer trimestre de 2022. Ahora, ¿cuál es la causa raíz de esto? Aplicemos de cambio de distribución para identificar la parte en el sistema que ha cambiado: 

median_attributions, confidence_intervals = gcm.confidence_intervals(
    lambda: gcm.distribution_change(scm,
                                    data_first_quarter_2021,
                                    data_first_quarter_2022,
                                    target_node='Profit',
                                    # Here, we are intersted in explaining the differences in the mean.
                                    difference_estimation_func=lambda x, y: np.mean(y) - np.mean(x)) 
)

bar_plot(median_attributions, 'Profit change attribution in $', confidence_intervals)
 
Root cause analysis chart for DoWhy 

En nuestro caso, el método de cambio de distribución explica el cambio en la media de las ganancias, es decir, un valor negativo indica que un nodo contribuye a una disminución y un valor positivo a un aumento de la media. Usando el gráfico de barras, ahora tenemos una imagen muy clara de que el cambio en el precio unitario tiene una contribución ligeramente positiva a la ganancia esperada debido al aumento de las unidades vendidas, pero parece que el problema proviene de las vistas de la página que tiene un valor negativo. Si bien ya entendimos esto como un conductor principal de la caída a principios de 2022, ahora hemos aislado y confirmado que algo cambió también para las vistas de la página. Comparemos las vistas promedio de la página con el año anterior.  

(1 - data_first_quarter_2022['Page Views'].mean() / data_first_quarter_2021['Page Views'].mean()) * 100
14.347627108364

De hecho, el número de vistas de página disminuyó en ~ 14%. Dado que eliminamos todos los demás factores potenciales, ahora podemos sumergirnos más profundamente en las vistas de la página y ver lo que está sucediendo allí. Este es un escenario hipotético, pero podríamos imaginar que podría deberse a un cambio en el algoritmo de búsqueda que clasifica este producto más bajo en los resultados y, por lo tanto, impulsa a menos clientes a la página del producto. Sabiendo esto, ahora podríamos comenzar a mitigar el problema.

Con la ayuda de las nuevas características de Dowhy para modelos causales gráficos, solo necesitábamos unas pocas líneas de código para identificar automáticamente los controladores principales de un atípico particular y, especialmente, pudimos identificar los factores principales que causaron un cambio en la distribución.

Conclusión

En este artículo, hemos demostrado cómo Dowhy puede ayudar en el análisis de causa raíz de una caída en las ganancias para una tienda en línea de ejemplo. Para esto, analizamos las características de Dowhy, como las fuerzas de flecha, las influencias causales intrínsecas, la atribución de anomalías y la atribución de cambio de distribución. Pero, ¿sabía que Dowhy también se puede usar para estimar los efectos promedio del tratamiento, el aprendizaje de la estructura causal, el diagnóstico de estructuras causales, intervenciones y contrafactuales? Si esto es interesante para usted, lo invitamos a visitar nuestra página de inicio de Pywhy o la documentación de Dowhy para obtener más información. También hay una comunidad activa en la discordia Dowhy donde los científicos y los practicantes de ML pueden reunirse, hacer preguntas y obtener ayuda. También organizamos reuniones semanales en Discord donde discutimos los desarrollos actuales. ¡Ven a nosotros!

 

No hay comentarios.:

Publicar un comentario

Entradas recientes

Thinkcspy 7.7 Condicionales encadenados

  7.7. Condicionales encadenados Python proporciona una forma alternativa de escribir una selección anidada, como la que se muestra en la s...

Entradas Populares