📘 Lição 5: Funcionou Bem? Avaliando Seu Modelo com Métricas Importantes

"Não meça seu modelo pelo quanto ele acerta... meça-o pelo quanto o que ele acerta importa."


⏱️ Duração estimada desta lição: 75-90 minutos


🧭 Por que esta lição é tão importante?

Porque aqui é onde você deixa de confiar e começa a verificar.

Você treinou um modelo.
Ele fez previsões.
Mas isso não significa que é bom!

Muitos iniciantes se empolgam com uma "acurácia de 98%"... e depois descobrem que seu modelo falha nos casos mais importantes.

Nesta lição, você aprenderá:

  • Por que a acurácia não é tudo (especialmente com dados desbalanceados!).
  • O que é uma matriz de confusão e como lê-la como um profissional.
  • O que significam precisão, revocação e F1-score... e quando usar cada um.
  • Como interpretar probabilidades, não apenas rótulos.
  • Como evitar se enganar com métricas superficiais.

⚠️ Aviso amigável: Esta lição fará você questionar tudo o que achava saber sobre "bons modelos". Mas isso é bom. A humildade é a mãe da melhoria.


🎯 Objetivos desta lição

Ao final, você será capaz de:

✅ Calcular e interpretar a acurácia do seu modelo.
✅ Construir e entender uma matriz de confusão.
✅ Calcular e interpretar precisão, revocação e F1-score.
✅ Saber quando usar cada métrica de acordo com o problema.
✅ Avaliar não apenas previsões, mas probabilidades.
✅ Detectar se seu modelo é "burro" ou verdadeiramente inteligente.
✅ Sentir-se confortável tomando decisões baseadas em métricas, não em intuição.


🛠️ Ferramentas que você usará

  • Scikit-learnaccuracy_score, confusion_matrix, classification_report, precision_recall_curve.
  • Matplotlib / Seaborn → Para visualizar métricas.
  • Pandas → Para manipular resultados.

💡 Certifique-se de ter seu modelo treinado e suas previsões (y_test, y_pred) prontas da Lição 4. Se não, aqui está o código rápido para acompanhar:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.feature_extraction.text import CountVectorizer
from sklearn.naive_bayes import MultinomialNB

# Carregar e preparar dados
url = "https://raw.githubusercontent.com/justmarkham/DAT8/master/data/sms.tsv"
data = pd.read_csv(url, sep='\t', names=['label', 'message'])
data['label_encoded'] = data['label'].map({'ham': 0, 'spam': 1})

X = data['message']
y = data['label_encoded']
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42, stratify=y)

vectorizer = CountVectorizer()
X_train_vec = vectorizer.fit_transform(X_train)
X_test_vec = vectorizer.transform(X_test)

# Treinar modelo
model = MultinomialNB()
model.fit(X_train_vec, y_train)

# Prever
y_pred = model.predict(X_test_vec)

📊 Parte 1: A Ilusão da Acurácia — É Realmente 98%?

Vamos começar com a métrica mais popular... e mais perigosa.


🔹 Passo 1: Calcular a acurácia

from sklearn.metrics import accuracy_score

acc = accuracy_score(y_test, y_pred)
print(f"Acurácia: {acc:.4f} → {acc*100:.2f}%")

📌 Saída típica:

Acurácia: 0.9821 → 98.21%

→ Uau! 98% corretos. Isso significa que o modelo é excelente?

NÃO! E aqui está o porquê.


🔍 O problema com dados desbalanceados

Lembre-se: em nosso conjunto de dados, apenas 13,4% são spam. 86,6% são ham.

Imagine um modelo burro que sempre prevê "ham".
Qual seria sua acurácia?

Acurácia = (Hams Verdadeiros) / (Total) = 955 / 1115 ≈ 85.65%

→ Um modelo que nunca detecta spam teria 85,65% de acurácia!

Seu modelo tem 98,21% → é melhor que o burro... mas quanto melhor no que realmente importa: detectar spam?

📌 Conclusão: A acurácia engana quando há desequilíbrio. Você precisa de métricas mais inteligentes.


🧩 Parte 2: A Matriz de Confusão — Seu Microscópio de Erros

Aqui é onde você vê exatamente quais acertos e quais erros seu modelo está cometendo.


🔹 Passo 2: Construir a matriz de confusão

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

cm = confusion_matrix(y_test, y_pred)

# Visualizar
plt.figure(figsize=(8, 6))
sns.heatmap(cm, annot=True, fmt='d', cmap='Blues', 
            xticklabels=['Ham (Pred)', 'Spam (Pred)'], 
            yticklabels=['Ham (Real)', 'Spam (Real)'])
plt.title("Matriz de Confusão - Classificador de Spam", fontsize=16)
plt.ylabel("Rótulo Verdadeiro", fontsize=12)
plt.xlabel("Rótulo Previsto", fontsize=12)
plt.show()

📌 Saída típica (valores aproximados):

          Previsto
          Ham  Spam
Real Ham   950    5
Real Spam   15  145

🔍 Como ler esta matriz?

  • Verdadeiros Negativos (VN): 950
    → Mensagens ham que o modelo disse que eram ham. ✅ Perfeito!

  • Falsos Positivos (FP): 5
    → Mensagens ham que o modelo disse que eram spam. ❌ Erro grave! (Marcar uma mensagem importante como spam).

  • Falsos Negativos (FN): 15
    → Mensagens spam que o modelo disse que eram ham. ❌ Erro grave! (Deixar spam passar).

  • Verdadeiros Positivos (VP): 145
    → Mensagens spam que o modelo disse que eram spam. ✅ Perfeito!

📌 Isso é ouro! Agora você sabe onde seu modelo falha. Não é um número abstrato... são erros concretos que você pode melhorar.


🎯 Parte 3: Precisão, Revocação e F1-Score — As 3 Métricas que Importam

Agora, vamos quantificar esses erros com métricas profissionais.


🔹 Passo 3: Calcular o relatório de classificação

from sklearn.metrics import classification_report

report = classification_report(y_test, y_pred, 
                               target_names=['Ham', 'Spam'], 
                               output_dict=False)
print(report)

📌 Saída típica:

              precision    recall  f1-score   support

         Ham       0.98      0.99      0.99       955
        Spam       0.97      0.91      0.94       160

    accuracy                           0.98      1115
   macro avg       0.98      0.95      0.96      1115
weighted avg       0.98      0.98      0.98      1115

🔍 O que significam essas métricas?

1. Precisão

"De todos aqueles que eu disse que eram spam, quantos realmente eram?"

Precisão (Spam) = VP / (VP + FP) = 145 / (145 + 5) = 145/150 ≈ 0.97

97% de precisão em spam: quando o modelo diz "spam", está certo 97% das vezes. Excelente!

📌 Quando a precisão importa?
Quando o custo de um falso positivo é alto.
Exemplo: Marcar um email importante como spam → o usuário pode perder informações críticas.


2. Revocação (Sensibilidade, Taxa de Verdadeiros Positivos)

"De todo o spam que existia, quantos eu detectei?"

Revocação (Spam) = VP / (VP + FN) = 145 / (145 + 15) = 145/160 ≈ 0.91

91% de revocação em spam: detectou 91% de todo o spam. Muito bom!

📌 Quando a revocação importa?
Quando o custo de um falso negativo é alto.
Exemplo: Deixar spam fraudulento passar → o usuário pode clicar e perder dinheiro.


3. F1-Score

"Média harmônica entre precisão e revocação. Ideal quando você quer equilíbrio."

F1 = 2 * (Precisão * Revocação) / (Precisão + Revocação)
   = 2 * (0.97 * 0.91) / (0.97 + 0.91) ≈ 0.94

94% de F1-score: um bom equilíbrio entre não incomodar o usuário (precisão) e protegê-lo (revocação).

📌 Quando usar F1?
Quando você não sabe o que é mais importante, ou quando quer uma única métrica que resuma o desempenho em classes desbalanceadas.


📈 Parte 4: Além dos Rótulos — Avaliando Probabilidades

Seu modelo não apenas prevê "spam" ou "ham." Ele também lhe dá probabilidades.

Isso é poderoso. Porque às vezes, você não quer uma decisão binária... você quer saber o quão certo o modelo está.


🔹 Passo 4: Obter probabilidades

# Obter probabilidades para cada classe
y_proba = model.predict_proba(X_test_vec)

# Para spam (classe 1), é a segunda coluna
y_proba_spam = y_proba[:, 1]

# Ver as primeiras 10 probabilidades
for i in range(10):
    print(f"Mensagem {i+1}: Probabilidade de spam = {y_proba_spam[i]:.4f} → Previsão: {'Spam' if y_pred[i] == 1 else 'Ham'}")

📌 Saída típica:

Mensagem 1: Probabilidade de spam = 0.0002 → Previsão: Ham
Mensagem 2: Probabilidade de spam = 0.9998 → Previsão: Spam
Mensagem 3: Probabilidade de spam = 0.0015 → Previsão: Ham
...

→ Incrível! O modelo não apenas diz "spam," ele lhe diz "tenho 99,98% de certeza."


🔹 Passo 5: Curva Precision-Recall (opcional, mas reveladora)

O que acontece se você mudar o limiar de decisão?

Por padrão, se probabilidade > 0.5 → spam.
Mas e se você usar 0.7? Ou 0.3?

from sklearn.metrics import precision_recall_curve
import matplotlib.pyplot as plt

precision, recall, thresholds = precision_recall_curve(y_test, y_proba_spam)

plt.figure(figsize=(10, 6))
plt.plot(recall, precision, marker='.', label='Naive Bayes')
plt.xlabel('Revocação')
plt.ylabel('Precisão')
plt.title('Curva Precision-Recall')
plt.legend()
plt.grid(True)
plt.show()

📌 O que você vê?
Uma curva que mostra a compensação entre precisão e revocação para diferentes limiares.
Ideal para escolher um limiar que se adapte às suas necessidades (mais precisão ou mais revocação).


❌ Erros Comuns nesta Lição (Evite-os!)

  1. Confiar apenas na acurácia → Você perde erros críticos.
  2. Ignorar a matriz de confusão → Você não vê onde o modelo falha.
  3. Não entender a diferença entre precisão e revocação → Você toma decisões erradas.
  4. Esquecer que as métricas dependem do problema → Na medicina, revocação é vital; em publicidade, precisão.
  5. Não usar probabilidades → Você perde informações valiosas sobre a confiança do modelo.

✅ Checklist desta lição — O que você deve saber fazer agora?

☐ Calcular e interpretar a acurácia.
☐ Construir e ler uma matriz de confusão.
☐ Calcular e interpretar precisão, revocação e F1-score.
☐ Saber quando priorizar precisão vs revocação de acordo com o problema.
☐ Obter e analisar probabilidades de previsão.
☐ Entender que um modelo "bom" depende do contexto, não apenas de um número.
☐ Sentir-se confortável avaliando modelos com rigor profissional.


🎯 Frase para lembrar:

"Não meça seu modelo pelo quanto ele acerta... meça-o pelo quanto o que ele acerta importa."


← Anterior: Lição 4: Treine Seu Primeiro Modelo | Próximo: Projeto Final →

Course Info

Course: AI-course0

Language: PT

Lesson: 5 evaluate model