Machine Learning: O que É e Como Funciona | Python Brasil
Machine learning com Python: fluxo completo de trabalho, bias-variance tradeoff, validação cruzada, pipelines com scikit-learn e boas práticas.
O que é Machine Learning?
Machine learning (aprendizado de máquina) é um ramo da inteligência artificial em que algoritmos aprendem padrões a partir de dados sem serem explicitamente programados para cada regra. Em vez de escrever if temperatura > 38: febre = True, um modelo de ML aprende essa relação observando milhares de exemplos.
Python domina o cenário de machine learning graças ao ecossistema de bibliotecas maduro e à comunidade ativa. Empresas como Google, Netflix, Spotify e iFood usam Python extensivamente em seus sistemas de ML em produção.
O fluxo de trabalho em Machine Learning
Um projeto de ML bem estruturado segue etapas bem definidas:
1. Coleta e compreensão dos dados 2. Pré-processamento e limpeza 3. Engenharia de features 4. Treinamento do modelo 5. Avaliação e ajuste 6. Deploy em produção
Pré-processamento e engenharia de features
import pandas as pd
import numpy as np
from sklearn.preprocessing import StandardScaler, LabelEncoder, OneHotEncoder
from sklearn.impute import SimpleImputer
# Carregando dados de exemplo
df = pd.DataFrame({
'idade': [25, np.nan, 35, 42, 28],
'salario': [3000, 8000, np.nan, 15000, 5000],
'cidade': ['SP', 'RJ', 'SP', 'MG', 'RJ'],
'comprou': [0, 1, 0, 1, 1]
})
# Tratando valores faltantes
imputer_num = SimpleImputer(strategy='median')
df[['idade', 'salario']] = imputer_num.fit_transform(df[['idade', 'salario']])
# Codificando variáveis categóricas
# OneHotEncoding para variáveis nominais (sem ordem)
cidade_dummies = pd.get_dummies(df['cidade'], prefix='cidade')
df = pd.concat([df.drop('cidade', axis=1), cidade_dummies], axis=1)
# Engenharia de features: criando novas variáveis
df['salario_por_idade'] = df['salario'] / df['idade']
df['faixa_etaria'] = pd.cut(df['idade'],
bins=[0, 30, 45, 100],
labels=['jovem', 'adulto', 'senior'])
print(df)
Treinamento, avaliação e o problema do overfitting
from sklearn.model_selection import train_test_split
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, classification_report, confusion_matrix
from sklearn.datasets import load_breast_cancer
# Carregando dataset
dados = load_breast_cancer()
X, y = dados.data, dados.target
# SEMPRE separe dados antes de qualquer transformação
X_treino, X_teste, y_treino, y_teste = train_test_split(
X, y, test_size=0.2, random_state=42, stratify=y
)
# Treinando o modelo
modelo = RandomForestClassifier(n_estimators=100, random_state=42)
modelo.fit(X_treino, y_treino)
# Avaliação
previsoes = modelo.predict(X_teste)
print(f"Acurácia: {accuracy_score(y_teste, previsoes):.2%}")
print(classification_report(y_teste, previsoes, target_names=dados.target_names))
# Matriz de confusão
cm = confusion_matrix(y_teste, previsoes)
print("Matriz de confusão:")
print(cm)
# Linhas = valores reais, colunas = previsões
# [[VP, FN]
# [FP, VN]]
Bias-Variance Tradeoff
O dilema bias-variância é um dos conceitos mais importantes em ML:
- Bias alto (underfitting): o modelo é muito simples e não captura os padrões dos dados. Erra tanto no treino quanto no teste.
- Variância alta (overfitting): o modelo é complexo demais e “memoriza” os dados de treino. Vai muito bem no treino, mas mal no teste.
from sklearn.tree import DecisionTreeClassifier
from sklearn.datasets import make_classification
X, y = make_classification(n_samples=1000, n_features=10, random_state=42)
X_tr, X_te, y_tr, y_te = train_test_split(X, y, test_size=0.3, random_state=42)
for profundidade in [1, 3, 5, 10, None]:
modelo = DecisionTreeClassifier(max_depth=profundidade, random_state=42)
modelo.fit(X_tr, y_tr)
acc_treino = accuracy_score(y_tr, modelo.predict(X_tr))
acc_teste = accuracy_score(y_te, modelo.predict(X_te))
print(f"Profundidade {str(profundidade):4s}: treino={acc_treino:.3f}, teste={acc_teste:.3f}")
# profundidade=1: treino~0.80, teste~0.79 (underfitting / bias alto)
# profundidade=None: treino=1.00, teste~0.86 (overfitting / variância alta)
# profundidade=5: treino~0.92, teste~0.90 (ponto ideal)
Validação cruzada (Cross-Validation)
A divisão simples treino/teste pode ser instável. A validação cruzada estima o desempenho de forma mais robusta:
from sklearn.model_selection import cross_val_score, StratifiedKFold
from sklearn.ensemble import GradientBoostingClassifier
modelo = GradientBoostingClassifier(random_state=42)
# K-Fold estratificado (mantém proporção das classes em cada fold)
kfold = StratifiedKFold(n_splits=5, shuffle=True, random_state=42)
scores = cross_val_score(modelo, X, y, cv=kfold, scoring='accuracy')
print(f"Scores por fold: {scores.round(3)}")
print(f"Média: {scores.mean():.3f} +/- {scores.std():.3f}")
Ajuste de hiperparâmetros
Hiperparâmetros são configurações do modelo definidas antes do treinamento (ao contrário dos parâmetros, que o modelo aprende nos dados):
from sklearn.model_selection import GridSearchCV, RandomizedSearchCV
from sklearn.ensemble import RandomForestClassifier
# GridSearchCV: testa todas as combinações (exaustivo)
param_grid = {
'n_estimators': [50, 100, 200],
'max_depth': [3, 5, None],
'min_samples_split': [2, 5, 10]
}
grid_search = GridSearchCV(
RandomForestClassifier(random_state=42),
param_grid,
cv=5,
scoring='f1',
n_jobs=-1, # Usa todos os núcleos da CPU
verbose=1
)
grid_search.fit(X_treino, y_treino)
print(f"Melhores parâmetros: {grid_search.best_params_}")
print(f"Melhor score (CV): {grid_search.best_score_:.3f}")
# RandomizedSearchCV: mais eficiente para espaços grandes
from scipy.stats import randint
param_dist = {
'n_estimators': randint(50, 300),
'max_depth': [3, 5, 7, 10, None],
'min_samples_split': randint(2, 20)
}
random_search = RandomizedSearchCV(
RandomForestClassifier(random_state=42),
param_dist,
n_iter=30, # Testa 30 combinações aleatórias
cv=5,
scoring='f1',
random_state=42,
n_jobs=-1
)
random_search.fit(X_treino, y_treino)
Pipeline com scikit-learn
Pipelines garantem que os passos de pré-processamento sejam aplicados corretamente, evitando vazamento de dados (data leakage):
from sklearn.pipeline import Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.decomposition import PCA
from sklearn.svm import SVC
from sklearn.model_selection import cross_val_score
# Criando um pipeline completo
pipeline = Pipeline([
('scaler', StandardScaler()), # Passo 1: normalização
('pca', PCA(n_components=5)), # Passo 2: redução de dimensionalidade
('classificador', SVC(kernel='rbf', C=1.0)) # Passo 3: modelo
])
# O pipeline pode ser usado como qualquer estimador do sklearn
scores = cross_val_score(pipeline, X, y, cv=5, scoring='accuracy')
print(f"Acurácia com pipeline: {scores.mean():.3f} +/- {scores.std():.3f}")
# Funciona perfeitamente com GridSearchCV
param_grid = {
'pca__n_components': [3, 5, 8],
'classificador__C': [0.1, 1, 10]
}
grid = GridSearchCV(pipeline, param_grid, cv=5)
grid.fit(X_treino, y_treino)
Importância de features
Entender quais variáveis mais influenciam o modelo é essencial para interpretabilidade:
import pandas as pd
from sklearn.ensemble import RandomForestClassifier
from sklearn.datasets import load_breast_cancer
dados = load_breast_cancer()
modelo = RandomForestClassifier(n_estimators=100, random_state=42)
modelo.fit(dados.data, dados.target)
# Feature importance integrada ao RandomForest
importancias = pd.DataFrame({
'feature': dados.feature_names,
'importancia': modelo.feature_importances_
}).sort_values('importancia', ascending=False)
print(importancias.head(10))
# As 5 features mais importantes explicam a maior parte das decisoes do modelo
Rastreamento de experimentos com MLflow
Em projetos reais, você precisa rastrear múltiplos experimentos:
# pip install mlflow
import mlflow
import mlflow.sklearn
from sklearn.ensemble import RandomForestClassifier
from sklearn.metrics import accuracy_score, f1_score
mlflow.set_experiment("classificacao-cancer")
with mlflow.start_run():
# Parâmetros do experimento
n_estimators = 100
max_depth = 5
mlflow.log_param("n_estimators", n_estimators)
mlflow.log_param("max_depth", max_depth)
# Treinamento
modelo = RandomForestClassifier(
n_estimators=n_estimators,
max_depth=max_depth,
random_state=42
)
modelo.fit(X_treino, y_treino)
previsoes = modelo.predict(X_teste)
# Métricas
acc = accuracy_score(y_teste, previsoes)
f1 = f1_score(y_teste, previsoes)
mlflow.log_metric("accuracy", acc)
mlflow.log_metric("f1_score", f1)
# Salvando o modelo
mlflow.sklearn.log_model(modelo, "modelo")
print(f"Acurácia: {acc:.3f}, F1: {f1:.3f}")
Considerações éticas em Machine Learning
Modelos de ML tomam decisões que afetam pessoas reais. Algumas considerações importantes:
Viés nos dados: se os dados históricos refletem discriminacao passada, o modelo pode perpetuá-la. Audite seus dados e métricas por grupos demograficos.
Transparência: em domínios de alto impacto (crédito, saúde, justiça), modelos interpretáveis (regressão logística, árvores de decisão) podem ser preferíveis a caixas-pretas.
Privacidade: dados de treinamento podem conter informações sensíveis. Considere técnicas como differential privacy ou federated learning.
Monitoramento em produção: modelos degradam com o tempo (data drift). Monitore as métricas em produção e re-treine periodicamente.
Tipos de aprendizado
- Supervisionado: o modelo aprende com dados rotulados. Problemas de classificação (spam ou não-spam) e regressão (prever preço de imóvel).
- Não supervisionado: o modelo encontra padrões sem rótulos. Clustering (K-Means), redução de dimensionalidade (PCA).
- Por reforço: o modelo aprende por tentativa e erro, maximizando uma recompensa. Usado em jogos e robótica.
- Semi-supervisionado: combina poucos dados rotulados com muitos não rotulados.
Quando usar Machine Learning
Use ML quando houver dados suficientes para aprender padrões, quando as regras forem dificeis de escrever manualmente (reconhecimento de imagens, processamento de linguagem natural), ou quando o desempenho precisar melhorar automaticamente com mais dados. Evite ML quando um sistema baseado em regras simples funcionar bem, quando os dados forem insuficientes ou de baixa qualidade, ou quando a interpretabilidade for uma exigencia legal.
Termos Relacionados
- Pandas - Preparação e análise de dados
- NumPy - Operações numéricas base do ML
- Jupyter Notebook - Ambiente para experimentação
- Anaconda - Distribuição com pacotes de ML