# CNN (Convolutional Neural Network)

### 🎯 Descrição Geral

**CNN (Convolutional Neural Network)** é uma arquitetura de rede neural projetada especificamente para processar dados com **estrutura de grade** (grid-like topology), como imagens (2D), vídeos (3D), séries temporais (1D) e até áudio (1D).

Diferente de redes neurais totalmente conectadas (Fully Connected), as CNNs exploram a **estrutura espacial** dos dados, reduzindo drasticamente o número de parâmetros e preservando relações locais.

```
Imagem de Entrada (224x224x3)
        │
        ▼
   ┌─────────┐
   │ Conv2D  │ ← Detecta bordas, texturas
   │ ReLU    │
   └─────────┘
        │
        ▼
   ┌─────────┐
   │ MaxPool │ ← Reduz dimensionalidade
   └─────────┘
        │
        ▼
   ┌─────────┐
   │ Conv2D  │ ← Detecta formas, objetos parciais
   │ ReLU    │
   └─────────┘
        │
        ▼
   ┌─────────┐
   │ MaxPool │
   └─────────┘
        │
        ▼
   ┌─────────┐
   │  Flatten│
   └─────────┘
        │
        ▼
   ┌─────────┐
   │   Dense │ ← Classificação final
   │ Softmax │
   └─────────┘
        │
        ▼
   "Gato" (0.92), "Cachorro" (0.05), "Pássaro" (0.03)
```

#### Analogia

> *"Uma CNN funciona como um detetive que examina uma foto: primeiro olha para pixels individuais, depois para bordas, depois para formas (olhos, nariz), depois para objetos completos (rosto). Cada camada entende um nível mais alto de abstração."*

***

### ⚙️ Arquitetura de uma CNN

#### Camadas Fundamentais

| Camada                        | Função                    | Exemplo                      |
| ----------------------------- | ------------------------- | ---------------------------- |
| **Convolução (Conv2D)**       | Extrai features espaciais | 3x3, 5x5 kernels             |
| **Ativação (ReLU)**           | Não-linearidade           | `max(0, x)`                  |
| **Pooling (MaxPool/AvgPool)** | Reduz dimensionalidade    | 2x2 com stride 2             |
| **Normalização (BatchNorm)**  | Estabiliza treino         | Normaliza ativações          |
| **Dropout**                   | Previne overfitting       | Desliga neurônios aleatórios |
| **Flatten**                   | Converte 2D → 1D          | Para camadas densas          |
| **Dense (Fully Connected)**   | Classificação final       | Softmax para classes         |

***

### 🔬 Operação de Convolução

#### Conceito

A convolução desliza um **kernel (filtro)** sobre a imagem, calculando o produto escalar em cada posição.

```
Imagem (5x5)              Kernel (3x3)           Saída (3x3)
┌─────────────────┐       ┌─────────┐           ┌─────────┐
│ 1 1 1 0 0       │       │ 1 0 1   │           │ 4 3 4   │
│ 0 1 1 1 0       │   ⊙   │ 0 1 0   │    =      │ 2 4 3   │
│ 0 0 1 1 1       │       │ 1 0 1   │           │ 2 3 4   │
│ 0 0 1 1 0       │       └─────────┘           └─────────┘
│ 0 1 1 0 0       │
└─────────────────┘

Cálculo do primeiro elemento: 
(1×1 + 1×0 + 1×1) + (0×0 + 1×1 + 1×0) + (0×1 + 0×0 + 1×1) = 4
```

#### Parâmetros da Convolução

| Parâmetro       | Descrição                | Valores Típicos  |
| --------------- | ------------------------ | ---------------- |
| **Kernel Size** | Tamanho do filtro        | 3x3, 5x5, 7x7    |
| **Stride**      | Passo do deslizamento    | 1, 2             |
| **Padding**     | Preenchimento das bordas | 'same', 'valid'  |
| **Filters**     | Número de filtros        | 32, 64, 128, 256 |
| **Dilation**    | Espaçamento entre pixels | 1 (padrão), 2, 3 |

#### Fórmula do Tamanho de Saída

```
W_out = (W_in - K + 2P) / S + 1

Onde:
W_in  = tamanho da entrada
K     = tamanho do kernel
P     = padding
S     = stride
```

***

### 📐 Arquiteturas Clássicas

#### 1. LeNet-5 (1998) - O Pioneiro

```
Input (32x32) → Conv(6@5x5) → Pool(2x2) → Conv(16@5x5) → Pool(2x2) → FC(120) → FC(84) → FC(10)
```

**Uso:** Reconhecimento de dígitos (MNIST)

#### 2. AlexNet (2012) - O Rompedor

```
Input (227x227) → Conv(96@11x11, s4) → Pool → Conv(256@5x5) → Pool → Conv(384@3x3) 
→ Conv(384@3x3) → Conv(256@3x3) → Pool → FC(4096) → FC(4096) → FC(1000)
```

**Inovações:** ReLU, Dropout, Data Augmentation, GPU **Uso:** ImageNet (1.2M imagens, 1000 classes)

#### 3. VGG-16 (2014) - A Profunda e Uniforme

```
Input (224x224) → [Conv(64@3x3) ×2 → Pool] → [Conv(128@3x3) ×2 → Pool] 
→ [Conv(256@3x3) ×3 → Pool] → [Conv(512@3x3) ×3 → Pool] 
→ [Conv(512@3x3) ×3 → Pool] → FC(4096) → FC(4096) → FC(1000)
```

**Característica:** Apenas convoluções 3x3 (uniforme) **Tamanho:** \~138M parâmetros

#### 4. ResNet (2015) - A Revolução das Skip Connections

```
Input → Conv → BatchNorm → ReLU → Conv → BatchNorm → [+] → ReLU
                                ↑              │
                                └──────────────┘ (Skip Connection)
```

**Inovação:** Conexões residuais permitem redes muito profundas (152 camadas!) **Versões:** ResNet-18, ResNet-34, ResNet-50, ResNet-101, ResNet-152

#### 5. Inception (GoogleNet, 2014)

```
                    ┌─────────────┐
                    │ 1x1 Conv    │
                    └──────┬──────┘
                           │
    ┌──────────────────────┼──────────────────────┐
    │                      │                      │
┌───▼───┐              ┌───▼───┐              ┌───▼───┐
│ 1x1   │              │ 3x3   │              │ 5x5   │
│ Conv  │              │ Conv  │              │ Conv  │
└───┬───┘              └───┬───┘              └───┬───┘
    │                      │                      │
    └──────────────────────┼──────────────────────┘
                           │
                      ┌────▼────┐
                      │ Concat  │
                      └─────────┘
```

**Inovação:** Múltiplos kernels paralelos (1x1, 3x3, 5x5) + 1x1 para reduzir dimensão

***

### 💻 Implementações Práticas

#### CNN Básica com TensorFlow/Keras

```python
import tensorflow as tf
from tensorflow.keras import layers, models

def create_cnn(input_shape=(32, 32, 3), num_classes=10):
    model = models.Sequential([
        # Primeiro bloco convolucional
        layers.Conv2D(32, (3, 3), activation='relu', input_shape=input_shape),
        layers.BatchNormalization(),
        layers.MaxPooling2D((2, 2)),
        
        # Segundo bloco convolucional
        layers.Conv2D(64, (3, 3), activation='relu'),
        layers.BatchNormalization(),
        layers.MaxPooling2D((2, 2)),
        
        # Terceiro bloco convolucional
        layers.Conv2D(128, (3, 3), activation='relu'),
        layers.BatchNormalization(),
        layers.MaxPooling2D((2, 2)),
        
        # Classificador
        layers.Flatten(),
        layers.Dropout(0.5),
        layers.Dense(256, activation='relu'),
        layers.Dropout(0.3),
        layers.Dense(num_classes, activation='softmax')
    ])
    
    return model

# Criar modelo
model = create_cnn()
model.summary()

# Compilar
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)
```

#### CNN para CIFAR-10 (Classificação de Imagens)

```python
import tensorflow as tf
from tensorflow.keras import layers, models
from tensorflow.keras.datasets import cifar10
import matplotlib.pyplot as plt

# Carregar dados
(x_train, y_train), (x_test, y_test) = cifar10.load_data()

# Normalizar
x_train = x_train.astype('float32') / 255.0
x_test = x_test.astype('float32') / 255.0

# Criar modelo
model = models.Sequential([
    # Camada 1
    layers.Conv2D(32, (3, 3), padding='same', activation='relu', input_shape=(32, 32, 3)),
    layers.Conv2D(32, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),
    
    # Camada 2
    layers.Conv2D(64, (3, 3), padding='same', activation='relu'),
    layers.Conv2D(64, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),
    
    # Camada 3
    layers.Conv2D(128, (3, 3), padding='same', activation='relu'),
    layers.Conv2D(128, (3, 3), activation='relu'),
    layers.MaxPooling2D((2, 2)),
    layers.Dropout(0.25),
    
    # Classificação
    layers.Flatten(),
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(10, activation='softmax')
])

# Compilar
model.compile(
    optimizer='adam',
    loss='sparse_categorical_crossentropy',
    metrics=['accuracy']
)

# Treinar
history = model.fit(
    x_train, y_train,
    batch_size=64,
    epochs=20,
    validation_data=(x_test, y_test),
    verbose=1
)

# Avaliar
test_loss, test_acc = model.evaluate(x_test, y_test)
print(f"Acurácia no teste: {test_acc:.4f}")
```

#### ResNet-50 com Transfer Learning

```python
from tensorflow.keras.applications import ResNet50
from tensorflow.keras.applications.resnet50 import preprocess_input, decode_predictions

# Carregar modelo pré-treinado (sem a camada final)
base_model = ResNet50(
    weights='imagenet',
    include_top=False,
    input_shape=(224, 224, 3)
)

# Congelar camadas pré-treinadas
base_model.trainable = False

# Adicionar novas camadas para dataset customizado
model = models.Sequential([
    base_model,
    layers.GlobalAveragePooling2D(),
    layers.Dense(256, activation='relu'),
    layers.Dropout(0.5),
    layers.Dense(5, activation='softmax')  # 5 classes customizadas
])

# Compilar (learning rate menor para fine-tuning)
model.compile(
    optimizer=tf.keras.optimizers.Adam(learning_rate=0.0001),
    loss='categorical_crossentropy',
    metrics=['accuracy']
)
```

#### CNN 1D para Séries Temporais

```python
import numpy as np

# Gerar dados sintéticos
def generate_time_series(n_samples, seq_length=100):
    X = np.random.randn(n_samples, seq_length, 1)
    y = np.mean(X, axis=1) > 0
    return X, y

X_train, y_train = generate_time_series(1000)
X_test, y_test = generate_time_series(200)

# CNN 1D
model = models.Sequential([
    layers.Conv1D(64, kernel_size=3, activation='relu', input_shape=(100, 1)),
    layers.MaxPooling1D(2),
    layers.Conv1D(128, kernel_size=3, activation='relu'),
    layers.GlobalAveragePooling1D(),
    layers.Dense(1, activation='sigmoid')
])

model.compile(optimizer='adam', loss='binary_crossentropy', metrics=['accuracy'])
model.summary()
```

***

### 👁️ Visualização de Features (O que a CNN aprende)

```python
import numpy as np
import matplotlib.pyplot as plt

def visualize_filters(model, layer_name):
    """Visualiza os filtros de uma camada convolucional"""
    
    # Extrair os pesos da camada
    layer = model.get_layer(layer_name)
    filters, biases = layer.get_weights()
    
    # Normalizar para [0, 1]
    f_min, f_max = filters.min(), filters.max()
    filters = (filters - f_min) / (f_max - f_min)
    
    # Plotar
    n_filters = min(32, filters.shape[-1])
    n_cols = 8
    n_rows = n_filters // n_cols + 1
    
    fig, axes = plt.subplots(n_rows, n_cols, figsize=(12, 12))
    
    for i in range(n_filters):
        row = i // n_cols
        col = i % n_cols
        
        # Para RGB, pegar um canal (ou média)
        if filters.shape[-2] == 3:
            filter_img = filters[:, :, :, i]
            filter_img = np.mean(filter_img, axis=-1)
        else:
            filter_img = filters[:, :, 0, i]
        
        axes[row, col].imshow(filter_img, cmap='gray')
        axes[row, col].axis('off')
    
    plt.show()

# Para CNN treinada
# visualize_filters(model, 'conv2d')
```

***

### 📊 Comparação de Arquiteturas

| Arquitetura         | Ano  | Profundidade | Parâmetros | Top-1 Acc (ImageNet) | Velocidade   |
| ------------------- | ---- | ------------ | ---------- | -------------------- | ------------ |
| **LeNet-5**         | 1998 | 7            | 60K        | \~99% (MNIST)        | Muito rápida |
| **AlexNet**         | 2012 | 8            | 61M        | 63.3%                | Rápida       |
| **VGG-16**          | 2014 | 16           | 138M       | 71.5%                | Lenta        |
| **ResNet-50**       | 2015 | 50           | 25.5M      | 76.0%                | Média        |
| **Inception-v3**    | 2015 | 48           | 23.8M      | 78.1%                | Média        |
| **DenseNet-121**    | 2017 | 121          | 8.0M       | 75.0%                | Média        |
| **EfficientNet-B0** | 2019 | \~50         | 5.3M       | 77.1%                | Rápida       |
| **EfficientNet-B7** | 2019 | \~100        | 66M        | 84.4%                | Lenta        |

***

### 🎯 Aplicações Práticas

#### 1. Classificação de Imagens

```python
from tensorflow.keras.preprocessing.image import ImageDataGenerator

# Data Augmentation para evitar overfitting
datagen = ImageDataGenerator(
    rotation_range=20,
    width_shift_range=0.2,
    height_shift_range=0.2,
    horizontal_flip=True,
    zoom_range=0.2
)
```

#### 2. Detecção de Objetos

```python
# Arquiteturas populares:
# - YOLO (You Only Look Once)
# - SSD (Single Shot Detector)
# - Faster R-CNN
```

#### 3. Segmentação Semântica

```python
# Arquiteturas populares:
# - U-Net (segmentação médica)
# - Mask R-CNN
# - DeepLab
```

#### 4. Transfer Learning (Uso mais comum)

```python
from tensorflow.keras.applications import ResNet50, VGG16, EfficientNetB0

# Carregar modelo pré-treinado
base_model = EfficientNetB0(weights='imagenet', include_top=False, input_shape=(224, 224, 3))

# Adicionar camadas customizadas
x = base_model.output
x = layers.GlobalAveragePooling2D()(x)
x = layers.Dense(256, activation='relu')(x)
output = layers.Dense(num_classes, activation='softmax')(x)

model = models.Model(inputs=base_model.input, outputs=output)
```

***

### 🔧 Hyperparâmetros e Otimização

#### Guia de Hyperparâmetros

| Parâmetro         | Valor Típico                | Efeito                                 |
| ----------------- | --------------------------- | -------------------------------------- |
| **Learning Rate** | 0.001 (Adam), 0.01 (SGD)    | ↑ converge mais rápido, ↑ overshooting |
| **Batch Size**    | 32, 64, 128                 | ↑ mais estável, ↓ mais memória         |
| **Epochs**        | 10-100 (depende do dataset) | ↑ overfitting                          |
| **Dropout**       | 0.2 - 0.5                   | ↑ generalização, ↓ overfitting         |
| **Kernel Size**   | 3x3 (padrão), 5x5           | ↑ receptive field, ↑ parâmetros        |

#### Learning Rate Scheduling

```python
def scheduler(epoch, lr):
    if epoch < 10:
        return lr
    else:
        return lr * tf.math.exp(-0.1)

callback = tf.keras.callbacks.LearningRateScheduler(scheduler)

# Ou usar ReduceLROnPlateau
callback = tf.keras.callbacks.ReduceLROnPlateau(
    monitor='val_loss',
    factor=0.5,
    patience=5,
    min_lr=1e-7
)
```

***

### ⚠️ Desafios e Limitações

| Desafio                  | Descrição                         | Solução                                   |
| ------------------------ | --------------------------------- | ----------------------------------------- |
| **Overfitting**          | Modelo decora os dados            | Dropout, Data Augmentation, Regularização |
| **Computação intensiva** | Treino pode levar dias/semanas    | GPU, TPU, modelos mais leves              |
| **Dados rotulados**      | Precisa de muitos exemplos        | Transfer Learning, Data Augmentation      |
| **Interpretabilidade**   | "Caixa preta"                     | Grad-CAM, LIME, SHAP                      |
| **Tamanho da imagem**    | Imagens grandes = mais parâmetros | Pooling, Stride > 1                       |

***

### 📈 Métricas de Avaliação

| Métrica      | Fórmula           | Uso                        |
| ------------ | ----------------- | -------------------------- |
| **Acurácia** | (VP+VN)/Total     | Balanceado                 |
| **Precisão** | VP/(VP+FP)        | Minimizar falsos positivos |
| **Recall**   | VP/(VP+FN)        | Minimizar falsos negativos |
| **F1-Score** | 2×(P×R)/(P+R)     | Desbalanceado              |
| **IoU**      | Intersecção/União | Segmentação                |
| **mAP**      | Média das APs     | Detecção de objetos        |

***

### 🔗 Links Úteis

* [CS231n - Stanford CNNs](http://cs231n.stanford.edu/)
* [TensorFlow CNN Tutorial](https://www.tensorflow.org/tutorials/images/cnn)
* [PyTorch CNN Tutorial](https://pytorch.org/tutorials/beginner/blitz/cifar10_tutorial.html)

***

### 📚 Leitura Recomendada

| Livro                     | Autor                         | Foco                            |
| ------------------------- | ----------------------------- | ------------------------------- |
| Deep Learning             | Goodfellow, Bengio, Courville | Teoria                          |
| Deep Learning with Python | François Chollet              | Prático (Keras)                 |
| Dive into Deep Learning   | Zhang, Lipton, Smola          | Interativo (PyTorch/TensorFlow) |


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://0xmorte.gitbook.io/bibliadopentestbr/conceitos/algoritmos/aprendizado-de-maquina-machine-learning/cnn-convolutional-neural-network.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
