ML Atlas

Machine learning desde cero · Lección 2.5 · 12 de 33 lecciones listas · 12 min

Clases desequilibradas

En pocas palabras

Si una clase es rara, la exactitud esconde las pérdidas y el modelo aprende a decir «la clase común». Sensibilidad, exactitud equilibrada y pesos lo corrigen.

Calentamiento Dos preguntas de lecciones anteriores. Un minuto, y no bloquea la lección.
De la lección 2.4: Calibración: ¿0,8 significa 80 %? Naive Bayes tiene un ROC AUC de 0,966, pero declara un 98,3 % con una exactitud del 88,3 %. ¿Qué se deduce?

Ver la respuesta

Respuesta correcta: Que ordena bien las biopsias, pero sus porcentajes están inflados

El ROC AUC mide el orden, la calibración los porcentajes. Son cosas distintas: la temperatura arregla los porcentajes de naive Bayes y el ROC AUC sigue en 0,966.

De la lección 2.3: Umbral, ROC y PR: todos los umbrales a la vez ¿Cuándo dice más la curva PR que la curva ROC?

Ver la respuesta

Respuesta correcta: Cuando la clase positiva es rara y lo que importa es cuántas alarmas aciertan

Con una clase rara la curva ROC se ve igual mientras la precisión cae. En el lab con 19 malignas el AP baja a 0,137 de media, aunque el ROC AUC casi no se mueve.

En la lección 1.3, «siempre benigno» tenía una exactitud alta y no detectaba a nadie. Allí la clase rara solo estaba en el test. Hoy es rara en los datos de aprendizaje, como en el cribado real, el fraude o las averías. Verás qué le hace eso al modelo, cómo medirlo y qué se puede arreglar sin datos nuevos.

Predice y comprueba Una regresión logística aprende de biopsias. En los datos de aprendizaje se quedan todas las benignas, pero solo 8 malignas en lugar de 159. En la misma parte de validación (apartada para comprobar el modelo, no para aprender), ¿qué cae más: la exactitud o la sensibilidad?
¿Qué tan seguro estás?

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: La sensibilidad, más de 20 puntos, y la exactitud solo unos 6 puntos

La sensibilidad cae del 83,0 % al 61,5 % (media de 5 sorteos de qué malignas se quedan), y la exactitud solo del 91,5 % al 85,6 %. En validación 89 de las 142 biopsias son benignas, y el modelo las reconoce cada vez con más seguridad, así que la exactitud apenas ve la pérdida.

Prueba esto

  • Sin pesos, mueve el control de 159 a 8 malignas. ¿Qué línea cae más rápido: la sensibilidad o la exactitud?
  • Con 8 malignas, activa los pesos de clase. ¿Cuánta sensibilidad vuelve y cuánta falta todavía frente a todos los datos?
  • Mira la P(maligno) media predicha. ¿Cómo cambia cuando desaparecen malignas?

Cuando lo hayas comprobado en el lab, pongamos nombre a lo que ves.

La idea en pocas palabras

Las clases están desequilibradas cuando una es mucho más rara que la otra. El modelo aprende entonces dos cosas a la vez: cómo son las biopsias malignas y lo raras que son. Esa segunda lección funciona como un prejuicio: cuando las medidas no son claras, el modelo elige «benigno» cada vez más. La P(maligno) media predicha baja de 0,36 a 0,24 cuando quedan 8 malignas en el aprendizaje en lugar de 159.

La exactitud apenas lo ve. La sensibilidad cae del 83,0 % al 61,5 %, la exactitud solo del 91,5 % al 85,6 %. Por eso, con una clase rara, se informa de la sensibilidad de la clase rara o de la exactitud equilibrada, la media de las sensibilidades de las dos clases. «Siempre benigno» tiene una exactitud equilibrada de 0,5, sean cuales sean las proporciones.

La primera corrección es sencilla: los pesos de clase. Un error en la clase rara cuesta en el aprendizaje tantas veces más como veces es más rara esa clase (class_weight='balanced'). Con 8 malignas, los pesos suben la sensibilidad del 61,5 % al 80,0 %, y la exactitud incluso sube, al 91,4 %. Frente a todos los datos con pesos (86,8 %) todavía falta algo: los pesos cambian las proporciones, no añaden ejemplos.

Jak to policzono
  • Biopsias: Breast Cancer Wisconsin (Diagnostic), UCI, licencia CC BY 4.0. 569 biopsias, 10 medidas «mean».
  • Parte de validación: 25 % de las biopsias, estratificada (142: 53 malignas, 89 benignas), la misma en todos los ajustes. En el aprendizaje, 268 benignas y de 159 a 8 malignas; por debajo de 159 es la media de 5 sorteos de qué malignas se quedan.
  • Modelo: estandarización con los datos de aprendizaje y regresión logística (C = 1), con o sin pesos de clase; umbral 0,5.

Por qué funciona

La regresión logística busca el modelo que menos se equivoca de media en los datos de aprendizaje. Con 268 benignas y 8 malignas, las malignas son solo el 2,9 % de la penalización total. El modelo mueve la frontera hacia el lado maligno: renuncia a unas cuantas malignas para fallar menos benignas. Los pesos de clase igualan la penalización: las 8 malignas juntas pesan lo mismo que las 268 benignas.

Una partición podría salir así por casualidad. En el código de abajo, el mismo experimento se repite con 50 particiones distintas: la sensibilidad cae de media del 89,3 % al 67,3 %, la exactitud del 93,5 % al 87,7 %, y los pesos con 8 malignas dan un 84,0 %. La sensibilidad cae más que la exactitud en 50 particiones de 50, y los pesos la suben en todas ellas.

La exactitud puede incluso subir sin que el modelo cambie nada. En el widget del Atlas sobre la exactitud equilibrada, un modelo débil con dos medidas puntúa las mismas biopsias mientras las malignas pasan de 212 a 20. Su exactitud sube del 75,9 % al 83,8 %, y la exactitud equilibrada no se mueve: 0,728 y 0,726. «Siempre benigno» con 20 malignas llega al 94,7 % de exactitud.

Error frecuente

Verdadero o falso: «SMOTE siempre ayuda». Falso. SMOTE fabrica ejemplos sintéticos de la clase rara en los segmentos entre ejemplos reales y sus vecinos más cercanos, hasta que las dos clases tienen el mismo tamaño. Eso mueve la frontera de decisión igual que los pesos de clase: el modelo dice «maligno» más a menudo. En el widget del Atlas sobre SMOTE (357 benignas, 30 malignas, dos medidas, validación cruzada 5 × 5), el modelo sin corrección detecta el 60,0 % de las malignas con una precisión del 90,0 %. SMOTE sube la detección al 86,7 %, pero la precisión cae al 42,9 %. Los pesos de clase dan la misma sensibilidad con una precisión del 40,2 %, y la simple duplicación con el 39,6 %. Es un sorteo de 30 malignas, el de mayor caída: de media en 20 sorteos la detección sube del 68,7 % al 91,9 % y la precisión cae del 91,0 % al 54,7 %. Cae en todos ellos. SMOTE no añade conocimiento, solo cambia las proporciones. Que eso ayude depende del coste de los errores: más detecciones a cambio de muchas falsas alarmas.

Un aviso: la corrección se aplica solo a los datos de aprendizaje. Ejemplos sintéticos o duplicados en la validación o el test darían un resultado que no significa nada.

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.

1. Quedan 8 biopsias malignas en el aprendizaje en lugar de 159. ¿Por qué la exactitud apenas lo muestra?
Ver la respuesta

Respuesta correcta: Porque en validación hay más benignas, y el modelo las reconoce cada vez con más seguridad

En validación 89 de las 142 biopsias son benignas. La sensibilidad cae del 83,0 % al 61,5 %, la exactitud solo del 91,5 % al 85,6 %.

2. ¿Qué mide la exactitud equilibrada?
Ver la respuesta

Respuesta correcta: La media de las sensibilidades de ambas clases, así «siempre la común» saca 0,5

Cada clase cuenta lo mismo, sea cual sea su tamaño. El modelo débil del widget tiene una exactitud equilibrada de 0,728 con 212 malignas y de 0,726 con 20, aunque su exactitud sube del 75,9 % al 83,8 %.

3. Con 8 malignas en el aprendizaje, los pesos de clase suben la sensibilidad del 61,5 % al 80,0 %. ¿Qué no hacen?
Ver la respuesta

Respuesta correcta: No añaden ejemplos nuevos, así que todavía falta algo frente a todos los datos

Los pesos solo cambian cuánto cuesta un error en cada clase. Todos los datos con pesos dan una sensibilidad del 86,8 %, así que con 8 malignas faltan 6,8 puntos.

Ideas clave

  • Cuando una clase es rara, la exactitud esconde las pérdidas: informa de la sensibilidad de la clase rara o de la exactitud equilibrada.
  • El modelo también aprende las proporciones de las clases; con una clase rara en el aprendizaje elige la clase común cada vez más.
  • Los pesos de clase y SMOTE mueven la frontera: más detecciones a cambio de falsas alarmas, sin conocimiento nuevo.
  • Aplica las correcciones solo a los datos de aprendizaje y comprueba el resultado en una validación intacta, mejor con muchas particiones.

Más a fondo: fórmula, código, práctica

Las matemáticas

Exactitud = (TP + TN) / n, sensibilidad = TP / (TP + FN), especificidad = TN / (TN + FP), exactitud equilibrada = (sensibilidad + especificidad) / 2. «Siempre benigno» tiene sensibilidad 0 y especificidad 1, así que una exactitud equilibrada de (0 + 1) / 2 = 0,5.

La regresión logística minimiza la pérdida logística media L = Σᵢ wᵢ · ℓ(yᵢ, pᵢ) / Σᵢ wᵢ. Sin pesos wᵢ = 1, así que las 8 malignas son 8 / 276 ≈ 2,9 % de la pérdida total. Los pesos «balanced» son w = n / (2 · n_clase): 276 / 16 = 17,25 para una maligna y 276 / 536 ≈ 0,51 para una benigna, así que cada clase pesa en total n / 2 = 138.

En código (Python)

El mismo experimento en scikit-learn con 50 particiones distintas: todas las benignas y 159 u 8 malignas en el aprendizaje, con y sin pesos de clase, evaluado en la parte de validación intacta.

import numpy as np
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import recall_score, accuracy_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
def run(seed, m, weights):
    tr, va = train_test_split(np.arange(len(y)), test_size=0.25, stratify=y, random_state=seed)
    mal = np.random.default_rng(seed).choice(tr[y[tr] == 1], m, replace=False)
    keep = np.r_[tr[y[tr] == 0], mal]  # todas las benignas + m malignas para aprender
    clf = make_pipeline(StandardScaler(), LogisticRegression(class_weight="balanced" if weights else None))
    pred = clf.fit(X[keep], y[keep]).predict(X[va])  # la parte de validación no cambia
    return recall_score(y[va], pred), accuracy_score(y[va], pred)
for m, w in ((159, False), (8, False), (8, True)):
    rec, acc = np.mean([run(s, m, w) for s in range(50)], axis=0)
    print(f"{m} malignant{' + class weights' if w else ''}: recall {rec:.1%}, accuracy {acc:.1%} (mean of 50 splits)")
drop = np.array([np.subtract(run(s, 159, False), run(s, 8, False)) for s in range(50)])
gain = np.array([run(s, 8, True)[0] - run(s, 8, False)[0] for s in range(50)])
print(f"recall fell more than accuracy in {(drop[:, 0] > drop[:, 1]).sum()} of 50 splits; weights raised recall in {(gain > 0).sum()}")

Resultado

159 malignant: recall 89.3%, accuracy 93.5% (mean of 50 splits)
8 malignant: recall 67.3%, accuracy 87.7% (mean of 50 splits)
8 malignant + class weights: recall 84.0%, accuracy 91.0% (mean of 50 splits)
recall fell more than accuracy in 50 of 50 splits; weights raised recall in 50

El lab muestra una partición y 5 sorteos, el código 50 particiones, así que los números son distintos: en la partición del lab la sensibilidad con todos los datos es del 83,0 %, de media del 89,3 %. La conclusión es la misma en cada partición.

Para profesionales
  • En scikit-learn los pesos salen de class_weight="balanced" (regresión logística, SVM, árboles, bosques) y la exactitud equilibrada de balanced_accuracy_score. Informa también de la sensibilidad y la precisión de la clase rara.
  • Divide con estratificación (stratify=y, StratifiedKFold), para que la clase rara llegue a cada parte.
  • SMOTE y la duplicación están en la biblioteca imbalanced-learn. Úsalos dentro de su Pipeline, para que actúen solo en las partes de aprendizaje de la validación cruzada.
  • Los pesos de clase y un umbral más bajo hacen algo parecido: mueven la decisión hacia la clase rara. El umbral lo puedes elegir en validación con la curva PR (lección 2.3), sin volver a entrenar el modelo.

Profundiza en el Atlas

Entradas de la enciclopedia sobre las ideas de esta lección: