Capítulo 5: Redes Neuronales Convolucionales (CNNs)
Ejercicios Prácticos Capítulo 5
Ejercicio 1: Implementar una CNN Básica para la Clasificación de Imágenes
Tarea: Implementar una CNN simple desde cero para clasificar imágenes del conjunto de datos MNIST. Entrenar el modelo durante algunas épocas y evaluar su precisión.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the CNN model
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
self.fc1 = nn.Linear(64 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 5 * 5)
x = torch.relu(self.fc1(x))
return self.fc2(x)
# Define transformations and load the MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model for 5 epochs
epochs = 5
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, implementamos una CNN simple para clasificar el conjunto de datos MNIST, entrenamos el modelo utilizando el optimizador Adam y mostramos la pérdida después de cada época. Puedes extender esto cargando un conjunto de prueba y calculando la precisión.
Ejercicio 2: Ajuste Fino de un ResNet Preentrenado para CIFAR-10
Tarea: Realiza el ajuste fino de un modelo preentrenado ResNet-18 en el conjunto de datos CIFAR-10 reemplazando la capa totalmente conectada final con una capa que tenga 10 salidas. Entrena el modelo y evalúa su precisión en el conjunto de prueba.
Solución:
import torch
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.optim as optim
# Set device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Load pretrained ResNet-18 model and modify the final layer
model = models.resnet18(pretrained=True)
model.fc = torch.nn.Linear(model.fc.in_features, 10)
model.to(device) # Move model to device
# Define loss function and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
model.train()
for epoch in range(5):
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device) # Move data to device
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, cargamos un modelo preentrenado ResNet-18 y modificamos su capa totalmente conectada final para ajustarla al conjunto de datos CIFAR-10 (10 clases). Después de entrenar durante algunas épocas, se puede evaluar el modelo en el conjunto de prueba.
Ejercicio 3: Detección de Objetos Usando Faster R-CNN
Tarea: Utiliza un modelo preentrenado Faster R-CNN para detectar objetos en una imagen. Carga el modelo, preprocesa la imagen de entrada e imprime los objetos detectados y sus cuadros delimitadores.
Solución:
import torch
import torchvision
from PIL import Image
import torchvision.transforms as transforms
# Load a pretrained Faster R-CNN model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
model.eval() # Set model to evaluation mode
# Load and preprocess the image
image = Image.open("test_image.jpg")
transform = transforms.Compose([transforms.ToTensor()])
image_tensor = transform(image).unsqueeze(0) # Add batch dimension
# Perform object detection
with torch.no_grad():
predictions = model(image_tensor)
# Print the predicted bounding boxes and labels
print(predictions)
En este ejercicio:
- Cargamos un modelo preentrenado Faster R-CNN para realizar la detección de objetos en una imagen dada.
- Los objetos detectados y sus cuadros delimitadores se imprimen en la salida. Puedes visualizar estos cuadros en la imagen para una mejor comprensión de las predicciones.
Ejercicio 4: Implementación del Módulo Inception en una CNN Personalizada
Tarea: Implementa un módulo Inception desde cero e intégralo en una CNN personalizada. Entrena este modelo en un conjunto de datos como CIFAR-10.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the Inception module
class InceptionModule(nn.Module):
def __init__(self, in_channels):
super(InceptionModule, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 64, kernel_size=1)
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, 128, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1)
)
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, 32, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(32, 32, kernel_size=5, padding=2)
)
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, 32, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, 1)
# Define the custom CNN using the Inception module
class CustomCNN(nn.Module):
def __init__(self):
super(CustomCNN, self).__init__()
self.inception1 = InceptionModule(in_channels=3)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1)) # Ensure fixed output size
self.fc = nn.Linear(256, 10) # Corrected output channels (64+128+32+32)
def forward(self, x):
x = self.inception1(x)
x = self.global_avg_pool(x) # Global average pooling
x = torch.flatten(x, 1) # Flatten before fully connected layer
return self.fc(x)
# Define the data transformations and load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(32), # Ensure correct input size
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Normalize
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CustomCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
for epoch in range(5):
model.train()
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}")
En este ejercicio, implementamos un módulo Inception personalizado e integrado en una CNN. El modelo se entrenó en el conjunto de datos CIFAR-10 utilizando el optimizador Adam.
Estos ejercicios prácticos brindan experiencia directa en tareas clave de CNN, como la construcción de CNN simples, el ajuste fino de modelos preentrenados, la detección de objetos y la implementación de módulos avanzados como Inception. Al completar estos ejercicios, podrás aplicar las CNN a una amplia gama de aplicaciones del mundo real.
Ejercicios Prácticos Capítulo 5
Ejercicio 1: Implementar una CNN Básica para la Clasificación de Imágenes
Tarea: Implementar una CNN simple desde cero para clasificar imágenes del conjunto de datos MNIST. Entrenar el modelo durante algunas épocas y evaluar su precisión.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the CNN model
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
self.fc1 = nn.Linear(64 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 5 * 5)
x = torch.relu(self.fc1(x))
return self.fc2(x)
# Define transformations and load the MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model for 5 epochs
epochs = 5
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, implementamos una CNN simple para clasificar el conjunto de datos MNIST, entrenamos el modelo utilizando el optimizador Adam y mostramos la pérdida después de cada época. Puedes extender esto cargando un conjunto de prueba y calculando la precisión.
Ejercicio 2: Ajuste Fino de un ResNet Preentrenado para CIFAR-10
Tarea: Realiza el ajuste fino de un modelo preentrenado ResNet-18 en el conjunto de datos CIFAR-10 reemplazando la capa totalmente conectada final con una capa que tenga 10 salidas. Entrena el modelo y evalúa su precisión en el conjunto de prueba.
Solución:
import torch
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.optim as optim
# Set device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Load pretrained ResNet-18 model and modify the final layer
model = models.resnet18(pretrained=True)
model.fc = torch.nn.Linear(model.fc.in_features, 10)
model.to(device) # Move model to device
# Define loss function and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
model.train()
for epoch in range(5):
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device) # Move data to device
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, cargamos un modelo preentrenado ResNet-18 y modificamos su capa totalmente conectada final para ajustarla al conjunto de datos CIFAR-10 (10 clases). Después de entrenar durante algunas épocas, se puede evaluar el modelo en el conjunto de prueba.
Ejercicio 3: Detección de Objetos Usando Faster R-CNN
Tarea: Utiliza un modelo preentrenado Faster R-CNN para detectar objetos en una imagen. Carga el modelo, preprocesa la imagen de entrada e imprime los objetos detectados y sus cuadros delimitadores.
Solución:
import torch
import torchvision
from PIL import Image
import torchvision.transforms as transforms
# Load a pretrained Faster R-CNN model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
model.eval() # Set model to evaluation mode
# Load and preprocess the image
image = Image.open("test_image.jpg")
transform = transforms.Compose([transforms.ToTensor()])
image_tensor = transform(image).unsqueeze(0) # Add batch dimension
# Perform object detection
with torch.no_grad():
predictions = model(image_tensor)
# Print the predicted bounding boxes and labels
print(predictions)
En este ejercicio:
- Cargamos un modelo preentrenado Faster R-CNN para realizar la detección de objetos en una imagen dada.
- Los objetos detectados y sus cuadros delimitadores se imprimen en la salida. Puedes visualizar estos cuadros en la imagen para una mejor comprensión de las predicciones.
Ejercicio 4: Implementación del Módulo Inception en una CNN Personalizada
Tarea: Implementa un módulo Inception desde cero e intégralo en una CNN personalizada. Entrena este modelo en un conjunto de datos como CIFAR-10.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the Inception module
class InceptionModule(nn.Module):
def __init__(self, in_channels):
super(InceptionModule, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 64, kernel_size=1)
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, 128, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1)
)
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, 32, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(32, 32, kernel_size=5, padding=2)
)
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, 32, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, 1)
# Define the custom CNN using the Inception module
class CustomCNN(nn.Module):
def __init__(self):
super(CustomCNN, self).__init__()
self.inception1 = InceptionModule(in_channels=3)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1)) # Ensure fixed output size
self.fc = nn.Linear(256, 10) # Corrected output channels (64+128+32+32)
def forward(self, x):
x = self.inception1(x)
x = self.global_avg_pool(x) # Global average pooling
x = torch.flatten(x, 1) # Flatten before fully connected layer
return self.fc(x)
# Define the data transformations and load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(32), # Ensure correct input size
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Normalize
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CustomCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
for epoch in range(5):
model.train()
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}")
En este ejercicio, implementamos un módulo Inception personalizado e integrado en una CNN. El modelo se entrenó en el conjunto de datos CIFAR-10 utilizando el optimizador Adam.
Estos ejercicios prácticos brindan experiencia directa en tareas clave de CNN, como la construcción de CNN simples, el ajuste fino de modelos preentrenados, la detección de objetos y la implementación de módulos avanzados como Inception. Al completar estos ejercicios, podrás aplicar las CNN a una amplia gama de aplicaciones del mundo real.
Ejercicios Prácticos Capítulo 5
Ejercicio 1: Implementar una CNN Básica para la Clasificación de Imágenes
Tarea: Implementar una CNN simple desde cero para clasificar imágenes del conjunto de datos MNIST. Entrenar el modelo durante algunas épocas y evaluar su precisión.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the CNN model
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
self.fc1 = nn.Linear(64 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 5 * 5)
x = torch.relu(self.fc1(x))
return self.fc2(x)
# Define transformations and load the MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model for 5 epochs
epochs = 5
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, implementamos una CNN simple para clasificar el conjunto de datos MNIST, entrenamos el modelo utilizando el optimizador Adam y mostramos la pérdida después de cada época. Puedes extender esto cargando un conjunto de prueba y calculando la precisión.
Ejercicio 2: Ajuste Fino de un ResNet Preentrenado para CIFAR-10
Tarea: Realiza el ajuste fino de un modelo preentrenado ResNet-18 en el conjunto de datos CIFAR-10 reemplazando la capa totalmente conectada final con una capa que tenga 10 salidas. Entrena el modelo y evalúa su precisión en el conjunto de prueba.
Solución:
import torch
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.optim as optim
# Set device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Load pretrained ResNet-18 model and modify the final layer
model = models.resnet18(pretrained=True)
model.fc = torch.nn.Linear(model.fc.in_features, 10)
model.to(device) # Move model to device
# Define loss function and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
model.train()
for epoch in range(5):
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device) # Move data to device
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, cargamos un modelo preentrenado ResNet-18 y modificamos su capa totalmente conectada final para ajustarla al conjunto de datos CIFAR-10 (10 clases). Después de entrenar durante algunas épocas, se puede evaluar el modelo en el conjunto de prueba.
Ejercicio 3: Detección de Objetos Usando Faster R-CNN
Tarea: Utiliza un modelo preentrenado Faster R-CNN para detectar objetos en una imagen. Carga el modelo, preprocesa la imagen de entrada e imprime los objetos detectados y sus cuadros delimitadores.
Solución:
import torch
import torchvision
from PIL import Image
import torchvision.transforms as transforms
# Load a pretrained Faster R-CNN model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
model.eval() # Set model to evaluation mode
# Load and preprocess the image
image = Image.open("test_image.jpg")
transform = transforms.Compose([transforms.ToTensor()])
image_tensor = transform(image).unsqueeze(0) # Add batch dimension
# Perform object detection
with torch.no_grad():
predictions = model(image_tensor)
# Print the predicted bounding boxes and labels
print(predictions)
En este ejercicio:
- Cargamos un modelo preentrenado Faster R-CNN para realizar la detección de objetos en una imagen dada.
- Los objetos detectados y sus cuadros delimitadores se imprimen en la salida. Puedes visualizar estos cuadros en la imagen para una mejor comprensión de las predicciones.
Ejercicio 4: Implementación del Módulo Inception en una CNN Personalizada
Tarea: Implementa un módulo Inception desde cero e intégralo en una CNN personalizada. Entrena este modelo en un conjunto de datos como CIFAR-10.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the Inception module
class InceptionModule(nn.Module):
def __init__(self, in_channels):
super(InceptionModule, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 64, kernel_size=1)
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, 128, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1)
)
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, 32, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(32, 32, kernel_size=5, padding=2)
)
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, 32, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, 1)
# Define the custom CNN using the Inception module
class CustomCNN(nn.Module):
def __init__(self):
super(CustomCNN, self).__init__()
self.inception1 = InceptionModule(in_channels=3)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1)) # Ensure fixed output size
self.fc = nn.Linear(256, 10) # Corrected output channels (64+128+32+32)
def forward(self, x):
x = self.inception1(x)
x = self.global_avg_pool(x) # Global average pooling
x = torch.flatten(x, 1) # Flatten before fully connected layer
return self.fc(x)
# Define the data transformations and load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(32), # Ensure correct input size
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Normalize
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CustomCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
for epoch in range(5):
model.train()
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}")
En este ejercicio, implementamos un módulo Inception personalizado e integrado en una CNN. El modelo se entrenó en el conjunto de datos CIFAR-10 utilizando el optimizador Adam.
Estos ejercicios prácticos brindan experiencia directa en tareas clave de CNN, como la construcción de CNN simples, el ajuste fino de modelos preentrenados, la detección de objetos y la implementación de módulos avanzados como Inception. Al completar estos ejercicios, podrás aplicar las CNN a una amplia gama de aplicaciones del mundo real.
Ejercicios Prácticos Capítulo 5
Ejercicio 1: Implementar una CNN Básica para la Clasificación de Imágenes
Tarea: Implementar una CNN simple desde cero para clasificar imágenes del conjunto de datos MNIST. Entrenar el modelo durante algunas épocas y evaluar su precisión.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the CNN model
class SimpleCNN(nn.Module):
def __init__(self):
super(SimpleCNN, self).__init__()
self.conv1 = nn.Conv2d(1, 32, kernel_size=3)
self.pool = nn.MaxPool2d(2, 2)
self.conv2 = nn.Conv2d(32, 64, kernel_size=3)
self.fc1 = nn.Linear(64 * 5 * 5, 128)
self.fc2 = nn.Linear(128, 10)
def forward(self, x):
x = self.pool(torch.relu(self.conv1(x)))
x = self.pool(torch.relu(self.conv2(x)))
x = x.view(-1, 64 * 5 * 5)
x = torch.relu(self.fc1(x))
return self.fc2(x)
# Define transformations and load the MNIST dataset
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
model = SimpleCNN()
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model for 5 epochs
epochs = 5
for epoch in range(epochs):
running_loss = 0.0
for inputs, labels in train_loader:
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, implementamos una CNN simple para clasificar el conjunto de datos MNIST, entrenamos el modelo utilizando el optimizador Adam y mostramos la pérdida después de cada época. Puedes extender esto cargando un conjunto de prueba y calculando la precisión.
Ejercicio 2: Ajuste Fino de un ResNet Preentrenado para CIFAR-10
Tarea: Realiza el ajuste fino de un modelo preentrenado ResNet-18 en el conjunto de datos CIFAR-10 reemplazando la capa totalmente conectada final con una capa que tenga 10 salidas. Entrena el modelo y evalúa su precisión en el conjunto de prueba.
Solución:
import torch
import torchvision.models as models
import torchvision.transforms as transforms
import torchvision.datasets as datasets
from torch.utils.data import DataLoader
import torch.optim as optim
# Set device
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
# Load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(224),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Load pretrained ResNet-18 model and modify the final layer
model = models.resnet18(pretrained=True)
model.fc = torch.nn.Linear(model.fc.in_features, 10)
model.to(device) # Move model to device
# Define loss function and optimizer
criterion = torch.nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
model.train()
for epoch in range(5):
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device) # Move data to device
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader)}")
# Evaluate the model (Optional: Load test set and compute accuracy)
En este ejercicio, cargamos un modelo preentrenado ResNet-18 y modificamos su capa totalmente conectada final para ajustarla al conjunto de datos CIFAR-10 (10 clases). Después de entrenar durante algunas épocas, se puede evaluar el modelo en el conjunto de prueba.
Ejercicio 3: Detección de Objetos Usando Faster R-CNN
Tarea: Utiliza un modelo preentrenado Faster R-CNN para detectar objetos en una imagen. Carga el modelo, preprocesa la imagen de entrada e imprime los objetos detectados y sus cuadros delimitadores.
Solución:
import torch
import torchvision
from PIL import Image
import torchvision.transforms as transforms
# Load a pretrained Faster R-CNN model
model = torchvision.models.detection.fasterrcnn_resnet50_fpn(pretrained=True)
model.eval() # Set model to evaluation mode
# Load and preprocess the image
image = Image.open("test_image.jpg")
transform = transforms.Compose([transforms.ToTensor()])
image_tensor = transform(image).unsqueeze(0) # Add batch dimension
# Perform object detection
with torch.no_grad():
predictions = model(image_tensor)
# Print the predicted bounding boxes and labels
print(predictions)
En este ejercicio:
- Cargamos un modelo preentrenado Faster R-CNN para realizar la detección de objetos en una imagen dada.
- Los objetos detectados y sus cuadros delimitadores se imprimen en la salida. Puedes visualizar estos cuadros en la imagen para una mejor comprensión de las predicciones.
Ejercicio 4: Implementación del Módulo Inception en una CNN Personalizada
Tarea: Implementa un módulo Inception desde cero e intégralo en una CNN personalizada. Entrena este modelo en un conjunto de datos como CIFAR-10.
Solución:
import torch
import torch.nn as nn
import torch.optim as optim
from torchvision import datasets, transforms
from torch.utils.data import DataLoader
# Define the Inception module
class InceptionModule(nn.Module):
def __init__(self, in_channels):
super(InceptionModule, self).__init__()
self.branch1x1 = nn.Conv2d(in_channels, 64, kernel_size=1)
self.branch3x3 = nn.Sequential(
nn.Conv2d(in_channels, 128, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(128, 128, kernel_size=3, padding=1)
)
self.branch5x5 = nn.Sequential(
nn.Conv2d(in_channels, 32, kernel_size=1),
nn.ReLU(inplace=True),
nn.Conv2d(32, 32, kernel_size=5, padding=2)
)
self.branch_pool = nn.Sequential(
nn.MaxPool2d(kernel_size=3, stride=1, padding=1),
nn.Conv2d(in_channels, 32, kernel_size=1)
)
def forward(self, x):
branch1x1 = self.branch1x1(x)
branch3x3 = self.branch3x3(x)
branch5x5 = self.branch5x5(x)
branch_pool = self.branch_pool(x)
outputs = [branch1x1, branch3x3, branch5x5, branch_pool]
return torch.cat(outputs, 1)
# Define the custom CNN using the Inception module
class CustomCNN(nn.Module):
def __init__(self):
super(CustomCNN, self).__init__()
self.inception1 = InceptionModule(in_channels=3)
self.global_avg_pool = nn.AdaptiveAvgPool2d((1, 1)) # Ensure fixed output size
self.fc = nn.Linear(256, 10) # Corrected output channels (64+128+32+32)
def forward(self, x):
x = self.inception1(x)
x = self.global_avg_pool(x) # Global average pooling
x = torch.flatten(x, 1) # Flatten before fully connected layer
return self.fc(x)
# Define the data transformations and load CIFAR-10 dataset
transform = transforms.Compose([
transforms.Resize(32), # Ensure correct input size
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Normalize
])
train_dataset = datasets.CIFAR10(root='./data', train=True, download=True, transform=transform)
train_loader = DataLoader(train_dataset, batch_size=32, shuffle=True)
# Instantiate the model, define the loss function and optimizer
device = torch.device("cuda" if torch.cuda.is_available() else "cpu")
model = CustomCNN().to(device)
criterion = nn.CrossEntropyLoss()
optimizer = optim.Adam(model.parameters(), lr=0.001)
# Train the model
for epoch in range(5):
model.train()
running_loss = 0.0
for inputs, labels in train_loader:
inputs, labels = inputs.to(device), labels.to(device)
optimizer.zero_grad()
outputs = model(inputs)
loss = criterion(outputs, labels)
loss.backward()
optimizer.step()
running_loss += loss.item()
print(f"Epoch {epoch+1}, Loss: {running_loss/len(train_loader):.4f}")
En este ejercicio, implementamos un módulo Inception personalizado e integrado en una CNN. El modelo se entrenó en el conjunto de datos CIFAR-10 utilizando el optimizador Adam.
Estos ejercicios prácticos brindan experiencia directa en tareas clave de CNN, como la construcción de CNN simples, el ajuste fino de modelos preentrenados, la detección de objetos y la implementación de módulos avanzados como Inception. Al completar estos ejercicios, podrás aplicar las CNN a una amplia gama de aplicaciones del mundo real.