Deje de capacitarse a ciegas: utilice PSI para crear un canal de monitoreo más inteligente

limpió los datos, realizó algunas transformaciones, los modeló y luego implementó su modelo para que lo utilice el cliente.

Eso es mucho trabajo para un científico de datos. Pero el trabajo no se completa una vez que el modelo llega al mundo real.

Todo se ve perfecto en tu tablero. Pero bajo el capó, algo anda mal. La mayoría de los modelos no fallan estrepitosamente. No “fallan” como una aplicación con errores. En cambio, simplemente… se desvían.

Recuerde, aún debe monitorearlo para asegurarse de que los resultados sean precisos.

Una de las formas más sencillas de hacerlo es comprobar si los datos se están desviando.

En otras palabras, medirá si la distribución de los nuevos datos que llegan a su modelo es similar a la distribución de los datos utilizados para entrenarlo.

Por qué las modelos no gritan

Cuando implementas un modelo, estás apostando a que el futuro se parece al pasado. Se espera que los nuevos datos tengan patrones similares en comparación con los datos utilizados para entrenarlos.

Pensemos en eso por un minuto: si entrené a mi modelo para reconocer manzanas y naranjas, ¿qué pasaría si de repente todo lo que mi modelo recibe son piñas?

Sí, los datos del mundo real son confusos. Cambios en el comportamiento del usuario. Se producen cambios económicos. Incluso un pequeño cambio en su canal de datos puede estropear las cosas.

Si espera a que disminuyan métricas como la precisión o el RMSE, ya está atrasado. ¿Por qué? Porque las etiquetas suelen tardar semanas o meses en llegar. Necesitas una forma de solucionar los problemas antes de que el daño esté hecho.

PSI: El detector de humo de datos

El Índice de Estabilidad de la Población (PSI) es una herramienta clásica. Nació en el mundo del riesgo crediticio para monitorear los modelos de préstamo.

El índice de estabilidad poblacional (PSI) es una medida estadística con base en la teoría de la información que cuantifica la diferencia entre una distribución de probabilidad y una distribución de probabilidad de referencia.

[1]

No le importa la precisión de su modelo. Solo le importa una cosa: ¿los datos que llegan hoy son diferentes de los datos utilizados durante el entrenamiento?

Esta métrica es una forma de cuantificar cuánta “masa” se movió entre depósitos. Si tus datos de entrenamiento tenían un 10% de usuarios en un determinado grupo de edad, pero la producción tiene un 30%, PSI lo marcará.

Interpretarlo: lo que te dicen los números

Normalmente seguimos estos umbrales como regla general:

PSI <0,10: Todo está bien. Tus datos son estables. 0,10 ≤ PSI < 0,25: algo está cambiando. Probablemente deberías investigar. PSI ≥ 0,25: cambio importante. Es posible que su modelo esté haciendo malas conjeturas.

Código

El script Python de este ejercicio realizará los siguientes pasos.

Divida los datos en “cubos” (cuantiles). Calcula el porcentaje de datos en cada depósito tanto para su conjunto de entrenamiento como para su conjunto de producción. Luego, la fórmula compara estos porcentajes. Si son casi idénticos, el PSI se mantiene cerca de cero. Cuanto más divergen, más sube la puntuación.

Aquí está el código para la función de cálculo de PSI.

def psi(ref, new, bins=10): # Datos a la matriz ref, new = np.array(ref), np.array(new) # Genera 10 depósitos iguales entre 0% y 100% cuantiles = np.linspace(0, 1, bins + 1) breakpoints = np.quantile(ref, quantiles) # Contando el número de muestras en cada depósito ref_counts = np.histograma (ref, puntos de interrupción)[0]
new_counts = np.histogram(nuevo, puntos de interrupción)[0]

# Calcular el porcentaje ref_pct = ref_counts / len(ref) new_pct = new_counts / len(new) # Si algún depósito es cero, agregue un número muy pequeño # para evitar la división por cero ref_pct = np.where(ref_pct == 0, 1e-6, ref_pct) new_pct = np.where(new_pct == 0, 1e-6, new_pct) # Calcular PSI y devolver return np.sum((ref_pct – new_pct) * np.log(ref_pct / new_pct))

Es rápido, económico y no requiere etiquetas “verdaderas” para funcionar, lo que significa que no es necesario esperar algunas semanas para tener suficientes predicciones para calcular métricas como RMSE. Por eso es uno de los favoritos de la producción.

PSI verifica si los datos actuales de su modelo han cambiado demasiado en comparación con los datos utilizados para construirlo. Comparar los datos actuales con una línea de base ayuda a garantizar que su modelo permanezca estable y confiable.

Donde brilla PSI

PSI es excelente porque es fácil de automatizar. Puede ejecutarlo diariamente en cada función.

Donde no es así

Puede ser sensible a cómo eliges tus cubos. No le dice por qué cambiaron los datos, solo que así fue. Examina las características una por una. Podría pasar por alto interacciones sutiles entre múltiples variables.

Cómo lo usan los equipos profesionales

Los equipos maduros no se fijan únicamente en un único valor de PSI. Realizan un seguimiento de la tendencia a lo largo del tiempo.

Un solo pico podría ser un problema técnico. Un avance constante hacia arriba es una señal de que es hora de volver a entrenar su modelo. Combine PSI con otras métricas, como un buen resumen de estadísticas (media, varianza) para obtener una imagen completa.

Veamos rápidamente este juguete de ejemplo de datos que se desviaron. Primero, generamos algunos datos aleatorios.

importar numpy como np importar pandas como pd desde sklearn.linear_model importar LinearRegression desde sklearn.datasets importar make_regression # 1. Generar datos de referencia # np.random.seed(42) X,y = make_regression(n_samples=1000, n_features=3, noise=5, random_state=42) df = pd.DataFrame(X, columnas= [‘var1’, ‘var2’, ‘var3’]) df[‘y’] = y # Separar X e y X_ref, y_ref = df.drop(‘y’, axis=1), df.y # Ver el encabezado de datos df.head()

Datos de referencia generados para un modelo de regresión. Imagen del autor.

Luego, entrenamos el modelo.

# 2. Entrenar modelo de regresión modelo = LinearRegression().fit(X_ref, y_ref)

Ahora, generemos algunos datos desviados.

# Generar los datos de deriva X,y = make_regression(n_samples=500, n_features=3, noise=5, random_state=42) df2 = pd.DataFrame(X, columns= [‘var1’, ‘var2’, ‘var3’]) df2[‘y’] = y # Suma la deriva df2[‘var1’] = 5 + 1.5 * X_ref.var1 + np.random.normal(0, 5, 1000) # Separar X e y X_new, y_new = df2.drop(‘y’, axis=1), df2.y # Ver df2.head()

A continuación, podemos usar nuestra función para calcular el PSI. Deberías notar la enorme variación en PSI para la variable 1.

# 4. Calcule PSI para la característica de deriva para v en df.columns[:-1]: valor_psi= psi(X_ref[v]X_nuevo[v]) print(f”Puntuación PSI para la característica {v}: {psi_value:.4f}”) Puntuación PSI para la característica var1: 2,3016 Puntuación PSI para la característica var2: 0,0546 Puntuación PSI para la característica var3: 0,1078

Y, finalmente, comprobemos el impacto que tiene en la y estimada.

# 5. Genere estimaciones para ver el impacto preds_ref = model.predict(X_ref[:5]) preds_drift = modelo.predict(X_nuevo[:5]) print(“\nPredicciones de muestra (referencia versus deriva):”) print(f”Preds de referencia: {preds_ref.round(2)}”) print(f”Predicciones de deriva: {preds_drift.round(2)}”) Predicciones de muestra (referencia versus deriva): Preds de referencia: [-104.22 -57.58 -32.69 -18.24 24.13]
Previsiones de deriva: [ 508.33 621.61 -241.88 13.19 433.27]

También podemos visualizar las diferencias por variable. Creamos una función simple para trazar los histogramas superpuestos.

def drift_plot(ref, nuevo): fig = plt.hist(ref) fig = plt.hist(nuevo, color=’r’, alpha=.5); return plt.show(fig) # Calcular PSI para la característica de deriva para v en df.columns[:-1]: valor_psi= psi(X_ref[v]X_nuevo[v]) print(f”Puntuación PSI para la característica {v}: {psi_value:.4f}”) drift_plot(X_ref[v]X_nuevo[v])

Aquí están los resultados.

Deriva de datos para las 3 variables. Imagen del autor.

¡La diferencia es enorme para la variable 1!

Antes de ir

Vimos lo sencillo que es calcular el PSI y cómo puede mostrarnos dónde se está produciendo la deriva. Rápidamente identificamos var1 como nuestra variable problemática. Monitorear su modelo sin monitorear sus datos es un gran punto ciego.

Tenemos que asegurarnos de que la misma distribución de datos identificada cuando se entrenó el modelo siga siendo válida, de modo que el modelo pueda seguir usando el patrón de los datos de referencia para estimar datos nuevos.

Production ML se trata menos de construir el modelo “perfecto” y más de mantener la alineación con la realidad.

Los mejores modelos no sólo predicen bien. Saben cuándo el mundo ha cambiado.

Si te gustó este contenido, búscame en mi sitio web.
https://gustavorsantos.me

Repositorio GitHub

El código para este ejercicio.

https://github.com/gurezende/Studying/blob/master/Python/statistics/data_drift/Data_Drift.ipynb

Referencias

[1. PSI Definition] https://arize.com/blog-course/population-stability-index-psi/

[2. Numpy Histogram] https://numpy.org/doc/2.2/reference/generated/numpy.histogram.html

[3. Numpy Linspace] https://numpy.org/devdocs/reference/generated/numpy.linspace.html

[4. Numpy Where] https://numpy.org/devdocs/reference/generated/numpy.where.html

[5. Make Regression data] https://scikit-learn.org/stable/modules/generated/sklearn.datasets.make_regression.html