1 O que é uma Rede Neural?
Inspirada no cérebro, mas muito mais simples — e muito mais poderosa.
Por que redes neurais?
No Módulo 1, vimos que ML clássico precisa que você defina manualmente as features (características) dos dados. Por exemplo, para classificar e-mails como spam, você precisa decidir: "vou usar frequência de palavras, presença de links, etc."
Redes neurais eliminam essa necessidade. Elas aprendem sozinhas quais features são importantes — e até criam features abstratas que você nunca imaginaria.
📊 ML Clássico
Você define: features manualmente
Modelo aprende: como combinar essas features
Ex: "use frequência de 'GRÁTIS' e presença de links"
🧠 Rede Neural
Você fornece: dados brutos (texto, pixels)
Modelo aprende: features E como combiná-las
Ex: rede descobre sozinha que "GRÁTIS" + "clique" + "agora" = spam
🎮 Visualização de uma rede neural
Clique nos neurônios para ver como a informação flui. A rede abaixo tem 3 camadas: input (azul), hidden (roxo) e output (verde).
2 O neurônio artificial (Perceptron)
A unidade básica de uma rede neural — inspirada no neurônio biológico.
Como funciona um neurônio
Um neurônio artificial faz 3 coisas:
- Recebe inputs (sinais de outros neurônios ou dados brutos)
- Multiplica cada input por um peso (importância daquele sinal)
- Soma tudo + bias e passa por uma função de ativação
Fórmula do neurônio
# Neurônio artificial output = activation(w1*x1 + w2*x2 + w3*x3 + ... + bias) # Onde: # x1, x2, x3 = inputs (sinais de entrada) # w1, w2, w3 = pesos (importância de cada input) # bias = limiar ajustável (threshold) # activation = função não-linear (ReLU, sigmoid, etc.)
Exemplo prático: decidir se vai chover
Vamos criar um neurônio que decide se vai chover com base em 3 features:
- x1: umidade do ar (0-100%)
- x2: pressão atmosférica (normalizada)
- x3: presença de nuvens escuras (0 ou 1)
import numpy as np def neuronio_chuva(x1, x2, x3): # Pesos aprendidos (exemplo) w1 = 0.6 # umidade é importante w2 = -0.4 # pressão baixa indica chuva w3 = 0.8 # nuvens escuras são forte indicador bias = -0.5 # Soma ponderada soma = w1*x1 + w2*x2 + w3*x3 + bias # Função de ativação: sigmoid (0 a 1) output = 1 / (1 + np.exp(-soma)) return output # Exemplos print(neuronio_chuva(80, 0.3, 1)) # 0.92 → alta probabilidade de chuva print(neuronio_chuva(30, 0.8, 0)) # 0.15 → baixa probabilidade
3 Funções de ativação
O que dá "poder" à rede neural — sem elas, seria só regressão linear.
Por que precisamos de não-linearidade?
Se todas as camadas fossem lineares, uma rede com 100 camadas seria equivalente a uma única camada (porque combinações lineares de lineares ainda são lineares). As funções de ativação introduzem não-linearidade, permitindo que a rede aprenda padrões complexos.
🎮 Simulador de funções de ativação
Veja como diferentes funções transformam o input
Eixo X: input do neurônio (soma ponderada)
Eixo Y: output após função de ativação
🟢 Linha ciano: função de ativação selecionada
Comparação das funções
| Função | Fórmula | Range | Uso típico |
|---|---|---|---|
| ReLU | max(0, x) | [0, ∞) | Camadas ocultas (mais popular) |
| Sigmoid | 1 / (1 + e^-x) | (0, 1) | Camada de saída (classificação binária) |
| Tanh | (e^x - e^-x) / (e^x + e^-x) | (-1, 1) | Camadas ocultas (RNNs) |
| Softmax | e^xi / Σe^xj | (0, 1), soma = 1 | Camada de saída (classificação multiclasse) |
4 Arquitetura: camadas e conexões
Como organizar neurônios em camadas para resolver problemas complexos.
Tipos de camadas
Camada de Input
Recebe os dados brutos. Cada neurônio representa uma feature. Ex: para uma imagem 28x28, são 784 neurônios (um por pixel).
Camadas Ocultas (Hidden)
Processam a informação. Quanto mais camadas, mais "profunda" é a rede (Deep Learning). Cada camada extrai features de complexidade crescente.
Camada de Output
Produz a previsão final. Para classificação binária: 1 neurônio (sigmoid). Para multiclasse: N neurônios (softmax).
Exemplo: rede para classificar tickets da Nimbus Cloud
Vamos criar uma rede para classificar tickets como "alta", "média" ou "baixa" prioridade:
- Input: 5 features (complexidade, cliente enterprise, fora do ar, hora do dia, histórico)
- Hidden: 2 camadas com 16 neurônios cada (ReLU)
- Output: 3 neurônios (softmax) → probabilidade de cada classe
import torch import torch.nn as nn class TicketClassifier(nn.Module): def __init__(self): super().__init__() # Camadas self.fc1 = nn.Linear(5, 16) # Input: 5 features → 16 neurônios self.fc2 = nn.Linear(16, 16) # Hidden: 16 → 16 self.fc3 = nn.Linear(16, 3) # Output: 16 → 3 classes self.relu = nn.ReLU() self.softmax = nn.Softmax(dim=1) def forward(self, x): # Forward pass x = self.relu(self.fc1(x)) # Camada 1 + ReLU x = self.relu(self.fc2(x)) # Camada 2 + ReLU x = self.softmax(self.fc3(x)) # Output + Softmax return x # Cria a rede model = TicketClassifier() print(model) # Exemplo de uso ticket = torch.tensor([[8.0, 1.0, 1.0, 14.0, 5.0]]) # 5 features output = model(ticket) print(f"Probabilidades: {output}") # [0.75, 0.20, 0.05] → 75% alta, 20% média, 5% baixa
Quantos neurônios e camadas usar?
| Tipo de problema | Camadas ocultas | Neurônios por camada |
|---|---|---|
| Simples (regressão, classificação básica) | 1-2 | 16-64 |
| Médio (imagens pequenas, texto curto) | 3-5 | 64-256 |
| Complexo (imagens grandes, NLP) | 10-100+ | 256-2048+ |
5 Forward Pass — como a rede "pensa"
O fluxo de informação da entrada até a saída.
Passo a passo do forward pass
- Input layer: dados brutos entram na rede
- Hidden layer 1: cada neurônio calcula soma ponderada + bias, aplica ativação
- Hidden layer 2: repete o processo com os outputs da camada anterior
- Output layer: última camada produz a previsão final
Exemplo numérico
# Rede simples: 2 inputs → 2 hidden → 1 output # Inputs x1 = 0.5 x2 = 0.8 # Pesos da camada 1 (input → hidden) w11 = 0.4 # x1 → h1 w12 = 0.6 # x2 → h1 w21 = 0.3 # x1 → h2 w22 = -0.2 # x2 → h2 # Bias da camada 1 b1 = 0.1 b2 = -0.1 # Camada hidden (com ReLU) h1 = max(0, w11*x1 + w12*x2 + b1) # max(0, 0.4*0.5 + 0.6*0.8 + 0.1) = 0.78 h2 = max(0, w21*x1 + w22*x2 + b2) # max(0, 0.3*0.5 + -0.2*0.8 + -0.1) = 0 # Pesos da camada 2 (hidden → output) w31 = 0.7 # h1 → output w32 = 0.5 # h2 → output b3 = 0.2 # Output (com sigmoid) output = 1 / (1 + np.exp(-(w31*h1 + w32*h2 + b3))) # 1 / (1 + exp(-(0.7*0.78 + 0.5*0 + 0.2))) = 0.76 print(f"Output: {output:.2f}") # 0.76 → 76% de probabilidade
6 Backpropagation — como a rede "aprende"
O algoritmo que ajusta os pesos para minimizar o erro.
O ciclo de aprendizado
- Forward pass: rede faz uma previsão
- Calcula o erro: compara previsão com resposta correta (loss function)
- Backward pass: calcula quanto cada peso contribuiu para o erro (gradiente)
- Atualiza pesos: ajusta pesos na direção que reduz o erro (gradient descent)
- Repete: faz isso para todos os exemplos de treinamento (epochs)
Loss Function — medindo o erro
A loss function (função de perda) mede quão errada foi a previsão:
- MSE (Mean Squared Error): para regressão → (previsto - real)²
- Cross-Entropy: para classificação → mede diferença entre distribuições de probabilidade
Gradient Descent — ajustando os pesos
# Gradient Descent (simplificado) learning_rate = 0.01 for epoch in range(1000): # Forward pass output = forward(X_train) # Calcula o erro loss = mse_loss(output, y_train) # Backward pass (calcula gradientes) gradients = backward(output, y_train) # Atualiza pesos for param in model.parameters(): param -= learning_rate * param.gradient if epoch % 100 == 0: print(f"Epoch {epoch}, Loss: {loss:.4f}")
🎮 Simulador de backpropagation
Veja os pesos sendo ajustados para minimizar o erro
w1 = 0.40
w2 = 0.60
Loss: 0.2500
Observação: quanto maior o learning rate, mais rápido os pesos mudam — mas pode "pular" o mínimo. Learning rate muito pequeno = aprendizado lento.
- Vanishing gradient: em redes muito profundas, os gradientes ficam tão pequenos que a rede para de aprender
- Exploding gradient: gradientes muito grandes fazem os pesos "explodirem"
- Solução: ReLU (evita vanishing), gradient clipping, batch normalization
7 Deep Learning — por que "deep"?
Redes neurais com muitas camadas — e por que isso importa.
O que torna uma rede "profunda"?
Uma rede é considerada "profunda" quando tem muitas camadas ocultas (tipicamente >3). Exemplos:
- Shallow: 1-2 camadas ocultas (ML clássico)
- Deep: 10-100 camadas (CNNs, Transformers)
- Very Deep: 100+ camadas (GPT, BERT, ResNet)
Por que profundidade ajuda?
Cada camada aprende features de complexidade crescente:
Camada 1
Features simples: bordas, cores, palavras-chave
Camada 2-3
Features intermediárias: formas, padrões, frases
Camada 4+
Features abstratas: objetos, conceitos, intenção
Exemplo: reconhecimento de imagem
Uma CNN (Convolutional Neural Network) para reconhecer gatos:
- Camada 1: detecta bordas e cores
- Camada 2: combina bordas em formas (orelhas, olhos)
- Camada 3: combina formas em partes de gato
- Camada 4: combina partes em "gato completo"
Arquiteturas famosas
| Arquitetura | Camadas | Uso | Ano |
|---|---|---|---|
| LeNet | 7 | Reconhecimento de dígitos | 1998 |
| AlexNet | 8 | Classificação de imagens | 2012 |
| VGG | 16-19 | Visão computacional | 2014 |
| ResNet | 152 | Visão computacional (skip connections) | 2015 |
| BERT | 12-24 | NLP (Encoder Transformer) | 2018 |
| GPT-3 | 96 | Generação de texto (Decoder Transformer) | 2020 |
8 Conexão com Embeddings e RAG
Como redes neurais são a base dos embeddings que usaremos em RAG.
Como embeddings são gerados
Um modelo de embedding é uma rede neural treinada para transformar texto em vetores. A arquitetura típica:
- Input: texto tokenizado (ex: "O contrato vence em março")
- Camadas Transformer: processam o texto e capturam contexto
- Pooling: combina os vetores de todos os tokens em um único vetor
- Output: vetor de 768-3072 dimensões representando o significado
Por que embeddings funcionam?
Durante o treinamento, a rede aprende a mapear textos semanticamente similares para vetores próximos no espaço. Isso acontece porque:
- A rede é treinada com milhões de pares de textos
- A loss function força a rede a aproximar vetores de textos similares
- As camadas Transformer capturam contexto e relações entre palavras
Exemplo: embedding com rede neural
# Modelo de embedding (simplificado) class EmbeddingModel(nn.Module): def __init__(self, vocab_size, embed_dim=768): super().__init__() self.embedding = nn.Embedding(vocab_size, embed_dim) self.transformer = nn.TransformerEncoder( nn.TransformerEncoderLayer(d_model=embed_dim, nhead=12), num_layers=6 ) def forward(self, tokens): # Tokens → vetores x = self.embedding(tokens) # Transformer processa contexto x = self.transformer(x) # Pooling: média dos vetores dos tokens output = x.mean(dim=1) return output # vetor de 768 dimensões # Uso model = EmbeddingModel(vocab_size=50000) tokens = tokenize("O contrato vence em março") embedding = model(tokens) print(embedding.shape) # torch.Size([768])
Conceitos que se conectam
| Conceito de Redes Neurais | Aplicação em RAG |
|---|---|
| Camadas Transformer | Modelos de embedding (nomic-embed-text, BERT) usam Transformers para capturar contexto |
| Pooling | Combina vetores de tokens em um único vetor representando o chunk inteiro |
| Similaridade de cosseno | Métrica usada para comparar embeddings na busca vetorial |
| Transfer learning | Modelos de embedding são pré-treinados em grandes corpora e fine-tuned para domínios específicos |
🎯 Quiz — teste seu conhecimento
Clique em uma alternativa para ver se acertou.
→ O que vem a seguir?
Agora que você entende redes neurais, vamos mergulhar em Processamento de Linguagem Natural (NLP).
Conceitos que vamos construir aqui
Tokenização
Como texto vira números (BPE, WordPiece).
Word Embeddings
Word2Vec, GloVe — os primeiros embeddings.
RNNs e LSTMs
Processando sequências de texto.
Transformers
A arquitetura que mudou tudo (Attention is All You Need).