ML clásico · Fácil · 15 min

Encuentra la factura rara

Dos reglas que puedes explicar a tu gestoría antes de tocar un modelo: z-score e IQR. Verás por qué una sola errata esconde a otra.

AMOUNTS son los importes de 36 facturas de material de oficina (datos sintéticos, en EUR). Hay dos raras: una errata de 4250 por 425 y un pedido duplicado de 980. Escribe cinco funciones pequeñas:

zScores(xs): (x - media) / desviación, con la desviación dividida entre n. Si todos los valores son iguales, devuelve ceros.

quantile(sorted, p): recibe una lista ordenada. Calcula la posición (n - 1) * p e interpola entre los dos vecinos (es el método por defecto de NumPy).

iqrFences(xs): devuelve { q1, q3, iqr, low, high }, con low = q1 - 1.5 * iqr y high = q3 + 1.5 * iqr.

flagZ(xs, limit) y flagIQR(xs): los índices de las facturas marcadas, en orden. La vista previa pinta lo que marca cada regla y mueve el límite de z.

Retos 0/4

  • z-score con la desviación entre n, y ceros si no hay dispersión
  • Cuartiles con interpolación y vallas a 1,5 IQR
  • Con límite 3, el z-score solo ve la errata de 4250
  • El IQR marca la errata y el pedido duplicado

function zScores(xs) {
  // (x - media) / desviación, dividiendo entre n; todo ceros si todos los valores son iguales
  return xs.map(() => 0);
}

function quantile(sorted, p) {
  // posición (n - 1) * p y luego interpola entre los dos vecinos
  return sorted[0];
}

function iqrFences(xs) {
  // vallas: q1, q3, iqr = q3 - q1, low = q1 - 1,5 * iqr, high = q3 + 1,5 * iqr
  return { q1: 0, q3: 0, iqr: 0, low: 0, high: 0 };
}

function flagZ(xs, limit) {
  // índices cuyo |z| supera limit
  return [];
}

function flagIQR(xs) {
  // índices por debajo de low o por encima de high
  return [];
}

console.log('z:', flagZ(AMOUNTS, 3), 'IQR:', flagIQR(AMOUNTS));
La consola aparece aquí (console.log).

La idea

Antes de entrenar nada, prueba una regla que puedas explicar en una frase. «Esta factura está a más de tres desviaciones de la media» o «está por encima de la valla del IQR» se entienden en una revisión con tu gestoría, y eso vale más que un modelo que nadie sabe justificar.

El z-score tiene un fallo conocido: la media y la desviación se calculan con todos los datos, también con los raros. La errata de 4250 infla tanto la desviación que el pedido duplicado de 980 se queda con un z por debajo de 1 y pasa desapercibido. A eso se le llama enmascaramiento.

El IQR usa cuartiles, y a los cuartiles un valor extremo les mueve poco. Por eso marca las dos facturas. La idea de aislamiento va un paso más allá: corta el rango al azar hasta que la factura se queda sola. Una factura rara se aísla en pocos cortes. Es la base del Isolation Forest, y la vista previa la calcula con 100 árboles.

Ninguna regla decide por ti. Marcan qué revisar primero, y una persona confirma.

Hazlo en tu máquina

Con Python y pandas, sobre el CSV de este ejercicio (CC BY 4.0):

curl -O https://vorluxai.com/data/labs/invoices-office-supplies.csv
python3 -c "
import pandas as pd
df = pd.read_csv('invoices-office-supplies.csv')
q1, q3 = df.amount.quantile([0.25, 0.75])
high = q3 + 1.5 * (q3 - q1)
print(df[df.amount > high])
"

Comprueba lo que has entendido

1. ¿Por qué el z-score no marca la factura de 980?
2. ¿Qué tiene el IQR que no tiene el z-score?
3. En la idea de aislamiento, ¿qué indica que una factura es rara?
4. ¿Qué haces con una factura marcada?

Para profundizar: la referencia de scikit-learn (en inglés) →

¿Esto en producción, con tus datos? Hablemos 15 minutos →