W3docs

Machine Learning: Entendendo a Matriz de Confusão

Aprenda o que é uma matriz de confusão, como construí-la em Python com scikit-learn, visualizá-la com seaborn e derivar precisão, recall e F1-score a partir dela.

Uma matriz de confusão é uma tabela que resume os resultados de predição de um modelo de classificação, comparando os rótulos reais com os rótulos previstos. Ela é o ponto de partida para calcular precisão, recall, F1-score e a maioria das outras métricas de classificação.

Este capítulo aborda:

  • O que significam as quatro células (TP, FP, TN, FN) e por que cada uma importa
  • Como calcular métricas comuns a partir dessas células
  • Construção e visualização de uma matriz de confusão em Python com scikit-learn e seaborn
  • Matrizes de confusão multi-classe
  • Armadilhas comuns — especialmente em conjuntos de dados desbalanceados

O que é uma Matriz de Confusão?

Para um classificador binário (duas classes possíveis: positiva e negativa), a matriz de confusão é uma tabela 2×2:

Previsto PositivoPrevisto Negativo
Real PositivoTrue Positive (TP)False Negative (FN)
Real NegativoFalse Positive (FP)True Negative (TN)

Cada célula conta um tipo específico de resultado:

TermoAbreviaçãoSignificado
True PositiveTPModelo diz positivo; realidade é positiva ✓
True NegativeTNModelo diz negativo; realidade é negativa ✓
False PositiveFPModelo diz positivo; realidade é negativa ✗ (Erro Tipo I)
False NegativeFNModelo diz negativo; realidade é positiva ✗ (Erro Tipo II)

Um recurso mnemônico rápido: a primeira palavra (True / False) indica se a predição foi correta; a segunda palavra (Positive / Negative) indica o que o modelo previu.

Métricas Derivadas da Matriz

Os quatro contadores alimentam todas as métricas de classificação padrão:

MétricaFórmulaO que mede
Acurácia(TP + TN) / (TP + TN + FP + FN)Fração geral de predições corretas
PrecisãoTP / (TP + FP)De todas as predições positivas, quantas estavam corretas
Recall (Sensibilidade)TP / (TP + FN)De todos os positivos reais, quantos foram encontrados
EspecificidadeTN / (TN + FP)De todos os negativos reais, quantos foram corretamente descartados
F1-Score2 × Precisão × Recall / (Precisão + Recall)Média harmônica de precisão e recall

Quando priorizar precisão vs. recall

  • Priorize o recall quando perder um caso positivo é custoso — triagem médica, detecção de fraudes, filtros de spam que precisam capturar todas as mensagens de spam.
  • Priorize a precisão quando falsos alarmes são custosos — recomendações cirúrgicas, marcação de documentos jurídicos, sistemas de notificação push.
  • F1-score equilibra ambos e é a métrica padrão quando o conjunto de dados é desbalanceado.

Exemplo Numérico Trabalhado

Suponha que um modelo rastreie 100 pacientes para uma doença:

  • TP = 50 (pacientes doentes corretamente identificados)
  • FP = 5 (pacientes saudáveis incorretamente sinalizados como doentes)
  • FN = 10 (pacientes doentes não detectados)
  • TN = 35 (pacientes saudáveis corretamente liberados)

Cálculos passo a passo:

Accuracy  = (50 + 35) / 100 = 0.85  (85 %)
Precision = 50 / (50 + 5)  ≈ 0.909 (90.9 %)
Recall    = 50 / (50 + 10) ≈ 0.833 (83.3 %)
F1-Score  = 2 × 0.909 × 0.833 / (0.909 + 0.833) ≈ 0.869 (86.9 %)

Observe que a acurácia (85 %) parece razoável, mas o recall é de apenas 83 % — o que significa que 10 dos 60 pacientes doentes foram perdidos. Em um contexto médico, essa diferença importa muito mais do que o número de acurácia isolado.

Construindo uma Matriz de Confusão em Python

Usando scikit-learn

sklearn.metrics fornece confusion_matrix() e um relatório de texto pronto via classification_report().

from sklearn.metrics import confusion_matrix, classification_report

# Ground-truth labels and model predictions
y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

cm = confusion_matrix(y_true, y_pred)
print("Confusion Matrix:")
print(cm)
print()
print(classification_report(y_true, y_pred, target_names=["Negative", "Positive"]))

confusion_matrix() retorna um array NumPy. Por padrão, as linhas são as classes reais e as colunas são as classes previstas (correspondendo ao layout da tabela mostrado acima). O layout do array é:

[[TN  FP]
 [FN  TP]]

Calculando métricas manualmente

Você pode extrair as quatro células e calcular as métricas por conta própria para verificar:

from sklearn.metrics import confusion_matrix

y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

tn, fp, fn, tp = confusion_matrix(y_true, y_pred).ravel()

accuracy  = (tp + tn) / (tp + tn + fp + fn)
precision = tp / (tp + fp)
recall    = tp / (tp + fn)
f1        = 2 * precision * recall / (precision + recall)

print(f"TP={tp}, FP={fp}, FN={fn}, TN={tn}")

print(f"Accuracy : {accuracy:.3f}")
print(f"Precision: {precision:.3f}")
print(f"Recall   : {recall:.3f}")
print(f"F1-Score : {f1:.3f}")

Saída esperada:

TP=4, FP=2, FN=1, TN=3
Accuracy : 0.700
Precision: 0.667
Recall   : 0.800
F1-Score : 0.727

Visualizando com seaborn

Um mapa de calor torna a matriz de confusão mais fácil de ler, especialmente para problemas multi-classe:

import matplotlib.pyplot as plt
import seaborn as sns
from sklearn.metrics import confusion_matrix

y_true = [1, 1, 0, 0, 1, 0, 1, 0, 1, 0]
y_pred = [1, 0, 0, 1, 1, 0, 1, 0, 1, 1]

cm = confusion_matrix(y_true, y_pred)

sns.heatmap(
    cm,
    annot=True,
    fmt="d",
    cmap="Blues",
    xticklabels=["Negative", "Positive"],
    yticklabels=["Negative", "Positive"],
)
plt.xlabel("Predicted label")
plt.ylabel("True label")
plt.title("Confusion Matrix")
plt.tight_layout()
plt.savefig("confusion_matrix.png", dpi=150)
plt.show()

annot=True imprime o contagem dentro de cada célula; fmt="d" formata-os como inteiros.

Matrizes de Confusão Multi-Classe

Quando há mais de duas classes, a matriz de confusão se expande para uma grade N×N. Cada linha ainda representa as classes reais; cada coluna representa as classes previstas. As células da diagonal são predições corretas; as células fora da diagonal são erros.

from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay
import matplotlib.pyplot as plt

# Three classes: cat, dog, rabbit
y_true = ["cat", "dog", "rabbit", "cat", "dog", "rabbit",
          "cat", "dog", "cat", "rabbit"]
y_pred = ["cat", "dog", "rabbit", "dog", "dog", "cat",
          "cat", "rabbit", "cat", "rabbit"]

labels = ["cat", "dog", "rabbit"]
cm = confusion_matrix(y_true, y_pred, labels=labels)
print(cm)

disp = ConfusionMatrixDisplay(confusion_matrix=cm, display_labels=labels)
disp.plot(cmap="Blues")
plt.title("Multi-Class Confusion Matrix")
plt.tight_layout()
plt.savefig("cm_multiclass.png", dpi=150)
plt.show()

ConfusionMatrixDisplay (adicionado no scikit-learn 0.24) é uma alternativa conveniente de uma única linha ao mapa de calor do seaborn e não requer a dependência do seaborn.

Para problemas multi-classe, precisão e recall são calculados por classe e depois calculados em média. classification_report() oferece três estratégias de média:

  • macro — média não ponderada entre as classes (trata todas as classes igualmente).
  • weighted — média ponderada pelo suporte (número de instâncias reais por classe).
  • micro — agrega TP/FP/FN em todas as classes antes de dividir (fornece acurácia geral para conjuntos de dados balanceados).

Armadilhas Comuns

A acurácia é enganosa em conjuntos de dados desbalanceados

Considere um conjunto de dados onde 95 % das amostras são negativas. Um modelo que sempre prevê negativo atinge 95 % de acurácia, mas tem recall zero — nunca captura um caso positivo. A matriz de confusão revela isso imediatamente: toda a primeira linha (Real Positivo) será composta apenas de FN.

Sempre combine acurácia com precisão, recall ou F1-score em dados desbalanceados. Consulte o capítulo Train/Test Split para saber como criar uma divisão representativa, e o capítulo AUC-ROC Curve para uma métrica de avaliação independente de limiar.

Escolhendo a estratégia de média errada

Usar a média macro quando as classes são muito desbalanceadas infla a pontuação das classes raras. Use weighted para uma visão realista da qualidade geral do modelo no conjunto de dados completo.

Esquecendo a normalização

As contagens brutas dependem do tamanho do conjunto de dados. Ao comparar modelos treinados em conjuntos de dados de tamanhos diferentes, normalize a matriz dividindo cada linha pela sua soma (passe normalize='true' para confusion_matrix()):

cm_normalized = confusion_matrix(y_true, y_pred, normalize="true")
print(cm_normalized.round(2))

Cada linha agora soma 1,0, mostrando a fração de cada classe real prevista corretamente.

Matriz de Confusão vs. Outras Ferramentas de Avaliação

FerramentaMelhor para
Matriz de confusãoEntender os tipos específicos de erros que um modelo comete
AUC-ROC CurveComparar classificadores em todos os limiares de decisão
Cross-ValidationEstimar o quão bem a matriz generaliza para dados não vistos
Grid SearchAjustar hiperparâmetros usando uma métrica escolhida (por exemplo, F1-score)

Principais Conclusões

  • Uma matriz de confusão divide as predições em TP, FP, TN e FN — quatro contadores que revelam quais erros um modelo comete, não apenas quantos.
  • A acurácia isolada é insuficiente; sempre verifique precisão, recall e F1-score, especialmente em dados desbalanceados.
  • Use sklearn.metrics.confusion_matrix() para o cálculo e seaborn ou ConfusionMatrixDisplay para a visualização.
  • Matrizes multi-classe seguem a mesma convenção linha = real, coluna = previsto e escalam para N×N.
  • Combine a estratégia de média (macro, weighted, micro) com a distribuição de classes do seu conjunto de dados.
Was this page helpful?