Vídeo em breve
Por enquanto, esta aula está disponível só em texto — o vídeo entra assim que ficar pronto.
Avaliando modelos
Métricas de avaliação
MAE, RMSE e R² para regressão; matriz de confusão, precisão, recall e F1 para classificação; e por que a acurácia sozinha engana. · 18 min
Treinar um modelo é a parte fácil. A pergunta difícil é: ele é bom? E “bom” depende do problema. Esta aula apresenta as métricas que respondem essa pergunta de formas diferentes.
Métricas de regressão
Quando o alvo é um número, medimos o quanto as previsões erram:
| Métrica | O que mede |
|---|---|
| MAE (erro absoluto médio) | Em média, quantas unidades o modelo erra |
| RMSE (raiz do erro quadrático médio) | Parecido com o MAE, mas pune mais os erros grandes |
| R² | Quanto da variação dos dados o modelo explica (1 é perfeito) |
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
y_pred = modelo.predict(X_teste)
print(mean_absolute_error(y_teste, y_pred))
print(mean_squared_error(y_teste, y_pred) ** 0.5) # RMSE
print(r2_score(y_teste, y_pred))
Um MAE de 15000 num modelo de preço de imóveis significa que, em média, o modelo erra R$ 15.000 para cima ou para baixo.
Métricas de classificação
Vamos usar o dataset de diagnóstico de tumores. Neste dataset, a classe 0
é maligno e a 1 é benigno:
from sklearn.datasets import load_breast_cancer
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
X, y = load_breast_cancer(return_X_y=True)
X_treino, X_teste, y_treino, y_teste = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
modelo = DecisionTreeClassifier(max_depth=4, random_state=42)
modelo.fit(X_treino, y_treino)
y_pred = modelo.predict(X_teste)
Matriz de confusão
Ela mostra, para cada classe real, o que o modelo previu:
from sklearn.metrics import confusion_matrix
print(confusion_matrix(y_teste, y_pred))
# [[ 58 6] linha 0: tumores malignos reais
# [ 4 103]] linha 1: tumores benignos reais
Os números acima são só ilustrativos, o seu resultado pode variar um pouco. A diagonal são os acertos, e fora dela estão os erros. Os erros têm nomes importantes:
- Falso positivo (FP): o modelo disse “sim” e era “não”.
- Falso negativo (FN): o modelo disse “não” e era “sim”.
Precisão, recall e F1
| Métrica | Pergunta que responde | Fórmula |
|---|---|---|
| Precisão | Das vezes que previu “sim”, quantas acertou? | VP / (VP + FP) |
| Recall | De todos os “sim” reais, quantos encontrou? | VP / (VP + FN) |
| F1 | Equilíbrio entre precisão e recall | média harmônica das duas |
from sklearn.metrics import classification_report
print(classification_report(y_teste, y_pred))
O classification_report mostra precisão, recall e F1 de cada classe de
uma vez.
Dica
Qual métrica priorizar depende do custo de cada erro. Num exame de câncer, deixar passar um tumor maligno (falso negativo) é muito mais grave que um alarme falso, então o recall da classe maligna é o que importa. Num filtro de spam, marcar um e-mail importante como spam (falso positivo) é o pior caso, então a precisão pesa mais.
Por que a acurácia sozinha engana
Imagine um sistema que detecta falhas raras num motor, em que só 5% das leituras são falhas. Um “modelo” que sempre responde “sem falha” tem 95% de acurácia e é completamente inútil, porque nunca detecta nada. É o problema das classes desbalanceadas, e a acurácia esconde ele.
Atenção
Sempre que as classes forem desbalanceadas, confie mais em precisão, recall e F1 do que na acurácia, e olhe a matriz de confusão.
Exercícios
Exercício
1. Aquecimento. Dada a matriz de confusão [[50, 10], [5, 35]]
(linhas: real, colunas: previsto), calcule na mão a acurácia e depois
confira com accuracy_score.
Exercício
2. Escolhendo a métrica. Para cada situação, diga se você priorizaria precisão ou recall e por quê: (a) um robô que detecta obstáculos à frente para frear; (b) recomendar filmes; (c) um alarme de incêndio.
Exercício
3. Desafio. Monte um problema desbalanceado: y com 950 zeros e 50
uns (np.array([0] * 950 + [1] * 50)) e X = np.zeros((1000, 1)).
Treine um DummyClassifier(strategy="most_frequent") do
sklearn.dummy e calcule a acurácia e o recall da classe 1
(recall_score). O que os dois números dizem sobre esse “modelo”?