Machine Learning: Aprendizado Profundo com PyTorch

Última atualização: 2026-08-26

O aprendizado profundo permite que as máquinas descubram features automaticamente — sem necessidade de design manual. A rede encontra padrões nos dados por conta própria.

1. O que você vai aprender


2. A história real de um engenheiro de ML

(1) O problema: modelos lineares não capturam interações entre features

Bob usou regressão linear para prever vendas, mas só alcançou um R² de 0,78. Ele notou que a interação entre "gasto com anúncios × promoção" tinha um impacto enorme nas vendas, mas adicionar manualmente todos os termos de interação (20 features → 190 interações) era tedioso e propenso a erros. A premissa do modelo linear (y = wx + b) é simples demais — as interações reais entre features são muito mais complexas do que qualquer coisa que você projetaria à mão.

(2) A solução com aprendizado profundo

Redes neurais aprendem automaticamente interações entre features e transformações não lineares através de camadas ocultas — sem engenharia manual.

PYTHON
import torch.nn as nn

model = nn.Sequential(
    nn.Linear(20, 64),
    nn.ReLU(),
    nn.Linear(64, 32),
    nn.ReLU(),
    nn.Linear(32, 1),
)

(3) O resultado: o MLP descobre interações automaticamente, R² salta para 0,86

Bob substituiu a regressão linear por um MLP de 3 camadas. A rede aprendeu automaticamente o padrão "alto gasto com anúncios + promoção = pico de vendas", elevando o R² de 0,78 para 0,86 — sem projetar manualmente um único termo de interação.


3. Aprendizado profundo vs. ML tradicional

(1) Quando escolher aprendizado profundo

Critério ML tradicional (ex.: XGBoost) Aprendizado profundo (ex.: MLP/CNN)
Tipo de dado Dados tabulares Imagens / texto / áudio / tabular complexo
Volume de dados <100k >100k
Engenharia de features Design manual necessário Aprende features automaticamente
Tempo de treinamento Minutos a horas Horas a dias
Hardware CPU é suficiente GPU recomendada
Interpretabilidade Alta (coeficientes / importâncias) Baixa (caixa-preta)
Desempenho tabular Geralmente melhor Não necessariamente melhor

▶ Exemplo: Instalando e verificando o PyTorch

PYTHON
import torch

print(f"Versão do PyTorch: {torch.__version__}")
print(f"CUDA disponível: {torch.cuda.is_available()}")
if torch.cuda.is_available():
    print(f"GPU: {torch.cuda.get_device_name(0)}")

# Operações básicas com tensores
a = torch.tensor([1.0, 2.0, 3.0])
b = torch.tensor([4.0, 5.0, 6.0])
print(f"a + b = {a + b}")
print(f"a * b = {a * b}")
print(f"Média de a: {a.mean()}")

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

4. Conceitos centrais do PyTorch

(1) Operações com tensores

▶ Exemplo: Criando e manipulando tensores

PYTHON
import torch

# Criar tensores
a = torch.zeros(3, 4)
b = torch.ones(2, 3)
c = torch.randn(3, 3)  # Distribuição normal
d = torch.arange(0, 10, 2)

# A partir de NumPy
import numpy as np
arr = np.array([1, 2, 3])
t = torch.from_numpy(arr)

# Tensor para NumPy
back = t.numpy()

# Tensor em GPU
if torch.cuda.is_available():
    gpu_tensor = torch.randn(3, 3).cuda()
    cpu_back = gpu_tensor.cpu()

# Remodelar
x = torch.arange(12)
matrix = x.reshape(3, 4)
print(f"Shape: {matrix.shape}")

# Broadcasting
a = torch.ones(3, 1)
b = torch.ones(1, 4)
c = a + b  # (3,4)
print(f"Shape do resultado do broadcasting: {c.shape}")

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

(2) Autograd: diferenciação automática

▶ Exemplo: diferenciação automática

PYTHON
import torch

# Exemplo de diferenciação automática
x = torch.tensor([2.0], requires_grad=True)
y = x ** 2 + 3 * x + 1  # y = x² + 3x + 1
y.backward()             # dy/dx = 2x + 3

print(f"x = {x.item()}")
print(f"y = {y.item()}")
print(f"dy/dx = {x.grad.item()}")  # Deve ser 2*2+3 = 7
print(f"Verificação manual: 2*2 + 3 = {2*2+3}")

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

(3) Definindo modelos com nn.Module

▶ Exemplo: Um modelo MLP personalizado

PYTHON
import torch
import torch.nn as nn

class SalesPredictMLP(nn.Module):
    def __init__(self, input_dim, hidden_dims, output_dim=1):
        super().__init__()
        layers = []
        prev_dim = input_dim
        for hidden_dim in hidden_dims:
            layers.append(nn.Linear(prev_dim, hidden_dim))
            layers.append(nn.BatchNorm1d(hidden_dim))
            layers.append(nn.ReLU())
            layers.append(nn.Dropout(0.2))
            prev_dim = hidden_dim
        layers.append(nn.Linear(prev_dim, output_dim))
        self.network = nn.Sequential(*layers)

    def forward(self, x):
        return self.network(x)

model = SalesPredictMLP(input_dim=20, hidden_dims=[64, 32], output_dim=1)
print(model)
print(f"Total de parâmetros: {sum(p.numel() for p in model.parameters()):,}")

Saída:

TEXT 📖 Somente leitura
# Funções definidas com sucesso

5. O pipeline completo de treinamento MLP

(1) O loop de treinamento

100%
sequenceDiagram
    participant Data as DataLoader
    participant Fwd as Forward Pass
    participant Loss as Calcular Perda
    participant Zero as Zerar Gradientes
    participant Bwd as Backward Pass
    participant Step as Passo do Otimizador

    loop Cada Época
        Data->>Fwd: Batch de (X, y)
        Fwd->>Loss: y_pred = model(X)
        Loss->>Zero: loss = criterion(y_pred, y)
        Zero->>Bwd: optimizer.zero_grad()
        Bwd->>Step: loss.backward()
        Step->>Data: optimizer.step()
    end

▶ Exemplo: Pipeline completo de treinamento MLP

PYTHON
import torch
import torch.nn as nn
from torch.utils.data import DataLoader, TensorDataset
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.metrics import r2_score, mean_absolute_error
import numpy as np

# Gerar dados
rng = np.random.default_rng(42)
n = 5000
X = rng.uniform(0, 100, (n, 20))
y = (50 + X[:, :5] @ [0.8, 1.2, -0.5, 0.3, 0.1]
     + 0.5 * X[:, 0] * X[:, 1]  # Interação
     + np.sin(X[:, 2]) * 5       # Não linear
     + rng.normal(0, 5, n))

X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)

scaler = StandardScaler()
X_train_s = scaler.fit_transform(X_train)
X_test_s = scaler.transform(X_test)

# Criar DataLoaders
train_ds = TensorDataset(torch.FloatTensor(X_train_s), torch.FloatTensor(y_train))
test_ds = TensorDataset(torch.FloatTensor(X_test_s), torch.FloatTensor(y_test))
train_loader = DataLoader(train_ds, batch_size=64, shuffle=True)
test_loader = DataLoader(test_ds, batch_size=256)

# Modelo, perda, otimizador
model = SalesPredictMLP(input_dim=20, hidden_dims=[128, 64, 32])
criterion = nn.MSELoss()
optimizer = torch.optim.Adam(model.parameters(), lr=0.001, weight_decay=1e-4)
scheduler = torch.optim.lr_scheduler.ReduceLROnPlateau(optimizer, patience=10, factor=0.5)

# Loop de treinamento
train_losses, val_losses = [], []
best_val_loss = float("inf")

for epoch in range(100):
    model.train()
    epoch_loss = 0
    for X_batch, y_batch in train_loader:
        y_pred = model(X_batch).squeeze()
        loss = criterion(y_pred, y_batch)
        optimizer.zero_grad()
        loss.backward()
        optimizer.step()
        epoch_loss += loss.item()

    avg_train_loss = epoch_loss / len(train_loader)
    train_losses.append(avg_train_loss)

    # Validação
    model.eval()
    val_loss = 0
    with torch.no_grad():
        for X_batch, y_batch in test_loader:
            y_pred = model(X_batch).squeeze()
            val_loss += criterion(y_pred, y_batch).item()
    avg_val_loss = val_loss / len(test_loader)
    val_losses.append(avg_val_loss)

    scheduler.step(avg_val_loss)

    # Early stopping
    if avg_val_loss < best_val_loss:
        best_val_loss = avg_val_loss
        best_state = model.state_dict().copy()

    if epoch % 20 == 0:
        print(f"Época {epoch:3d}: perda_treino={avg_train_loss:.4f}, perda_val={avg_val_loss:.4f}")

# Carregar o melhor modelo e avaliar
model.load_state_dict(best_state)
model.eval()
with torch.no_grad():
    y_pred = model(torch.FloatTensor(X_test_s)).squeeze().numpy()

print(f"\nMLP R²: {r2_score(y_test, y_pred):.4f}")
print(f"MLP MAE: {mean_absolute_error(y_test, y_pred):.2f}")

Saída:

TEXT 📖 Somente leitura
# Executado com sucesso

6. Confronto MLP do Bob vs. Regressão Linear

▶ Exemplo: Cara a cara no mesmo conjunto de dados

PYTHON
from sklearn.linear_model import LinearRegression
from sklearn.metrics import r2_score, mean_absolute_error

# Linha de base de regressão linear
lr = LinearRegression()
lr.fit(X_train_s, y_train)
lr_pred = lr.predict(X_test_s)

print("=" * 50)
print("COMPARAÇÃO DE MODELOS")
print("=" * 50)
print(f"Regressão Linear: R²={r2_score(y_test, lr_pred):.4f}, MAE={mean_absolute_error(y_test, lr_pred):.2f}")
print(f"MLP (3 camadas):     R²={r2_score(y_test, y_pred):.4f}, MAE={mean_absolute_error(y_test, y_pred):.2f}")

Saída:

TEXT 📖 Somente leitura
=
COMPARAÇÃO DE MODELOS
=
Dimensão LinearRegression MLP (3 camadas)
0,78 0,86
MAE 12,5 9,3
Interações de features Adicionadas manualmente Aprendidas automaticamente
Tempo de treinamento <1s ~30s
Interpretabilidade Alta (coeficientes) Baixa (caixa-preta)
Risco de sobreajuste Baixo Médio
⚠️ Nota: Em dados tabulares, XGBoost/LightGBM geralmente superam MLPs e treinam mais rápido. A vantagem do MLP está em aprender automaticamente interações de features e transformações não lineares. Na prática, tente GBDT primeiro — se não for bom o suficiente, então tente um MLP.


❓ Perguntas Frequentes

P: Devo aprender PyTorch ou TensorFlow? R: Para pesquisa e aprendizado, vá com PyTorch — é mais pythônico e mais fácil de depurar. Para implantação em produção, depende da stack da sua equipe. Ambos são igualmente capazes, mas PyTorch domina na academia.

P: Quantas camadas ocultas e neurônios meu MLP deve ter? R: Uma regra prática — comece com 1–2 camadas ocultas, diminuindo a contagem de neurônios como input_dim → 64 → 32. Profundidade/largura demais leva a sobreajuste; rasa/estreita demais leva a subajuste. Ajuste usando um conjunto de validação.

P: Adam ou SGD — qual é melhor? R: Na maioria dos casos, Adam vence (taxas de aprendizado adaptativas, convergência mais rápida). SGD + Momentum pode generalizar melhor em certas tarefas. Comece com Adam; mude para SGD para ajuste fino.

P: O que são BatchNorm e Dropout? R: BatchNorm normaliza a saída de cada camada (treinamento mais rápido + estabilidade); Dropout zera aleatoriamente neurônios (evita sobreajuste). Ambos são técnicas padrão de treinamento.

P: Como escolher uma learning rate? R: Comece com 0,001 (Adam) ou 0,01 (SGD). Combine com um scheduler para decaimento automático (ReduceLROnPlateau). Treinamento instável? Diminua o lr. Convergindo muito devagar? Aumente-o.

P: Para dados tabulares, devo usar um MLP ou XGBoost? R: Prefira XGBoost — geralmente é melhor e mais rápido em dados tabulares. A força do MLP é o aprendizado automático de interações de features. Se GBDT já funciona bem, você não precisa de um MLP.


📖 Resumo


📝 Exercícios

  1. Básico (Dificuldade ⭐): Crie um MLP de 2 camadas em PyTorch (entrada 4-dim → 16 → 8 → saída 1). Imprima a arquitetura do modelo e a contagem total de parâmetros. Dica: nn.Sequential + sum(p.numel()...).
  2. Intermediário (Dificuldade ⭐⭐): Use um MLP para prever preços de imóveis do California Housing. Implemente um loop de treinamento completo (com validação e early stopping) e compare o R² com a Regressão Linear. Dica: consulte o pipeline de treinamento completo na Seção 5.
  3. Desafio (Dificuldade ⭐⭐⭐): Experimente diferentes arquiteturas MLP (1/2/3 camadas, variando tamanhos ocultos). Plote uma curva "número de camadas ocultas vs. R²" e encontre a arquitetura ótima. Dica: itere sobre diferentes configurações de hidden_dims e registre o R² de validação.

← Anterior: Fundamentos de NLP | Próximo: Redes Neurais Convolucionais →

Web-Tutorial.com

Equipe Técnica Web-Tutorial

Uma plataforma de tutoriais mantida por diversos desenvolvedores. Cada tutorial é escrito e revisado por profissionais da área correspondente. Trabalhamos para manter nosso conteúdo preciso e confiável — se encontrar algum problema, avise-nos.

100%