Machine Learning: Primeiros Passos com Scikit-learn
Última atualização: 2026-08-26
A API unificada do Scikit-learn significa que todo algoritmo é chamado da mesma forma — aprenda um e você conhecerá todos.
1. O que você vai aprender
- A filosofia de design e a API unificada do Scikit-learn: fit → predict → score
- As três interfaces centrais: Estimator, Transformer e Predictor
- Seu primeiro modelo: treine um classificador de árvore de decisão no conjunto de dados Iris, percorrendo o fluxo completo de train-test-split → fit → predict → evaluate
- Pipelines de pré-processamento de dados: encadeando StandardScaler + modelo em um único objeto
- A primeira tentativa do Bob: usar sklearn para fazer previsões simples no conjunto de dados de pequena amostra do SalesPredict
2. A história real de um iniciante em ML
(1) O problema: cada biblioteca tem uma API diferente
O Bob testou três bibliotecas de ML diferentes, e cada uma tinha sua própria convenção de chamada — uma usava train(), outra usava fit_model() e outra ainda usava learn(). Ele passou dois dias lendo documentação apenas para descobrir como chamá-las, e mudar para um algoritmo diferente significava começar do zero. APIs inconsistentes são a maior barreira para começar em ML.
(2) A solução do Scikit-learn
O Scikit-learn define um design de API unificada: todo algoritmo segue o padrão fit → predict → score. Mudar de algoritmo exige apenas alterar uma única linha.
from sklearn.linear_model import LinearRegression
from sklearn.ensemble import RandomForestRegressor
# Mesma API, algoritmo diferente - basta trocar a classe do modelo
models = {
"LinearRegression": LinearRegression(),
"RandomForest": RandomForestRegressor(n_estimators=100),
}
for name, model in models.items():
model.fit(X_train, y_train)
score = model.score(X_test, y_test)
print(f"{name}: R² = {score:.3f}")
(3) O resultado: uma API cobre 30+ algoritmos
Depois que o Bob dominou a API unificada do sklearn, a convenção de chamada de 30+ algoritmos se tornou idêntica — de LinearRegression ao XGBoost, basta trocar o nome da classe.
3. Filosofia de design do Scikit-learn e a API unificada
(1) O padrão da API unificada
graph LR
A[Estimator<br/>Classe Base] --> B[Transformer<br/>fit + transform]
A --> C[Predictor<br/>fit + predict]
A --> D[Modelo<br/>fit + predict + score]
B --> E[StandardScaler<br/>PCA<br/>OneHotEncoder]
C --> F[KMeans<br/>DBSCAN]
D --> G[LinearRegression<br/>RandomForest<br/>SVM]
(2) As três interfaces centrais
| Interface | Métodos principais | Propósito | Exemplos |
|---|---|---|---|
| Estimator | fit(X, y) |
Aprender parâmetros a partir dos dados | Classe base de todos os modelos |
| Transformer | fit() + transform() + fit_transform() |
Pré-processamento de dados | StandardScaler, PCA |
| Predictor | fit() + predict() |
Gerar previsões | LinearRegression, SVM |
▶ Exemplo: Padrões de uso de Estimator/Transformer/Predictor
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import numpy as np
# Gerar dados de amostra
rng = np.random.default_rng(42)
X = rng.uniform(0, 100, (200, 3))
y = 50 + 0.8 * X[:, 0] + 1.2 * X[:, 1] - 0.5 * X[:, 2] + rng.normal(0, 5, 200)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# Transformer: StandardScaler
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train) # fit + transform em um único passo
X_test_scaled = scaler.transform(X_test) # apenas transform (usa estatísticas do treino)
# Predictor: LinearRegression
model = LinearRegression()
model.fit(X_train_scaled, y_train)
predictions = model.predict(X_test_scaled)
score = model.score(X_test_scaled, y_test)
print(f"R² score: {score:.4f}")
print(f"Coeficientes: {model.coef_}")
print(f"Intercepto: {model.intercept_:.2f}")
Saída:
# Executado com sucesso
4. Seu primeiro modelo de ML: classificação da Iris
(1) O fluxo completo de trabalho em ML
▶ Exemplo: Pipeline completo de classificação com árvore de decisão na Iris
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
# Passo 1: Carregar os dados
iris = load_iris()
X, y = iris.data, iris.target
print(f"Features: {iris.feature_names}")
print(f"Classes: {iris.target_names}")
print(f"Shape: {X.shape}")
# Passo 2: Dividir treino/teste
X_train, X_test, y_train, y_test = train_test_split(
X, y, test_size=0.3, random_state=42, stratify=y
)
print(f"Treino: {X_train.shape[0]}, Teste: {X_test.shape[0]}")
# Passo 3: Treinar o modelo
model = DecisionTreeClassifier(max_depth=3, random_state=42)
model.fit(X_train, y_train)
# Passo 4: Prever
y_pred = model.predict(X_test)
# Passo 5: Avaliar
acc = accuracy_score(y_test, y_pred)
print(f"\nAcurácia: {acc:.4f}")
print(f"\nRelatório de Classificação:\n{classification_report(y_test, y_pred, target_names=iris.target_names)}")
print(f"Matriz de Confusão:\n{confusion_matrix(y_test, y_pred)}")
Saída:
Features: ['sepal length (cm)', 'sepal width (cm)', ...]
Classes: ['setosa' 'versicolor' 'virginica']
Shape: (150, 4)
Treino: 105, Teste: 45
Acurácia: 1.0000
▶ Exemplo: Visualizando a árvore de decisão
from sklearn.tree import plot_tree
import matplotlib.pyplot as plt
fig, ax = plt.subplots(figsize=(12, 8))
plot_tree(model, feature_names=iris.feature_names,
class_names=iris.target_names, filled=True, ax=ax)
plt.title("Árvore de Decisão Iris (max_depth=3)")
plt.tight_layout()
plt.savefig("iris_tree.png", dpi=150)
Saída:
# Executado com sucesso
(2) Entendendo o train_test_split em detalhes
| Parâmetro | Significado | Valor recomendado |
|---|---|---|
| test_size | Proporção para o conjunto de teste | 0.2–0.3 |
| random_state | Semente aleatória | 42 (para reprodutibilidade) |
| stratify | Amostragem estratificada | Obrigatório para tarefas de classificação |
| shuffle | Se deve embaralhar os dados | True por padrão |
5. Pipelines de pré-processamento de dados
(1) Por que você precisa de um Pipeline
Um Pipeline une pré-processamento e modelo em uma única unidade, evitando vazamento de dados (quando informações do conjunto de teste vazam para o processo de treinamento).
▶ Exemplo: Um Pipeline com StandardScaler + Modelo
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.linear_model import LogisticRegression
from sklearn.model_selection import cross_val_score
from sklearn.datasets import load_iris
iris = load_iris()
X, y = iris.data, iris.target
# Construir pipeline
pipe = Pipeline([
("scaler", StandardScaler()),
("classifier", LogisticRegression(max_iter=200)),
])
# Validação cruzada com pipeline (sem vazamento de dados!)
scores = cross_val_score(pipe, X, y, cv=5, scoring="accuracy")
print(f"Acurácia na CV: {scores.mean():.4f} +/- {scores.std():.4f}")
# Ajustar aos dados completos e prever
pipe.fit(X, y)
new_sample = [[5.1, 3.5, 1.4, 0.2]]
prediction = pipe.predict(new_sample)
print(f"Previsão: {iris.target_names[prediction[0]]}")
Saída:
# Executado com sucesso
(2) Pipeline vs. pré-processamento manual
| Aspecto | Pré-processamento Manual | Pipeline |
|---|---|---|
| Risco de vazamento de dados | Alto (fácil encaixar o scaler nos dados de teste por acidente) | Baixo (Pipeline isola automaticamente) |
| Legibilidade do código | Disperso em vários passos | Consolidado em um único objeto |
| Validação cruzada | Exige loop manual | cross_val_score(pipe) |
| Facilidade de implantação | É preciso salvar scaler e modelo separados | Salve um único objeto do pipeline |
▶ Exemplo: Pipeline de linha de base do SalesPredict
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler, OneHotEncoder
from sklearn.compose import ColumnTransformer
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import train_test_split
import pandas as pd
import numpy as np
# Simular dados do SalesPredict
rng = np.random.default_rng(42)
n = 500
df = pd.DataFrame({
"ad_spend": rng.uniform(10, 100, n),
"traffic": rng.uniform(100, 1000, n),
"category": rng.choice(["Elec", "Roupa", "Alim"], n),
"is_weekend": rng.choice([0, 1], n),
})
df["revenue"] = 50 + 0.8 * df["ad_spend"] + 0.1 * df["traffic"] + rng.normal(0, 10, n)
# Definir grupos de features
num_features = ["ad_spend", "traffic"]
cat_features = ["category", "is_weekend"]
# ColumnTransformer para pré-processamento misto
preprocessor = ColumnTransformer([
("num", StandardScaler(), num_features),
("cat", OneHotEncoder(drop="first"), cat_features),
])
# Pipeline completo
pipe = Pipeline([
("preprocessor", preprocessor),
("model", LinearRegression()),
])
X = df.drop(columns=["revenue"])
y = df["revenue"]
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
pipe.fit(X_train, y_train)
score = pipe.score(X_test, y_test)
print(f"R² da linha de base do SalesPredict: {score:.4f}")
# Prever
sample = pd.DataFrame({"ad_spend": [50], "traffic": [500], "category": ["Elec"], "is_weekend": [1]})
pred = pipe.predict(sample)
print(f"Receita prevista: {pred[0]:.1f} mil USD")
Saída:
# Executado com sucesso
6. Fundamentos de avaliação de modelos
(1) Métricas de classificação vs. regressão
| Tarefa | Métrica | Significado | Função do sklearn |
|---|---|---|---|
| Classificação | Acurácia | Proporção de previsões corretas | accuracy_score |
| Classificação | Precisão | Proporção de verdadeiros positivos entre os positivos previstos | precision_score |
| Classificação | Revocação | Proporção de verdadeiros positivos entre os positivos reais | recall_score |
| Classificação | F1 | Média harmônica de precisão e revocação | f1_score |
| Regressão | MAE | Erro Absoluto Médio | mean_absolute_error |
| Regressão | MSE | Erro Quadrático Médio | mean_squared_error |
| Regressão | R² | Coeficiente de determinação | r2_score |
▶ Exemplo: Avaliação completa de um modelo de regressão
from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score
import numpy as np
y_true = np.array([100, 150, 200, 250, 300])
y_pred = np.array([95, 160, 190, 260, 310])
mae = mean_absolute_error(y_true, y_pred)
mse = mean_squared_error(y_true, y_pred)
rmse = np.sqrt(mse)
r2 = r2_score(y_true, y_pred)
mape = np.mean(np.abs((y_true - y_pred) / y_true)) * 100
print(f"MAE: {mae:.2f} mil USD")
print(f"RMSE: {rmse:.2f} mil USD")
print(f"R²: {r2:.4f}")
print(f"MAPE: {mape:.1f}%")
Saída:
# Executado com sucesso
❓ Perguntas Frequentes
P: Qual a diferença entre fit_transform e transform? R: fit_transform = fit + transform. Use no conjunto de treino (aprende os parâmetros e aplica a transformação). transform aplica apenas parâmetros já aprendidos e deve ser usado no conjunto de teste. Nunca chame fit no conjunto de teste — isso causa vazamento de dados.
P: Quais os benefícios de usar um Pipeline? R: Três benefícios principais — 1) Evita vazamento de dados (isola automaticamente fit/transform durante a validação cruzada); 2) Código mais limpo (um único objeto contém todos os passos); 3) Implantação mais fácil (salve um único arquivo pickle).
P: O que significa random_state=42? R: Define a semente aleatória para garantir reprodutibilidade. 42 é uma referência cultural da programação a "a resposta" de O Guia do Mochileiro das Galáxias — não tem efeito sobre a qualidade do resultado.
P: Quando o parâmetro stratify é obrigatório? R: É obrigatório em tarefas de classificação.
stratify=ygarante que a distribuição de classes nos conjuntos de treino e teste corresponda à dos dados originais, evitando que classes minoritárias fiquem inteiramente no conjunto de teste.
P: O que significa cv=5 em cross_val_score? R: Significa validação cruzada de 5 folds — os dados são divididos em 5 partes, e o modelo é treinado em 4 partes e validado na parte restante, em rotação. O score final é a média entre os 5 folds. Isso é mais confiável do que uma única divisão treino/teste.
P: Qual a diferença entre ColumnTransformer e Pipeline? R: Pipeline encadeia passos em sequência (a saída de um passo se torna a entrada do seguinte), enquanto ColumnTransformer aplica diferentes transformers a diferentes colunas em paralelo e depois concatena os resultados. Eles costumam ser usados juntos.
📖 Resumo
- API unificada do sklearn: Estimator(fit) → Transformer(fit+transform) → Predictor(fit+predict+score)
- O fluxo completo de trabalho em ML: carregar dados → dividir em treino/teste → ajustar ao treino → prever → avaliar com score
- Pipelines unem pré-processamento + modelo em uma única unidade, evitando vazamento de dados e simplificando a implantação
- ColumnTransformer lida com features de tipos mistos (StandardScaler para colunas numéricas, OneHotEncoder para categóricas)
- Avaliação de classificação usa acurácia/precisão/revocação/F1; avaliação de regressão usa MAE/RMSE/R²/MAPE
cross_val_scoreexecuta validação cruzada, que é mais confiável do que uma única divisão treino/teste
📝 Exercícios
- Básico (Dificuldade ⭐): Use sklearn para carregar o conjunto de dados Iris, treine um classificador LogisticRegression e imprima a acurácia. Dica: siga o fluxo completo da Seção 4.
- Intermediário (Dificuldade ⭐⭐): Construa um Pipeline (StandardScaler + LogisticRegression) e use validação cruzada de 5 folds para comparar a acurácia com e sem o scaler. Dica: execute
cross_val_scoreno Pipeline vs. no modelo isolado. - Desafio (Dificuldade ⭐⭐⭐): Use ColumnTransformer para construir um Pipeline de tipos mistos para os dados do SalesPredict (padronize colunas numéricas + one-hot encode categóricas), depois treine um modelo LinearRegression e calcule R² e MAE. Dica: consulte o exemplo de Pipeline do SalesPredict na Seção 5.
← Anterior: Visualização de Dados com Matplotlib e Seaborn | Próximo: Exercício Integrador — Projeto para Iniciantes →