Vídeo em breve
Por enquanto, esta aula está disponível só em texto — o vídeo entra assim que ficar pronto.
Redes neurais e projeto
Projeto final: reconhecendo dígitos manuscritos
Um projeto completo de ponta a ponta: explorar imagens, comparar modelos, avaliar erros, salvar o modelo e usá-lo em dados novos. · 25 min
Hora de juntar tudo. O projeto final é um classificador de dígitos manuscritos: dada a imagem de um número escrito à mão, o modelo diz qual dígito de 0 a 9 ela representa. É um clássico do ramo, e o mesmo fluxo serve para reconhecer objetos, placas ou gestos.
Vamos seguir o fluxo completo do projeto de ML que vimos na primeira aula.
1. Conhecendo os dados
O scikit-learn traz 1797 imagens pequenas, de 8 por 8 pixels:
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_digits
digitos = load_digits()
X, y = digitos.data, digitos.target
print(X.shape) # (1797, 64): cada imagem virou 64 features, uma por pixel
print(y[:10]) # os primeiros rótulos
plt.imshow(digitos.images[0], cmap="gray_r")
plt.title(f"Rótulo: {y[0]}")
plt.show()
Cada imagem 8x8 vira uma linha com 64 números, um por pixel, com o brilho de 0 a 16. Para o modelo, um dígito é só um ponto num espaço de 64 dimensões.
2. Separando treino e teste
from sklearn.model_selection import train_test_split
X_treino, X_teste, y_treino, y_teste = train_test_split(
X, y, test_size=0.25, random_state=42, stratify=y
)
3. Comparando modelos
Vamos treinar os três tipos de modelo que vimos, num só laço:
from sklearn.neighbors import KNeighborsClassifier
from sklearn.tree import DecisionTreeClassifier
from sklearn.neural_network import MLPClassifier
from sklearn.pipeline import make_pipeline
from sklearn.preprocessing import StandardScaler
modelos = {
"KNN": make_pipeline(StandardScaler(), KNeighborsClassifier()),
"Árvore": DecisionTreeClassifier(max_depth=10, random_state=42),
"MLP": make_pipeline(
StandardScaler(),
MLPClassifier(hidden_layer_sizes=(64,), max_iter=500, random_state=42),
),
}
for nome, modelo in modelos.items():
modelo.fit(X_treino, y_treino)
print(f"{nome}: {modelo.score(X_teste, y_teste):.3f}")
Em geral o KNN e o MLP ficam bem acima da árvore neste problema. Os valores exatos dependem da sua versão do scikit-learn, então use os seus.
4. Avaliando de verdade
A acurácia é um bom começo, mas a matriz de confusão mostra onde o modelo erra. Vamos usar o melhor modelo:
from sklearn.metrics import confusion_matrix, classification_report
melhor = modelos["MLP"]
previsoes = melhor.predict(X_teste)
print(confusion_matrix(y_teste, previsoes))
print(classification_report(y_teste, previsoes))
Procure na matriz os pares de dígitos mais confundidos. É comum que números parecidos, como 3 e 8, ou 4 e 9, apareçam juntos nos erros.
Para ver os erros com os próprios olhos:
erros = np.where(previsoes != y_teste)[0]
for i in erros[:5]:
plt.imshow(X_teste[i].reshape(8, 8), cmap="gray_r")
plt.title(f"Real: {y_teste[i]} | Previsto: {previsoes[i]}")
plt.show()
Dica
Olhar os erros costuma ensinar mais do que olhar a nota. Muitas vezes você vai olhar uma imagem errada e pensar “nem eu saberia dizer qual número é esse”, o que mostra que o modelo já está perto do limite dos dados.
5. Salvando e reutilizando o modelo
Treinar leva tempo, e usar um modelo pronto deve ser instantâneo. Com o
joblib (instalado junto do scikit-learn) você salva o modelo em disco:
import joblib
joblib.dump(melhor, "digitos.joblib")
# em outro programa, ou outro dia:
modelo_carregado = joblib.load("digitos.joblib")
print(modelo_carregado.predict([X_teste[0]]))
Atenção
Como salvamos o pipeline inteiro, o StandardScaler vai junto com o
modelo e é aplicado automaticamente em dados novos. Se tivesse salvado
só o MLP, você teria que lembrar de padronizar os dados na mão toda vez
que fosse prever.
Exercícios: evoluindo o projeto
Exercício
1. Ajuste fino. Use GridSearchCV para achar o melhor
hidden_layer_sizes do MLP (teste por exemplo (32,), (64,) e
(64, 32)). Ele supera o valor que usamos na aula?
Exercício
2. Matriz visual. Desenhe a matriz de confusão como um mapa de calor
com ConfusionMatrixDisplay.from_predictions(y_teste, previsoes) do
sklearn.metrics. Quais são os dois dígitos mais confundidos?
Exercício
3. Desafio final. Crie a imagem de um dígito seu: um array de 64
valores (entre 0 e 16) formando, por exemplo, um número 1. Passe pelo
modelo com predict e veja se ele acerta. Depois tente enganá-lo
desenhando um dígito ambíguo. Onde ele passa a errar?
Parabéns por chegar ao fim! Você percorreu o ciclo completo: dados, modelo, avaliação e uso. O que você aprendeu vale para problemas bem maiores. Trocar dígitos por imagens de uma câmera de robô, ou leituras de sensores por classes de terreno, é o mesmo raciocínio com dados diferentes. Os próximos passos naturais são visão computacional, redes neurais profundas e a integração de modelos com robôs.