---
title: "Machine Learning: O que É e Como Funciona | Python Brasil"
url: "https://python.dev.br/glossario/machine-learning/"
markdown_url: "https://python.dev.br/glossario/machine-learning.MD"
description: "Machine learning com Python: fluxo completo de trabalho, bias-variance tradeoff, validação cruzada, pipelines com scikit-learn e boas práticas."
date: "2025-06-30"
author: ""
---

# 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

```python
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

```python
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.

```python
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:

```python
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):

```python
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):

```python
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:

```python
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:

```python
# 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.

Muitas bibliotecas de ML modernas utilizam <a href="https://rustlang.com.br/blog/" target="_blank" rel="noopener" onclick="umami.track('portfolio-site-click', {source: 'python.dev.br', target: 'rustlang.com.br', content: 'machine-learning'})">Rust</a> para otimizar componentes críticos de performance, como tokenizers e processamento de dados.

## Termos Relacionados

- [Pandas](/glossario/pandas/) - Preparação e análise de dados
- [NumPy](/glossario/numpy/) - Operações numéricas base do ML
- [Jupyter Notebook](/glossario/jupyter-notebook/) - Ambiente para experimentação
- [Anaconda](/glossario/anaconda/) - Distribuição com pacotes de ML
