Machine learning do zero · Aula 2.3 · 10 de 33 aulas prontas · 12 min
Limiar, ROC e PR: todos os limiares de uma vez
Em resumo
As curvas ROC e PR mostram todos os limiares de uma vez. Com uma classe rara, o ROC AUC quase não muda e o AP cai: os alarmes falsos comem a precisão.
Aquecimento Duas perguntas de aulas anteriores. Um minuto, e a aula nunca fica bloqueada.
Na aula 2.2 você movia um limiar e via a matriz de confusão mudar. Cada limiar é uma decisão diferente, embora as pontuações do modelo continuem as mesmas. Hoje você vai ver todos os limiares de uma vez, em duas curvas: ROC e precisão–sensibilidade (PR). Também vai conferir qual delas diz a verdade quando há poucos doentes. O modelo é fraco de propósito: uma regressão logística que vê só uma medida, a textura média do tumor, para que as curvas não grudem nos cantos.
Escolha uma resposta e o seu grau de certeza.
Responda para liberar o experimento.
Experimento interativo
Este experimento interativo funciona em um navegador com JavaScript ativado. O texto ao redor descreve o que ele mostra.
Ver a resposta
Resposta certa: O ROC AUC quase não muda (cerca de 0,77), enquanto o AP cai para cerca de 0,14
O ROC AUC é 0,773 com todas as malignas e 0,772 em média com 19 (em 200 sorteios de quais malignas ficam). O AP cai de 0,591 para 0,137 em média. O modelo não esqueceu nada; só as proporções das classes mudaram. A ROC não vê isso, a curva PR vê.
Experimente
- Comece com 212 malignas e limiar 0,5. Leia a sensibilidade e a FPR e depois mova o limiar para 0,3. Para onde vai o ponto nas duas curvas?
- Troque para 19 malignas com limiar 0,3. Há tantos alarmes falsos quanto há pouco. O que aconteceu com a precisão?
- Compare o ROC AUC e o AP com 212, 40 e 19 malignas.
Depois de conferir no lab, vamos dar nome ao que você vê.
A ideia em poucas palavras
O modelo não diz “maligno” ou “benigno”. Ele dá uma pontuação de 0 a 1, e quem decide é um limiar. Cada limiar dá um par de números diferente: quantas malignas foram encontradas (sensibilidade) e quantas benignas receberam um alarme falso. A curva ROC desenha esses pares para todos os limiares de uma vez: na horizontal, a parcela de alarmes falsos entre as benignas (FPR); na vertical, a sensibilidade. Um limiar alto é o canto inferior esquerdo (poucos alarmes); um baixo, o canto superior direito (alarme em toda biópsia).
A curva precisão–sensibilidade (PR) mostra os mesmos limiares de outro jeito: na horizontal, a sensibilidade; na vertical, a precisão, ou seja, que parte dos alarmes está certa. A área sob a curva ROC é o ROC AUC; a área sob a curva PR é o AP (average precision). Cada um resume todos os limiares de uma vez, então não depende do limiar que você escolher.
Com as 569 biópsias o modelo tem ROC AUC de 0,773 e AP de 0,591. Chutar ao acaso daria ROC AUC de 0,5 e um AP igual à parcela de malignas, ou seja, 0,373. O modelo é claramente melhor que o acaso, mas está longe do ideal, que é 1.
Jak to policzono
- Biópsias: Breast Cancer Wisconsin (Diagnostic), UCI, licença CC BY 4.0. 569 biópsias (357 benignas, 212 malignas). O modelo vê uma medida: a textura média do tumor.
- Pontuações de validação cruzada em 5 partes (
StratifiedKFold(5)no scikit-learn): cada biópsia é pontuada por um modelo que nunca a viu. - Classe mais rara: ficam as 357 benignas e 40 ou 19 malignas sorteadas. O gráfico mostra um sorteio; as médias são de 200 sorteios.
- Modelo: padronização e regressão logística (C = 1).
Por que funciona
A ROC conta os alarmes falsos em relação às benignas: a FPR é o número de alarmes falsos dividido por 357. A sensibilidade conta os acertos em relação às malignas. Quando você tira malignas ao acaso, as duas frações continuam mais ou menos iguais, então a curva ROC e sua área quase não se mexem. Com limiar 0,3 o modelo dá alarme em 144 de 357 benignas (FPR 40,3%), haja 212 malignas ou 19.
A precisão conta os alarmes falsos em relação a todos os alarmes. Com 212 malignas e limiar 0,3 o modelo encontra 177, então a precisão é de 55,1%. Com 19 malignas ele encontra 17, e os 144 alarmes falsos continuam lá: a precisão cai para 10,6%, ou seja, 8,5 alarmes falsos por alarme certo. A curva PR cai junto com a precisão, e o AP vai de 0,591 para 0,137 em média. A linha do chute ao acaso na PR também desce, até a parcela de malignas: 0,051.
Não é sorte de um sorteio nem de um jeito de dividir os dados. Com 40 malignas (10%) o ROC AUC é 0,773 em média e o AP 0,232. No código abaixo, o mesmo modelo em 20 outras divisões tem, com 19 malignas, um AP abaixo da metade do obtido com todos os dados, todas as vezes.
Erro comum
Verdadeiro ou falso: “um ROC AUC alto significa poucos alarmes falsos”. Falso. O ROC AUC mede quão bem o modelo ordena: a probabilidade de uma biópsia maligna sorteada receber pontuação maior que uma benigna sorteada. Ele não diz quantos alarmes serão falsos, porque isso depende de quão rara é a classe. No lab, com 19 malignas o ROC AUC é 0,772 em média, quase o mesmo que com 212, e com limiar 0,3 há 8,5 alarmes falsos para cada certo. Quando a classe é rara, olhe a curva PR e a precisão no limiar que você vai usar de verdade.
Um aviso no sentido contrário: o AP também não é um número “só do modelo”. Ele depende da parcela da classe nos dados, então o AP de dois conjuntos com proporções diferentes não pode ser comparado diretamente. Compare o AP com a linha do chute ao acaso nos mesmos dados.
Quiz
Três perguntas para você se testar. Escolha uma resposta ou abra a resposta embaixo de cada pergunta. No teclado: as setas escolhem, Enter ou Espaço confirma.
Pontos-chave
- A curva ROC e a curva PR mostram todos os limiares de uma vez; o limiar se escolhe depois, pelo custo dos erros.
- O ROC AUC mede quão bem o modelo ordena e quase não depende das proporções das classes.
- Quando a classe positiva é rara, os mesmos alarmes falsos comem a precisão: olhe a curva PR e o AP.
- Compare o AP com a linha do chute ao acaso, a parcela da classe positiva nos mesmos dados.
Mais a fundo: fórmula, código, prática
A matemática
Com o limiar t, o modelo diz “maligno” quando sua pontuação s ≥ t. Então sensibilidade = TP / (TP + FN), FPR = FP / (FP + TN), precisão = TP / (TP + FP).
A FPR só tem benignas no denominador; a sensibilidade, só malignas. Se você tira malignas ao acaso, nenhuma das duas frações muda de forma sistemática, então a curva ROC fica. A precisão tem os dois tipos de alarme no denominador. Com limiar 0,3: 177 / (177 + 144) ≈ 0,551 com 212 malignas e 17 / (17 + 144) ≈ 0,106 com 19.
O ROC AUC é a probabilidade de uma maligna sorteada receber pontuação maior que uma benigna sorteada: AUC = P(s₊ > s₋), e os empates contam pela metade. O AP é a precisão média ponderada pelos saltos de sensibilidade: AP = Σₖ (Rₖ − Rₖ₋₁) · Pₖ. Pontuações ao acaso dão AUC 0,5 e um AP igual à parcela da classe positiva: 212 / 569 ≈ 0,373 ou 19 / 376 ≈ 0,051.
No código (Python)
O mesmo experimento no scikit-learn: pontuações de validação cruzada, ROC AUC e AP com 212, 40 e 19 malignas (médias de 1000 sorteios), e depois o mesmo em 20 outras divisões.
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 roc_auc_score, average_precision_score
X, y = load_breast_cancer(return_X_y=True)
X, y = X[:, [1]], 1 - y # só a textura média, como no lab; 1 = maligno
model = make_pipeline(StandardScaler(), LogisticRegression())
def scores(cv): # pontuações de validação: cada biópsia é pontuada por um modelo que nunca a viu
return cross_val_predict(model, X, y, cv=cv, method="predict_proba")[:, 1]
ben, mal = np.flatnonzero(y == 0), np.flatnonzero(y == 1)
def rare(p, keep, draws, seed): # as 357 benignas + `keep` malignas sorteadas, média dos sorteios
rng = np.random.default_rng(seed)
rows = [np.r_[ben, rng.choice(mal, keep, replace=False)] for _ in range(draws)]
return np.mean([(roc_auc_score(y[i], p[i]), average_precision_score(y[i], p[i])) for i in rows], axis=0)
p = scores(StratifiedKFold(5))
print(f"212 malignant ({212 / 569:.0%}): ROC AUC {roc_auc_score(y, p):.3f}, AP {average_precision_score(y, p):.3f}")
for keep in (40, 19):
auc, ap = rare(p, keep, 1000, 0)
print(f"{keep} malignant ({keep / (357 + keep):.0%}), mean of 1000 draws: ROC AUC {auc:.3f}, AP {ap:.3f}")
r = []
for s in range(20): # 20 outras formas de dividir os dados em 5 partes
q = scores(StratifiedKFold(5, shuffle=True, random_state=s))
r.append([roc_auc_score(y, q), average_precision_score(y, q), *rare(q, 19, 200, s)])
r = np.array(r)
print(f"20 other fold splits, 212 -> 19 malignant: ROC AUC {r[:, 0].mean():.3f} -> {r[:, 2].mean():.3f}, AP {r[:, 1].mean():.3f} -> {r[:, 3].mean():.3f}; AP below half in {(r[:, 3] < r[:, 1] / 2).sum()} of 20")
Saída
212 malignant (37%): ROC AUC 0.773, AP 0.591
40 malignant (10%), mean of 1000 draws: ROC AUC 0.773, AP 0.231
19 malignant (5%), mean of 1000 draws: ROC AUC 0.774, AP 0.140
20 other fold splits, 212 -> 19 malignant: ROC AUC 0.774 -> 0.775, AP 0.595 -> 0.140; AP below half in 20 of 20
Com todas as malignas os números são os mesmos do lab. Com 40 e 19 o código sorteia as malignas de outro jeito que o lab e faz 1000 sorteios em vez de 200, por isso as médias diferem na terceira casa decimal: AP 0,140 em vez de 0,137. Em 20 outras divisões o quadro é o mesmo: o ROC AUC fica, e o AP cai abaixo da metade todas as vezes.
Baixar o notebook (.ipynb). Abra no Jupyter ou envie para o Google Colab; ele baixa sozinho os dados que faltarem.
Para quem pratica
- No scikit-learn os números vêm de
roc_auc_scoreeaverage_precision_score, e as curvas são desenhadas porRocCurveDisplayePrecisionRecallDisplay. Calcule-os com pontuações de validação (cross_val_predict(..., method="predict_proba")), não com os dados de aprendizado. - Com uma classe rara (fraudes, doenças raras, falhas) informe o AP ao lado do ROC AUC, e ao lado do AP a linha do chute ao acaso, a parcela da classe positiva.
- Uma curva é um cardápio de limiares. Escolha o limiar na validação pelo custo dos erros, por exemplo “sensibilidade de pelo menos 90% com a maior precisão possível”, e só depois confira no teste.
- O ROC AUC de dois conjuntos com proporções diferentes pode ser comparado, mas não diz quantos alarmes serão falsos; o AP diz mais sobre isso, mas compare-o só com as mesmas proporções.
Isto foi útil?
Obrigado! Isso nos ajuda a melhorar.
Vá mais fundo no Atlas
Verbetes da enciclopédia sobre as ideias desta aula: