Machine learning desde cero · Lección 2.6 · 13 de 33 lecciones listas · 12 min
Métrica y umbral según el coste de los errores
En pocas palabras
El umbral se elige por el precio de los errores, no por hábito. Si un fallo cuesta 10 veces más que una falsa alarma, el umbral más barato está cerca de 0,09.
Calentamiento Dos preguntas de lecciones anteriores. Un minuto, y no bloquea la lección.
En la lección 2.3 las curvas mostraron un menú de umbrales, y en la lección 2.4 comprobaste cuándo los números del modelo son porcentajes reales. Ahora elegirás un umbral de ese menú. No por costumbre (0,5) ni por una métrica favorita, sino por lo que cuesta de verdad cada error.
Elige una respuesta y tu grado de seguridad.
Responde para desbloquear el experimento.
Experimento interactivo
Este experimento interactivo funciona en un navegador con JavaScript activado. El texto que lo rodea describe lo que muestra.
Ver la respuesta
Respuesta correcta: Más cerca de 0,1, porque la alarma ya compensa con un riesgo pequeño
Teoría de la decisión: la alarma compensa cuando p · 10 > (1 − p) · 1, es decir, p > 1/11 ≈ 0,09. En el lab el umbral 0,09 cuesta 125 y el habitual 0,5 llega a 254. El umbral más barato en validación, 0,06, cuesta 111, pero solo en las mismas puntuaciones con las que se eligió.
Prueba
- Deja los precios en 10 y 1 y baja el umbral desde 0,5. ¿Dónde es más bajo el coste? ¿Cuántos fallos y cuántas falsas alarmas hay entonces?
- Pon los dos costes a 1. ¿Dónde está ahora el umbral más barato? Compáralo con el umbral de mejor F1.
- Haz que una falsa alarma cueste más que un fallo. ¿A qué lado de 0,5 cae el umbral más barato?
- Vuelve a los precios 10 y 1 y compara tres costes: el del umbral más barato, el de la prueba honesta y el del umbral de la teoría. ¿Qué elección es la más barata en biopsias que no se usaron para hacerla?
Cuando lo hayas comprobado en el lab, pongamos nombre a lo que ves.
La idea en palabras sencillas
Cada error tiene un precio. Un tumor maligno no detectado (FN) es una enfermedad descubierta tarde. Una falsa alarma (FP) es una biopsia innecesaria y estrés. Cuando conoces los precios, el coste de un umbral es una simple suma: fallos por el precio de un fallo más falsas alarmas por el precio de una alarma. El mejor umbral es el de la suma más pequeña en los datos de validación.
Con precios 10 y 1, el umbral 0,5 da 24 fallos y 14 falsas alarmas: coste 254. El umbral más barato en validación es 0,06: 2 fallos y 91 alarmas, coste 111. Pero esa cifra es optimista, porque el umbral se eligió y se valoró con las mismas puntuaciones (más en «Por qué funciona»). Para comparar, una biopsia para todas cuesta 357, y ninguna biopsia, 2120.
Si el modelo está calibrado, el umbral también se puede calcular sin buscarlo. Una biopsia tiene una probabilidad de malignidad p. Una alarma cuesta entonces de media (1 − p) · 1, y no dar la alarma, p · 10. La alarma compensa cuando p · 10 > (1 − p) · 1, es decir, cuando p > 1/11 ≈ 0,09. En general, el umbral es c_FP / (c_FP + c_FN). Es un resultado de la teoría de la decisión, no una medición: supone que los números del modelo son porcentajes reales (lección 2.4). Este modelo está bien calibrado (ECE 0,010). En el lab el umbral 0,09 cuesta 125, menos de la mitad que el umbral 0,5, y nadie lo ajustó con estos datos.
Jak to policzono
- Biopsias: Breast Cancer Wisconsin (Diagnostic), UCI, licencia CC BY 4.0. 569 biopsias (212 malignas, 357 benignas), 10 medidas «mean» de cada una.
- Puntuaciones de validación cruzada en 5 partes (
StratifiedKFold(5)en scikit-learn): cada biopsia la puntúa un modelo que nunca la vio. - Modelo: estandarización y regresión logística (C = 1). Umbrales de 0,01 a 0,99 en pasos de 0,01.
- Precios de los errores: un fallo 10, una falsa alarma 1. Es un ejemplo, no una valoración médica.
Por qué funciona
El lab y la teoría casi coinciden: el umbral más barato sale 0,06 y la teoría dice 0,09. La diferencia viene de que 569 biopsias son pocas, mientras que un fallo pesa como 10 alarmas, así que la curva de coste da saltos. Su fondo es plano y dentado: el umbral 0,13 cuesta lo mismo que 0,06 (111), y 0,09 cuesta 125. En otros 20 cortes en partes (código abajo) el umbral más barato cae entre 0,04 y 0,13, de media 0,08. La teoría acierta en el centro de ese intervalo, y el lab muestra lo ancho que es el fondo.
Pero el umbral más barato tiene trampa. El lab prueba 99 umbrales y elige el que mejor salió en estas 569 biopsias, en parte gracias a aciertos de suerte. Así que el coste 111 es optimista: es la misma maldición del ganador que en el ajuste (lección 3.5). Una prueba honesta: elige el umbral en 4/5 de las biopsias y calcula su coste en el 1/5 restante, cinco veces. Un umbral elegido así cuesta 141, más que el umbral de la teoría 0,09 (125), que nadie ajustó. En otros 20 cortes el coste honesto del umbral elegido va de 106 a 153 (de media 129), mientras que el umbral de la teoría cuesta de 105 a 136 (de media 117) y es más barato en 16 de 20. Conclusión: con un modelo calibrado, el umbral de la teoría es un punto de partida sólido y barato, y ajustar el umbral con los mismos datos exagera el ahorro.
La dirección es siempre la misma: cuanto más caro el fallo, más bajo el umbral, y cuanto más cara la falsa alarma, más alto. Con precios iguales, el umbral más barato es 0,65 (coste 33). Cuando la alarma cuesta más que el fallo, el umbral más barato cae por encima de 0,5.
Error frecuente
¿Verdadero o falso?: «F1 es una buena métrica para todo». Falso. F1 = 2·TP / (2·TP + FN + FP), así que F1 pesa igual un fallo y una falsa alarma, aunque sus precios sean distintos. En el lab el umbral de mejor F1 es 0,65 (F1 0,918). Con precios 10 y 1 cuesta 276: más que el habitual 0,5 (254) y casi 2,5 veces el umbral más barato (111). En otros 20 cortes el umbral de mejor F1 cuesta de 1,6 a 2,9 veces el más barato.
Ni siquiera con precios iguales F1 es lo mismo que el coste. En el lab, con precios 1 y 1, el umbral más barato cae justo donde F1 es mejor (0,65), pero no es una regla. El coste con precios iguales es simplemente el número de errores, mientras que F1 es una fracción en la que los «no» acertados (TN) no cuentan en absoluto. En otros 20 cortes los dos umbrales difieren en 3.
Si conoces los precios de los errores, calcula el coste. Si no los conoces, pregúntalos antes de elegir una métrica: elegir una métrica también es decidir unos precios, solo que sin decirlo.
Test
Tres preguntas para comprobar lo aprendido. Elige una respuesta o despliega la solución bajo cada pregunta. Con el teclado: las flechas eligen, Enter o Espacio confirma.
Ideas clave
- El umbral se elige por los precios de los errores: el coste son los fallos por su precio más las falsas alarmas por el suyo, calculado en validación.
- Para un modelo calibrado, la teoría da el umbral c_FP / (c_FP + c_FN); con precios 10 y 1 es cerca de 0,09. Es un punto de partida sólido: un umbral ajustado con los mismos datos parece más barato de lo que es.
- Los fallos más caros bajan el umbral, las falsas alarmas más caras lo suben.
- F1 pesa igual los dos errores e ignora los «no» acertados; si conoces los precios, calcula el coste.
Más a fondo: fórmula, código, práctica
Las matemáticas
Coste de un umbral t: K(t) = c_FN · FN(t) + c_FP · FP(t). El umbral más barato en validación es t = argmin K(t). Su coste K(t) calculado con los mismos datos es optimista; el coste honesto se calcula con datos que no se usaron para elegir t*.
Una biopsia tiene una probabilidad de malignidad p. Una alarma cuesta de media (1 − p) · c_FP, y no darla, p · c_FN. La alarma compensa cuando p · c_FN > (1 − p) · c_FP, es decir, p > c_FP / (c_FP + c_FN). Para c_FN = 10 y c_FP = 1 es 1 / 11 ≈ 0,09.
F1 = 2·TP / (2·TP + FN + FP): FN y FP tienen el mismo peso 1 en el denominador.
En código (Python)
El mismo experimento en scikit-learn: puntuaciones de validación cruzada, el coste de cada umbral de 0,01 a 0,99, el coste honesto del umbral elegido y luego lo mismo en otros 20 cortes en partes.
import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import StratifiedKFold, cross_val_predict
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import f1_score
X, y = load_breast_cancer(return_X_y=True)
X, y = X[:, :10], 1 - y # las 10 medidas "mean", como en el lab; 1 = maligno
model = make_pipeline(StandardScaler(), LogisticRegression())
t = np.arange(1, 100) / 100 # umbrales 0.01 ... 0.99, como en el lab
def costs(p, i=slice(None), c_fn=10, c_fp=1): # un fallo cuesta 10, una falsa alarma 1; i = qué biopsias
return np.array([c_fn * ((p[i] < s) & (y[i] == 1)).sum() + c_fp * ((p[i] >= s) & (y[i] == 0)).sum() for s in t])
def scores(cv): # cada biopsia la puntúa un modelo que nunca la vio
return cross_val_predict(model, X, y, cv=cv, method="predict_proba")[:, 1]
def held_out(p, cv): # el umbral más barato elegido en 4/5 de las biopsias, coste en el 1/5 restante, cinco veces
return sum(costs(p, b)[costs(p, a).argmin()] for a, b in cv.split(X, y))
p = scores(StratifiedKFold(5))
c, f1 = costs(p), np.array([f1_score(y, p >= s) for s in t])
print(f"cheapest threshold {t[c.argmin()]:.2f} (cost {c.min()}); theory 1/11 = {1 / 11:.2f} (cost {c[8]}); 0.5 costs {c[49]}; best F1 at {t[f1.argmax()]:.2f} costs {c[f1.argmax()]}")
print(f"picked on 4/5, priced on the other 1/5: {held_out(p, StratifiedKFold(5))}; theory 1/11: {c[8]}")
r = []
for s in range(20): # otros 20 cortes en 5 partes
cv = StratifiedKFold(5, shuffle=True, random_state=s)
q = scores(cv)
cq, fq = costs(q), np.array([f1_score(y, q >= u) for u in t])
r.append((t[cq.argmin()], cq[fq.argmax()] / cq.min(), cq[49] / cq.min(), held_out(q, cv), cq[8], costs(q, c_fn=1).argmin() != fq.argmax()))
r = np.array(r)
print(f"20 other cuts: cheapest threshold {r[:, 0].min():.2f} to {r[:, 0].max():.2f} (mean {r[:, 0].mean():.2f}); best F1 costs {r[:, 1].min():.1f} to {r[:, 1].max():.1f} times the cheapest, 0.5 costs {r[:, 2].min():.1f} to {r[:, 2].max():.1f} times")
print(f"20 other cuts, held out: the picked threshold costs {r[:, 3].min():.0f} to {r[:, 3].max():.0f} (mean {r[:, 3].mean():.0f}), theory 1/11 costs {r[:, 4].min():.0f} to {r[:, 4].max():.0f} (mean {r[:, 4].mean():.0f}); theory is cheaper in {(r[:, 4] < r[:, 3]).sum():.0f} of 20; at equal prices the cheapest and the best-F1 threshold differ in {r[:, 5].sum():.0f} of 20")
Resultado
cheapest threshold 0.06 (cost 111); theory 1/11 = 0.09 (cost 125); 0.5 costs 254; best F1 at 0.65 costs 276
picked on 4/5, priced on the other 1/5: 141; theory 1/11: 125
20 other cuts: cheapest threshold 0.04 to 0.13 (mean 0.08); best F1 costs 1.6 to 2.9 times the cheapest, 0.5 costs 2.0 to 2.5 times
20 other cuts, held out: the picked threshold costs 106 to 153 (mean 129), theory 1/11 costs 105 to 136 (mean 117); theory is cheaper in 16 of 20; at equal prices the cheapest and the best-F1 threshold differ in 3 of 20
Con el corte StratifiedKFold(5) los números son los del lab: el umbral más barato 0,06 (coste 111), la teoría 0,09 (125), el umbral 0,5 cuesta 254 y el de mejor F1, 276. En otros 20 cortes el umbral más barato cae entre 0,04 y 0,13, de media 0,08, y el habitual 0,5 cuesta de 2,0 a 2,5 veces el más barato. El umbral elegido en 4/5 de las biopsias y valorado en el 1/5 restante cuesta 141, como en el lab. En otros 20 cortes esa elección cuesta de 106 a 153 (de media 129), el umbral de la teoría de 105 a 136 (de media 117), y la teoría es más barata en 16 de 20. Con precios iguales, el umbral más barato y el de mejor F1 difieren en 3 de 20 cortes.
Descargar el notebook (.ipynb). Ábrelo en Jupyter o súbelo a Google Colab; descarga por sí solo los datos que falten.
Para profesionales
- Fija los precios de los errores con quienes sufren sus consecuencias (un médico, un equipo de riesgos) antes de ver los resultados del modelo. Si no, es fácil elegir precios que encajen con un umbral que ya te gusta.
- En scikit-learn,
TunedThresholdClassifierCVcon tu propioscoring(por ejemplo, conmake_scorer) ajusta el umbral a un coste. Un umbral se aplica a mano así:predict_proba(X)[:, 1] >= t. - Ajusta el umbral en validación y comprueba su coste con datos que no usaste para elegirlo (el test o una parte apartada, como en el lab). Da el coste junto a dos referencias sencillas: «todas a biopsia» y «ninguna».
- Usa la fórmula c_FP / (c_FP + c_FN) solo con un modelo calibrado (lección 2.4). Si el modelo se confía demasiado, busca el umbral en la curva de coste.
¿Te ha sido útil?
¡Gracias! Nos ayuda a mejorar.
Profundiza en el Atlas
Entradas de la enciclopedia sobre las ideas de esta lección: