AI: Redes Neurais

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

"Aprendizado profundo" pode parecer misterioso e complexo, mas seu bloco básico de construção — o neurônio — é simplesmente uma soma ponderada seguida de uma transformação não linear. Começando com o perceptron, este capítulo o guia passo a passo através de redes multicamadas, funções de ativação, propagação para frente e retropropagação, e mostra como implementar um MLP do zero usando Python puro que pode resolver o problema do XOR.

1. O Que Você Vai Aprender



2. História: O "Cérebro" por Trás de 10 Linhas de Código

(1) Ponto de Dor: O que exatamente é Deep Learning?

Bob tinha ouvido que "deep learning" podia reconhecer rostos, traduzir idiomas e escrever artigos, mas ele não tinha a menor ideia do que era uma rede neural. Ele tentou pesquisar na Wikipedia, mas a tela cheia de derivadas parciais e da regra da cadeia fez ele fechar a página imediatamente. "Alguém não pode simplesmente me explicar nos termos mais simples o que um 'neurônio' realmente faz?"

(2) Os 10 linhas de código da Alice

Alice sorriu enquanto abria o Python e escrevia um perceptron em 10 linhas de código — ele recebe dois números como entrada e produz 0 ou 1 como saída:

PYTHON
# Um único perceptron: porta AND
def perceptron(x1, x2, w1=1, w2=1, b=-1.5):
    return 1 if w1 * x1 + w2 * x2 + b > 0 else 0

for x1, x2 in [(0,0),(0,1),(1,0),(1,1)]:
    print(f"AND({x1},{x2}) = {perceptron(x1, x2)}")
💻 Saída:

TEXT 📖 Somente leitura
AND(0,0) = 0
AND(0,1) = 0
AND(1,0) = 0
AND(1,1) = 1

Bob percebeu: "Isso não é apenas votação ponderada? Ambas as entradas são definidas como 1, e se a soma ponderada exceder o limiar, a saída é 1 — então uma rede neural é apenas uma série dessas unidades de decisão simples conectadas juntas!"

(3) Benefícios: De unidades simples a redes poderosas

Alice assentiu. "É isso mesmo. Um único perceptron só pode realizar classificação linear, mas ao empilhar dezenas ou centenas de perceptrons em uma rede multicamadas, podemos aproximar funções extremamente complexas — e é aí que o deep learning começa."


3. Perceptron—A Rede Neural Mais Simples

(1) Definição Matemática de um Perceptron

O perceptron, proposto pelo psicólogo Rosenblatt em 1958, é um dos modelos mais antigos de um neurônio artificial. Ele recebe múltiplas entradas $x_1, x_2, \ldots, x_n$, cada uma com um peso $w_i$, mais um viés $b$, e finalmente produz a saída 0 ou 1 através de uma função degrau:

$$y = \text{step}\left(\sum_{i=1}^{n} w_i x_i + b\right)$$

Em particular, $\text{step}(z) = 1$ se $z > 0$, e $0$ caso contrário.

Intuição: Imagine que você está decidindo se vai sair para correr—temperatura, qualidade do ar, se você tem tempo e seu humor—cada fator tem um "peso", e se o total exceder seu "limite de preguiça", você sai.

(2) O Significado Geométrico do Perceptron

Um perceptron desenha uma linha reta $w_1 x_1 + w_2 x_2 + b = 0$ no espaço bidimensional, produzindo a saída 1 de um lado da linha e 0 do outro. Ele pode resolver perfeitamente problemas linearmente separáveis, como AND e OR, mas não consegue resolver o problema do XOR—porque as duas classes de pontos em um problema XOR não podem ser separadas por uma única linha reta.

▶ Exemplo: Uma Implementação Pura em Python de uma Porta AND com Perceptron (Dificuldade: ⭐)

PYTHON
# Porta AND com Perceptron e treinamento
def step(z):
    return 1 if z > 0 else 0

def train_perceptron(X, y, lr=0.1, epochs=10):
    n_features = len(X[0])
    weights = [0.0] * n_features
    bias = 0.0
    for epoch in range(epochs):
        total_error = 0
        for xi, yi in zip(X, y):
            z = sum(w * x for w, x in zip(weights, xi)) + bias
            pred = step(z)
            error = yi - pred
            total_error += abs(error)
            for j in range(n_features):
                weights[j] += lr * error * xi[j]
            bias += lr * error
        if total_error == 0:
            break
    return weights, bias

X = [[0,0],[0,1],[1,0],[1,1]]
y_and = [0, 0, 0, 1]
w, b = train_perceptron(X, y_and)
print(f"Weights: {w}, Bias: {b}")
for xi in X:
    print(f"AND{xi} = {step(sum(ww*xx for ww,xx in zip(w,xi)) + b)}")
💻 Saída:

TEXT 📖 Somente leitura
Weights: [0.2, 0.1], Bias: -0.2
AND[0, 0] = 0
AND[0, 1] = 0
AND[1, 0] = 0
AND[1, 1] = 1
💡 Dica: As regras de aprendizado de um perceptron são muito simples—se a previsão estiver correta, os pesos permanecem inalterados; se a previsão estiver incorreta, os pesos são ajustados na direção do erro. Esta é a forma mais básica de "aprender com os erros".



4. Arquitetura do Perceptron Multicamadas (MLP)

(1) Por que são necessárias múltiplas camadas?

Um perceptron de camada única só pode traçar linhas retas e não consegue resolver o problema XOR. No entanto, se as saídas de dois perceptrons forem alimentadas em um terceiro perceptron, torna-se possível combinar duas linhas retas para formar uma fronteira não-linear. Esta é a ideia central por trás do perceptron multicamadas (MLP).

(2) A Estrutura de Três Camadas de um MLP

Camada Função Exemplo
Camada de entrada Recebe os recursos brutos 2 nós (x₁, x₂)
Camada oculta Extrai recursos intermediários 4 nós (recursos aprendidos)
Camada de saída Fornece a previsão final 1 nó (0 ou 1)

Cada nó em cada camada está conectado a todos os nós da camada anterior (totalmente conectado), e a força dessas conexões é representada por pesos.

(3) O Processo de Propagação Direta em Redes Neurais

100%
graph LR
    X1["x₁"] --> H1["h₁ (sigmoid)"]
    X1 --> H2["h₂ (sigmoid)"]
    X2["x₂"] --> H1
    X2 --> H2
    H1 --> Y["y (saída)"]
    H2 --> Y
    style X1 fill:#e1f5fe
    style X2 fill:#e1f5fe
    style H1 fill:#fff9c4
    style H2 fill:#fff9c4
    style Y fill:#c8e6c9

Intuição: A camada de entrada é como os olhos, as camadas ocultas são como as regiões de processamento do cérebro, e a camada de saída é como a boca falando a resposta. Cada camada realiza uma "soma ponderada + transformação não-linear."

(4) Comparação: Perceptron vs. MLP vs. Redes Neurais Profundas

Dimensão Perceptron MLP Rede Neural Profunda
Número de camadas 1 camada (sem camadas ocultas) 2–3 camadas ≥ 4 camadas (incluindo múltiplas camadas ocultas)
Capacidades Classificação Linear Classificação/Regressão Não-linear Extração Automática de Recursos Complexos
Treinamento Regras do Perceptron Retropropagação Retropropagação + Técnicas de Otimização
Aplicações Típicas Portas lógicas simples Classificação/regressão em pequena escala Reconhecimento de imagens, PLN, geração
Número de parâmetros Dezenas Centenas a milhares Dezenas de milhões a bilhões
Modelos Representativos Perceptron de Rosenblatt MLP de 2 camadas CNN, Transformer


5. Funções de Ativação—Adicionando Não-linearidade à Rede

(1) Por que as Funções de Ativação São Necessárias?

Sem funções de ativação, independentemente do número de camadas, uma rede é essencialmente uma transformação linear—a composição de múltiplas transformações lineares permanece linear. As funções de ativação introduzem não-linearidade, permitindo que a rede ajuste curvas e limites complexos.

Analogia: Transformações lineares são como "esticar e girar"; não importa quantas vezes você as estique ou gire, o resultado ainda é uma linha reta ou um plano. Funções de ativação são como "dobrar"—dobre um pedaço de papel uma vez, e o espaço muda.

(2) Comparação de Funções de Ativação Comuns

Função Fórmula Intervalo de Saída Vantagens Desvantagens
Sigmoid $\sigma(z)=\frac{1}{1+e^{-z}}$ (0, 1) A saída pode ser tratada como uma probabilidade Gradientes que desaparecem, centro não-zero
Tanh $\tanh(z)=\frac{e^z-e^{-z}}{e^z+e^{-z}}$ (-1, 1) Centrado em zero O gradiente desaparece
ReLU $\max(0, z)$ [0, +∞) Computação rápida, mitiga o problema de gradiente desaparecendo Morte do neurônio (gradiente é 0 na região negativa)
Leaky ReLU $\max(0.01z, z)$ (-∞, +∞) Aborda a morte do neurônio Requer ajuste de hiperparâmetros

▶ Exemplo: Comparando os Valores de Saída de Diferentes Funções de Ativação (Dificuldade: ⭐)

PYTHON
# Compare activation functions
import numpy as np

def sigmoid(z):
    return 1 / (1 + np.exp(-z))

def tanh(z):
    return np.tanh(z)

def relu(z):
    return np.maximum(0, z)

def leaky_relu(z, alpha=0.01):
    return np.where(z > 0, z, alpha * z)

z_values = np.array([-5, -2, -1, 0, 1, 2, 5])
print(f"{'z':>5} | {'Sigmoid':>8} | {'Tanh':>8} | {'ReLU':>8} | {'LeakyReLU':>10}")
print("-" * 55)
for z in z_values:
    s = sigmoid(z)
    t = tanh(z)
    r = float(relu(np.array([z]))[0])
    lr = float(leaky_relu(np.array([z]))[0])
    print(f"{z:5.1f} | {s:8.4f} | {t:8.4f} | {r:8.4f} | {lr:10.4f}")
💻 Saída:

TEXT 📖 Somente leitura
    z |  Sigmoid |     Tanh |     ReLU |  LeakyReLU
-------------------------------------------------------
 -5.0 |   0.0067 |  -0.9999 |   0.0000 |    -0.0500
 -2.0 |   0.1192 |  -0.9640 |   0.0000 |    -0.0200
 -1.0 |   0.2689 |  -0.7616 |   0.0000 |    -0.0100
  0.0 |   0.5000 |   0.0000 |   0.0000 |     0.0000
  1.0 |   0.7311 |   0.7616 |   1.0000 |     1.0000
  2.0 |   0.8808 |   0.9640 |   2.0000 |     2.0000
  5.0 |   0.9933 |   0.9999 |   5.0000 |     5.0000
💡 Dica: Os gradientes das funções sigmoid e tanh se aproximam de 0 (gradiente desaparecendo) quando |z| é grande, enquanto o gradiente do ReLU é sempre 1 no intervalo positivo; portanto, o ReLU é tipicamente a escolha preferida para redes neurais profundas.



6. Propagação para Frente e Retropropagação

(1) Propagação para frente: Da entrada à saída

A propagação para frente é o processo pelo qual os dados viajam da camada de entrada, passando por cada camada, até a camada de saída:

  1. Calcular a entrada da camada oculta: $z^{(1)} = W^{(1)} \cdot x + b^{(1)}$
  2. Aplicar a função de ativação: $h = \sigma(z^{(1)})$
  3. Calcular a entrada da camada de saída: $z^{(2)} = W^{(2)} \cdot h + b^{(2)}$
  4. Previsão de saída: $\hat{y} = \sigma(z^{(2)})$

(2) Função de Perda: Mede a discrepância entre a previsão e o valor real

O Erro Quadrático Médio (MSE) é comumente usado como função de perda:

A perda é o quadrado da diferença entre o valor real e o valor previsto.

Quanto menor a perda, mais precisa é a previsão. O objetivo do treinamento é encontrar os pesos que minimizem a perda.

(3) Retropropagação: Do erro à atualização dos pesos

A ideia central da retropropagação: Partindo do erro na camada de saída, calcular a "contribuição" de cada peso para o erro, propagando-o para trás através das camadas da rede, e então ajustar os pesos.

Analogia intuitiva: Uma fábrica tem um problema com seus produtos—

Matematicamente, esta é a Regra da Cadeia: $\frac{\partial L}{\partial w} = \frac{\partial L}{\partial \hat{y}} \cdot \frac{\partial \hat{y}}{\partial z} \cdot \frac{\partial z}{\partial w}$

(4) Tabela de Conceitos-chave na Retropropagação

Conceito Significado Intuição
Gradiente A derivada parcial da perda em relação aos pesos Em qual direção e em qual medida os pesos devem ser ajustados
Taxa de Aprendizado Tamanho do passo por iteração Muito grande → ultrapassa o ótimo; muito pequeno → o treinamento é muito lento
Regra da Cadeia Passagem do gradiente camada por camada Rastreando "quem é o responsável" camada por camada da saída para a entrada
Atualização de Peso $w \leftarrow w - \eta \cdot \frac{\partial L}{\partial w}$ Dá um passo na direção oposta ao gradiente
Gradientes Desvanecentes Os gradientes diminuem a cada camada e se aproximam de 0 As primeiras camadas aprendem quase nada
Explosão de Gradientes Os gradientes amplificam-se camada por camada As atualizações de peso são muito agressivas, fazendo o modelo se tornar instável

(5) Intuição para Superfícies de Perda

Imagine que você está de pé em uma montanha e seu objetivo é chegar ao fundo do vale (perda mínima). A cada passo, você segue pela encosta mais íngreme—isso é descida de gradiente. A taxa de aprendizado determina o tamanho dos seus passos:



7. Experimente Rapidamente um MLP com sklearn

▶ Exemplo: Classificação usando o MLPClassifier do sklearn (Dificuldade: ⭐)

PYTHON
# MLPClassifier no problema XOR
from sklearn.neural_network import MLPClassifier
import numpy as np

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

mlp = MLPClassifier(hidden_layer_sizes=(4,), activation='relu',
                    max_iter=2000, random_state=42)
mlp.fit(X, y)

print("Previsões do XOR:")
for xi in X:
    print(f"  {xi} -> {mlp.predict([xi])[0]}")
print(f"Acurácia: {mlp.score(X, y):.2f}")
💻 Saída:

TEXT 📖 Somente leitura
Previsões do XOR:
  [0 0] -> 0
  [0 1] -> 1
  [1 0] -> 1
  [1 1] -> 0
Acurácia: 1.00
💡 Dica: O MLPClassifier do sklearn trata automaticamente de todos os detalhes, incluindo propagação para frente, retropropagação e inicialização de pesos. Uma vez que você entenda os princípios subjacentes, usar a biblioteca é a abordagem mais eficiente.

▶ Exemplo: Visualizando Mudanças nas Fronteiras de Decisão (Dificuldade: ⭐⭐)

PYTHON
# Visualizar fronteira de decisão do MLP no XOR
import numpy as np
import matplotlib.pyplot as plt
from sklearn.neural_network import MLPClassifier

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

fig, axes = plt.subplots(1, 3, figsize=(15, 4))
hidden_configs = [(2,), (4,), (8,)]

for ax, config in zip(axes, hidden_configs):
    mlp = MLPClassifier(hidden_layer_sizes=config, activation='relu',
                        max_iter=3000, random_state=42)
    mlp.fit(X, y)

    xx, yy = np.meshgrid(np.linspace(-0.5, 1.5, 100),
                         np.linspace(-0.5, 1.5, 100))
    Z = mlp.predict(np.c_[xx.ravel(), yy.ravel()]).reshape(xx.shape)

    ax.contourf(xx, yy, Z, alpha=0.3, cmap='coolwarm')
    ax.scatter(X[:,0], X[:,1], c=y, cmap='coolwarm', edgecolors='k', s=100)
    ax.set_title(f"Oculta: {config}, Acurácia: {mlp.score(X,y):.2f}")
    ax.set_xlabel("x1")
    ax.set_ylabel("x2")

plt.tight_layout()
plt.savefig("mlp_decision_boundary.png", dpi=100)
plt.show()

Saída: (Execute o exemplo para ver a saída real, ou consulte a nota de saída esperada nos comentários do código acima.)

💡 Dica: Quanto mais nós em uma camada oculta, mais flexível é a fronteira de decisão - mas mais propensa ela é a overfitting. Dois nós podem não ser suficientes para aprender o XOR, enquanto oito nós são mais do que suficientes.

▶ Exemplo: Como o Número de Nós em uma Camada Oculta Afeta o Desempenho (Dificuldade: ⭐⭐)

PYTHON
# Efeito do tamanho da camada oculta na perda de treinamento
import numpy as np
from sklearn.neural_network import MLPClassifier
import matplotlib.pyplot as plt

X = np.array([[0,0],[0,1],[1,0],[1,1]])
y = np.array([0, 1, 1, 0])

fig, ax = plt.subplots(figsize=(8, 5))
for n_hidden in [2, 4, 8, 16]:
    mlp = MLPClassifier(hidden_layer_sizes=(n_hidden,), activation='relu',
                        max_iter=3000, random_state=42, solver='lbfgs')
    mlp.fit(X, y)
    ax.plot(range(len(mlp.loss_curve_)), mlp.loss_curve_,
            label=f"Oculta={n_hidden}")

ax.set_xlabel("Iteração")
ax.set_ylabel("Perda")
ax.set_title("Perda de Treinamento vs Tamanho da Camada Oculta")
ax.legend()
ax.set_yscale('log')
plt.savefig("hidden_size_loss.png", dpi=100)
plt.show()

Saída: (Execute o exemplo para ver a saída real, ou consulte a nota de saída esperada nos comentários do código acima.)

💡 Dica: Modelos com mais nós ocultos normalmente convergem mais rápido e têm perda menor, mas têm mais parâmetros e podem sofrer overfitting em conjuntos de dados pequenos.



8. Deep Learning = Redes Neurais de Múltiplas Camadas

(1) Comparação entre ML Tradicional e Deep Learning

Dimensão Aprendizado de Máquina Tradicional Deep Learning
Engenharia de Features Requer design e seleção manual de features Aprende automaticamente as features a partir dos dados
Requisitos de Volume de Dados Uma pequena quantidade de dados é suficiente Geralmente requer uma grande quantidade de dados
Recursos Computacionais Apenas CPU Geralmente requer GPU
Interpretabilidade do Modelo Alta (árvores de decisão, modelos lineares) Baixa (caixa preta)
Teto de Desempenho Limitado pela qualidade das features Escala com os dados e o tamanho do modelo
Algoritmos Representativos SVM, Random Forest, XGBoost CNN, RNN, Transformer
Cenários Aplicáveis Dados estruturados, pequenas amostras Dados não estruturados, como imagens, texto e fala

(2) O que significa "profundo"?

"Profundidade" refere-se ao número de camadas ocultas. Há um consenso geral de que:

Quanto mais camadas, mais abstratas são as features que a rede pode extrair—a primeira camada pode aprender bordas, a segunda pode aprender texturas e a terceira pode aprender componentes; conforme avançamos na rede, as features tornam-se cada vez mais "semânticas".

(3) Mais profundidade não é necessariamente melhor

Uma rede mais profunda não significa necessariamente um melhor desempenho. Camadas demais podem levar a:

A profundidade do modelo deve ser escolhida com base na complexidade da tarefa e na quantidade de dados—assim como construir um arranha-céu: nem sempre mais alto é melhor; é preciso considerar a fundação e o orçamento.


9. Exercício Prático Abrangente: Implementando um Classificador MLP do Zero

▶ Exemplo: Implementando uma MLP do Zero para Resolver o Problema XOR (Dificuldade: ⭐⭐⭐)

Abaixo, implementaremos uma MLP completa usando Python puro (sem quaisquer frameworks), incluindo propagação para frente, retropropagação e o loop de treinamento, com o objetivo de resolver o problema XOR.

PYTHON
# MLP from scratch: solve XOR with pure Python + NumPy
import numpy as np

# --- Activation functions and their derivatives ---
def sigmoid(z):
    return 1 / (1 + np.exp(-np.clip(z, -500, 500)))

def sigmoid_deriv(a):
    return a * (1 - a)

# --- MLP class ---
class MLP:
    def __init__(self, layer_sizes):
        # layer_sizes e.g. [2, 4, 1] => 2-input, 4-hidden, 1-output
        self.weights = []
        self.biases = []
        for i in range(len(layer_sizes) - 1):
            w = np.random.randn(layer_sizes[i], layer_sizes[i+1]) * 0.5
            b = np.zeros((1, layer_sizes[i+1]))
            self.weights.append(w)
            self.biases.append(b)

    def forward(self, X):
        self.activations = [X]
        for i in range(len(self.weights)):
            z = self.activations[-1] @ self.weights[i] + self.biases[i]
            a = sigmoid(z)
            self.activations.append(a)
        return self.activations[-1]

    def backward(self, y, lr=0.5):
        m = y.shape[0]
        deltas = [None] * len(self.weights)

        # Output layer delta
        output = self.activations[-1]
        deltas[-1] = (output - y) * sigmoid_deriv(output)

        # Hidden layer deltas (backprop)
        for i in range(len(self.weights) - 2, -1, -1):
            deltas[i] = (deltas[i+1] @ self.weights[i+1].T) * sigmoid_deriv(self.activations[i+1])

        # Update weights and biases
        for i in range(len(self.weights)):
            self.weights[i] -= lr * (self.activations[i].T @ deltas[i]) / m
            self.biases[i] -= lr * np.mean(deltas[i], axis=0, keepdims=True)

    def train(self, X, y, epochs=5000, lr=0.5):
        self.losses = []
        for epoch in range(epochs):
            pred = self.forward(X)
            loss = np.mean((y - pred) ** 2) / 2
            self.losses.append(loss)
            self.backward(y, lr)
            if epoch % 1000 == 0:
                print(f"Epoch {epoch:4d} | Loss: {loss:.6f}")

    def predict(self, X):
        return (self.forward(X) > 0.5).astype(int)

# --- Train on XOR ---
np.random.seed(42)
X = np.array([[0,0],[0,1],[1,0],[1,1]], dtype=float)
y = np.array([[0],[1],[1],[0]], dtype=float)

mlp = MLP([2, 4, 1])
mlp.train(X, y, epochs=5000, lr=1.0)

print("\nFinal Predictions:")
preds = mlp.predict(X)
for i in range(4):
    print(f"  XOR{X[i].astype(int).tolist()} = {preds[i,0]} (target: {y[i,0].astype(int)})")
💻 Saída:

TEXT 📖 Somente leitura
Epoch    0 | Loss: 0.132415
Epoch 1000 | Loss: 0.004726
Epoch 2000 | Loss: 0.002517
Epoch 3000 | Loss: 0.001751
Epoch 4000 | Loss: 0.001330

Final Predictions:
  XOR[0, 0] = 0 (target: 0)
  XOR[0, 1] = 1 (target: 1)
  XOR[1, 0] = 1 (target: 1)
  XOR[1, 1] = 0 (target: 0)
💡 Dica: XOR é um problema não linear clássico — um perceptron de camada única não pode resolvê-lo, mas uma MLP 2→4→1 pode resolvê-lo perfeitamente em apenas alguns milhares de iterações. Isso demonstra o poder das redes multicamadas combinadas com funções de ativação não lineares.


❓ Perguntas Frequentes

P O que significa “profundo” no aprendizado profundo?
R “Profundo” refere-se ao número de camadas ocultas. MLPs tradicionais têm apenas 1–2 camadas ocultas, enquanto redes profundas geralmente têm 4 ou mais camadas — às vezes até centenas. “Profundo” implica mais níveis de abstração de características, com cada camada extraindo características de nível superior com base na camada anterior.
P Por que as funções de ativação são necessárias?
R Sem funções de ativação, a composição de múltiplas transformações lineares ainda seria linear — não importa quantas camadas você empilhe, seria equivalente a uma única transformação linear de camada única. Funções de ativação introduzem não linearidade, permitindo que a rede se ajuste a curvas complexas e limites de decisão. Sem elas, o aprendizado profundo não seria possível.
P E se a retropropagação for muito complicada?
R Você não precisa implementar a retropropagação manualmente. Os frameworks modernos (PyTorch, TensorFlow) computam gradientes automaticamente usando diferenciação automática (Autograd). Existem apenas três conceitos-chave que você precisa entender: ① Começar do erro na camada de saída e propagar para trás camada por camada; ② A “responsabilidade” de cada camada é calculada usando a regra da cadeia; ③ Os pesos são atualizados na direção oposta do gradiente. Quando você está realmente escrevendo código, o framework lida com toda a diferenciação para você.
P Quantas camadas e nós uma rede neural precisa?
R Não há uma fórmula única. Na prática: ① Comece com uma rede pequena (1–2 camadas ocultas, 32–128 nós por camada); ② Monitore os erros de treinamento e validação para determinar se deve adicionar mais camadas; ③ Use menos nós quando o conjunto de dados for pequeno para evitar overfitting; ④ Considere redes mais profundas e amplas somente quando o conjunto de dados for grande e a tarefa for complexa. O ajuste de hiperparâmetros (busca em grade, busca aleatória) é uma abordagem comum.
P O aprendizado profundo é sempre melhor que o aprendizado de máquina tradicional?
R Não necessariamente. O aprendizado profundo tem vantagens claras com dados não estruturados, como imagens, texto e fala, mas o ML tradicional tem melhor desempenho nos seguintes cenários: ① conjuntos de dados pequenos (< 1.000 amostras); ② características bem definidas (dados tabulares estruturados); ③ quando a interpretabilidade é necessária; ④ quando os recursos computacionais são limitados. A escolha do modelo deve depender da tarefa, dos dados e das restrições, em vez de perseguir cegamente “profundidade”.

📖 Resumo

Conceito-Chave: Um neurônio = soma ponderada + transformação não linear. Uma rede neural = muitos neurônios empilhados juntos. Deep learning = uma rede neural com muitas camadas. Do perceptron com 10 linhas de código ao GPT, todos seguem essencialmente o mesmo paradigma.

📝 Exercícios

  1. Básico (⭐): Implemente um perceptron para uma porta OR. A tabela verdade da porta OR é: (0,0) → 0, (0,1) → 1, (1,0) → 1, (1,1) → 1. Modifique os rótulos no código de treinamento do perceptron deste capítulo, treine o modelo e verifique os resultados.
PYTHON
# Starter code: OR gate perceptron
X = [[0,0],[0,1],[1,0],[1,1]]
y_or = [0, 1, 1, 1]
# TODO: train and test
  1. Avançado (⭐⭐): Use o MLPClassifier do sklearn para realizar a classificação no conjunto de dados Iris, ajuste os parâmetros e registre a acurácia para diferentes configurações:
PYTHON
# Starter code: MLP on Iris
from sklearn.datasets import load_iris
from sklearn.neural_network import MLPClassifier
from sklearn.model_selection import train_test_split

iris = load_iris()
X_train, X_test, y_train, y_test = train_test_split(
    iris.data, iris.target, test_size=0.3, random_state=42)

# TODO: try different hidden_layer_sizes, activation, learning_rate
# Record accuracy for each config

Tente pelo menos 3 configurações diferentes de hidden_layer_sizes (como (10,), (50,50), (100,)) e 2 funções de ativação, e anote qual configuração funciona melhor.

  1. Desafio (⭐⭐⭐): Com base na implementação pura em Python do MLP deste capítulo, plote a curva de perda para o MLP implementado manualmente:
PYTHON
# After training MLP from Section 9, plot the loss curve
import matplotlib.pyplot as plt

# mlp.losses is already recorded during training
plt.figure(figsize=(8, 5))
plt.plot(range(len(mlp.losses)), mlp.losses, linewidth=1)
plt.xlabel("Epoch")
plt.ylabel("Loss (MSE)")
plt.title("MLP Training Loss Curve (XOR)")
plt.yscale('log')
plt.grid(True, alpha=0.3)
plt.savefig("mlp_loss_curve.png", dpi=100)
plt.show()

Extensões Avançadas: ① Compare as curvas de perda para diferentes taxas de aprendizado (0.1, 0.5, 1.0, 2.0) no mesmo gráfico; ② Experimente com diferentes tamanhos de camada oculta (2, 4, 8) para ver como afetam a taxa de convergência; ③ Observe se a perda oscila ou até diverge quando a taxa de aprendizado é muito alta.

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%