Procesamiento y carga de datos de PyTorch
En PyTorch, procesar y cargar datos son pasos clave en el proceso de entrenamiento del aprendizaje profundo.
Para manejar los datos de manera eficiente, PyTorch proporciona potentes herramientas, incluyendotorch.utils.data.Datasetytorch.utils.data.DataLoader, que nos ayudan a gestionar tareas como conjuntos de datos, carga por lotes y aumento de datos.
Introducción al procesamiento y carga de datos de PyTorch:
- Dataset personalizado: Heredando de
torch.utils.data.Datasetpara cargar tus propios conjuntos de datos. - DataLoader:
DataLoaderCarga datos por lotes, admite carga con múltiples hilos y barajado de datos. - Preprocesamiento y aumento de datos: Usando
torchvision.transformspara realizar operaciones comunes de preprocesamiento y aumento de imágenes, mejorando la capacidad de generalización del modelo. - Carga de conjuntos de datos estándar:
torchvision.datasetsproporciona muchos conjuntos de datos comunes, simplificando el proceso de carga de datos. - Múltiples fuentes de datos: Combinando múltiples
Datasetinstancias para manejar datos de diferentes fuentes.
Dataset personalizado
torch.utils.data.Datasetes una clase abstracta que te permite crear conjuntos de datos a partir de tus propias fuentes de datos.
Necesitamos heredar esta clase e implementar los siguientes dos métodos:
__len__(self): Devuelve el número de muestras en el conjunto de datos.__getitem__(self, idx): Devuelve una muestra mediante un índice.
Supongamos que tenemos un archivo CSV simple o algunos datos de lista; podemos crear nuestro propio conjunto de datos heredando la clase Dataset.
Ejemplo
from torch.utils.data import Dataset
# Clase de conjunto de datos personalizada
class MyDataset(Dataset):
def __init__(self, X_data, Y_data):
"""
Inicializa el conjunto de datos; X_data y Y_data son dos listas o arrays
X_data: características de entrada
Y_data: etiquetas objetivo
"""
self.X_data = X_data
self.Y_data = Y_data
def __len__(self):
"""Devuelve el tamaño del conjunto de datos"""
return len(self.X_data)
def __getitem__(self, idx):
"""Devuelve los datos del índice especificado"""
x = torch.tensor(self.X_data[idx], dtype=torch.float32) # Convertir a Tensor
y = torch.tensor(self.Y_data[idx], dtype=torch.float32)
return x, y
# Datos de ejemplo
X_data = [[1, 2], [3, 4], [5, 6], [7, 8]] # Características de entrada
Y_data = [1, 0, 1, 0] # Etiquetas objetivo
# Crear una instancia del conjunto de datos
dataset = MyDataset(X_data, Y_data)
Uso de DataLoader para cargar datos
DataLoader es una herramienta importante proporcionada por PyTorch, utilizada para cargar datos por lotes (batch) desde el Dataset.
DataLoader nos permite leer datos en lotes y realizar carga con múltiples hilos, mejorando así la eficiencia del entrenamiento.
Ejemplo
# Crear una instancia de DataLoader; batch_size establece el número de muestras cargadas cada vez
dataloader = DataLoader(dataset, batch_size=2, shuffle=True)
# Imprimir los datos cargados
for epoch in range(1):
for batch_idx, (inputs, labels) in enumerate(dataloader):
print(f'Batch {batch_idx + 1}:')
print(f'Inputs: {inputs}')
print(f'Labels: {labels}')
batch_size: Número de muestras cargadas cada vez.shuffle: Si se barajan los datos; generalmente es necesario barajarlos durante el entrenamiento.drop_last: Si el número de muestras en el conjunto de datos no puede dividirse uniformemente porbatch_size, al configurarlo comoTrue, se descarta el último batch incompleto.
Salida:
Batch 1: Inputs: tensor([[3., 4.], [1., 2.]]) Labels: tensor([0., 1.]) Batch 2: Inputs: tensor([[7., 8.], [5., 6.]]) Labels: tensor([0., 1.])
En cada bucle, DataLoader devuelve un lote de datos, incluyendo las características de entrada (inputs) y las etiquetas objetivo (labels).
Preprocesamiento y aumento de datos
El preprocesamiento y el aumento de datos son cruciales para mejorar el rendimiento del modelo.
PyTorch proporciona el módulo torchvision.transforms para realizar operaciones comunes de preprocesamiento y aumento de imágenes, como rotación, recorte, normalización, etc.
Operaciones comunes de preprocesamiento de imágenes:
Ejemplo
from PIL import Image
# Definir el pipeline de preprocesamiento de datos
transform = transforms.Compose([
transforms.Resize((128, 128)), # Redimensionar la imagen a 128x128
transforms.ToTensor(), # Convertir la imagen a tensor
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]) # Estandarizar
])
# Cargar imagen
image = Image.open('image.jpg')
# Aplicar preprocesamiento
image_tensor = transform(image)
print(image_tensor.shape) # Imprimir la forma del tensor
transforms.Compose(): Combina múltiples operaciones de transformación.transforms.Resize(): Redimensiona la imagen.transforms.ToTensor(): Convierte la imagen a un tensor de PyTorch; los valores se normalizan al[0, 1]rango.transforms.Normalize(): Estandariza los datos de la imagen; normalmente se requiere estandarización cuando se usan modelos preentrenados.
Aumento de datos de imágenes
Las técnicas de aumento de datos incrementan la diversidad de los datos mediante transformaciones aleatorias de los datos de entrenamiento, ayudando al modelo a generalizar mejor. Por ejemplo, volteo aleatorio, rotación, recorte, etc.
Ejemplo
transforms.RandomHorizontalFlip(), # Volteo horizontal aleatorio
transforms.RandomRotation(30), # Rotación aleatoria de 30 grados
transforms.RandomResizedCrop(128), # Recorte aleatorio y redimensionamiento a 128x128
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
])
Estos métodos de aumento de datos se pueden combinar mediante transforms.Compose(), garantizando que cada imagen tenga transformaciones diferentes durante el entrenamiento.
Carga de conjuntos de datos de imágenes
Para conjuntos de datos de imágenes, torchvision.datasets proporciona muchos conjuntos de datos conocidos (como CIFAR-10, ImageNet, MNIST, etc.), así como herramientas para cargar datos de imágenes.
Cargar el conjunto de datos MNIST:
Ejemplo
import torchvision.transforms as transforms
# Definir operaciones de preprocesamiento
transform = transforms.Compose([
transforms.ToTensor(),
transforms.Normalize((0.5,), (0.5,)) # Estandarizar imágenes en escala de grises
])
# Descargar y cargar el conjunto de datos MNIST
train_dataset = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_dataset = datasets.MNIST(root='./data', train=False, download=True, transform=transform)
# Crear DataLoader
train_loader = DataLoader(train_dataset, batch_size=64, shuffle=True)
test_loader = DataLoader(test_dataset, batch_size=64, shuffle=False)
# Iterar sobre los datos de entrenamiento
for inputs, labels in train_loader:
print(inputs.shape) # Forma de los datos de entrada de cada lote
print(labels.shape) # Forma de las etiquetas de cada lote
datasets.MNIST()Descargará automáticamente el conjunto de datos MNIST y lo cargará.transformEl parámetro nos permite preprocesar los datos.train=Trueytrain=FalseIndican respectivamente el conjunto de entrenamiento y el conjunto de prueba.
Uso de múltiples fuentes de datos (Dataset de múltiples fuentes)
Si tu conjunto de datos está compuesto por múltiples archivos o múltiples fuentes (por ejemplo, múltiples carpetas de imágenes), puedes personalizar la carga de múltiples fuentes de datos heredando la clase Dataset.
PyTorch proporciona clases como ConcatDataset y ChainDataset para concatenar múltiples conjuntos de datos.
Por ejemplo, supongamos que tenemos datos de múltiples carpetas de imágenes; podemos combinarlos en un solo conjunto de datos:
Ejemplo
# Supongamos que dataset1 y dataset2 son dos objetos Dataset
combined_dataset = ConcatDataset([dataset1, dataset2])
combined_loader = DataLoader(combined_dataset, batch_size=64, shuffle=True)