Cree métricas efectivas para describir a los usuarios | de Vladimir Zhyvov | enero 2025

Cree métricas efectivas para describir a los usuarios | de Vladimir Zhyvov | enero 2025

Imagine que es una plataforma de comercio electrónico que desea personalizar sus campañas de correo electrónico en función de la actividad de los usuarios de la última semana. Si un usuario ha estado menos activo en comparación con las semanas anteriores, considera enviarle una oferta de descuento.

Recopiló estadísticas de usuario y notó lo siguiente para un usuario llamado John:

  • John visitó la plataforma por primera vez hace 15 días.
  • Durante los primeros 7 días (días 1-7), realizó 9 visitas.
  • Durante los siguientes 7 días (días 2 a 8), realizó 8 visitas.
  • En total tenemos 9 valores.

Ahora desea evaluar qué tan extremo es el valor más reciente en comparación con los anteriores.

import numpy as np
visits = np.array([9, 8, 6, 5, 8, 6, 8, 7])
num_visits_last_week = 6

Creemos un CDF de estos valores.

import numpy as np
import matplotlib.pyplot as plt

values = np.array(sorted(set(visits)))
counts = np.array([data.count(x) for x in values])
probabilities = counts / counts.sum()
cdf = np.cumsum(probabilities)

plt.scatter(values, cdf, color='black', linewidth=10)

CDF, imagen del autor

Ahora necesitamos restaurar la función en función de estos valores. Usaremos interpolación spline.

from scipy.interpolate import make_interp_spline

x_new = np.linspace(values.min(), values.max(), 300)
spline = make_interp_spline(values, cdf, k=3)
cdf_smooth = spline(x_new)

plt.plot(x_new, cdf_smooth, label='Сплайн CDF', color='black', linewidth=4)
plt.scatter(values, cdf, color='black', linewidth=10)
plt.scatter(values[-2:], cdf[-2:], color='#f95d5f', linewidth=10, zorder=5)
plt.show()

CDF con interpolación spline, imagen del autor

Nada mal. Pero observamos un pequeño problema entre los puntos rojos: el CDF debe aumentar de forma monótona. Arreglemos este problema con el polinomio de interpolación cúbica de Hermite por partes.

from scipy.interpolate import PchipInterpolator

spline_monotonic = PchipInterpolator(values, cdf)
cdf_smooth = spline_monotonic(x_new)

plt.plot(x_new, cdf_smooth, color='black', linewidth=4)
plt.scatter(values, cdf, color='black', linewidth=10)
plt.show()

CDF con interpolación cúbica de Hermite por partes, imagen del autor

Muy bien, ahora es perfecto.

Para calcular el valor p de nuestra observación actual (6 visitas en la última semana), necesitamos calcular el área del área llena.

Zona crítica, imagen del autor.

Para hacer esto, creemos una función simple. calcular_p_valor:

def calculate_p_value(x):
if x < values.min():
return 0
elif x > values.max():
return 1
else:
return spline_monotonic(x)

p_value = calculate_p_value(num_visits_last_week)
print(f"Probability of getting less than {num_visits_last_week} equals: {p_value}")

La probabilidad de obtener menos de 6 es igual a: 0,375

Por tanto, la probabilidad es bastante alta (podemos compararla con un umbral de 0,1, por ejemplo) y decidimos no enviar el descuento a John. El mismo cálculo tenemos que hacer para todos los usuarios.