Datasets & DataLoaders
PyTorch Dataset e DataLoader alimentam loops de treinamento com dados agrupados, embaralhados e opcionalmente aumentados. Pipelines de entrada eficientes mantêm a GPU ocupada e o treinamento rápido.
Receita
Cartão de referência rápida - pronto para copiar e colar.
from torch.utils.data import Dataset, DataLoader
from torchvision import transforms
transform = transforms.Compose([transforms.ToTensor(), transforms.Normalize((0.5,), (0.5,))])
loader = DataLoader(dataset, batch_size=64, shuffle=True, num_workers=4, pin_memory=True)
for batch_x, batch_y in loader:
batch_x = batch_x.to(device, non_blocking=True)Quando usar isso:
- Carregando imagens, texto ou dados tabulares em loops de treinamento.
- Aplicando transformações por amostra (aumento, tokenização).
- Agrupando sequências de comprimento variável com um
collate_fnpersonalizado. - Pré-buscando dados para a GPU com
pin_memoryenon_blocking.
Exemplo de Trabalho
"""datasets_dataloaders.py - Dataset e DataLoader personalizados para dados CSV."""
from __future__ import annotations
import pandas as pd
import torch
from torch.utils.data import Dataset, DataLoader, random_split
class TabularDataset(Dataset):
def __init__(self, df: pd.DataFrame, feature_cols: list[str], target_col: str):
self.X = torch.tensor(df[feature_cols].values, dtype=torch.float32)
self.y = torch.tensor(df[target_col].values, dtype=torch.long)
def __len__(self) -> int:
return len(self.y)
def __getitem__(self, idx: int) -> tuple[torch.Tensor, torch.Tensor]:
return self.X[idx], self.y[idx]
df = pd.read_csv("train.csv")
dataset = TabularDataset(df, feature_cols=["f1", "f2", "f3"], target_col="label")
train_size = int(0.8 * len(dataset))
train_ds, val_ds = random_split(dataset, [train_size, len(dataset) - train_size])
train_loader = DataLoader(train_ds, batch_size=128, shuffle=True, num_workers=2, pin_memory=True)
val_loader = DataLoader(val_ds, batch_size=256, shuffle=False, num_workers=2)
for epoch in range(3):
for x_batch, y_batch in train_loader:
# x_batch: (128, 3), y_batch: (128,)
passO que isso demonstra:
Datasetpersonalizado com__len__e__getitem__.random_splitpara partição de treino/validação.DataLoaderlida com agrupamento e embaralhamento.pin_memory=Trueacelera a transferência CPU-GPU quando CUDA está disponível.
Mergulho Profundo
Como Funciona
Dataset.__getitem__(i)retorna uma amostra;DataLoadercoletabatch_sizeamostras.shuffle=Truerandomiza a ordem a cada época.num_workersinicia subprocessos para carregamento paralelo de dados.collate_fnpersonaliza como as amostras são mescladas em um lote (preenchimento para sequências).IterableDatasettransmite dados para fontes muito grandes ou online.
Opções do DataLoader
| Parâmetro | Efeito | Valor Típico |
|---|---|---|
batch_size | Amostras por lote | 32-256 (dependente da memória da GPU) |
shuffle | Randomizar ordem | True para treinamento |
num_workers | Carregadores paralelos | 4-8 em multi-core |
pin_memory | Memória host travada (page-locked) | True com CUDA |
drop_last | Descartar o último lote incompleto | True para treinamento BatchNorm |
Notas de Python
from torchvision import datasets, transforms
# Dataset de imagem integrado com transforms
transform = transforms.Compose([
transforms.RandomHorizontalFlip(),
transforms.ToTensor(),
transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
])
train_set = datasets.CIFAR10(root="./data", train=True, download=True, transform=transform)Armadilhas
- Aumento de dados na validação - transformações aleatórias corrompem a avaliação. Correção: pipelines de transformações separados para treino/validação; validação recebe apenas transformações determinísticas.
- num_workers no Windows/notebooks - problemas de multiprocessamento no Jupyter. Correção:
num_workers=0em notebooks; usar scripts para carregamento paralelo. - Não usar pin_memory com CUDA - cópias mais lentas de host para dispositivo. Correção:
pin_memory=Trueenon_blocking=Trueem.to(device). - Carregar o dataset inteiro na RAM - OOM (Out Of Memory) em datasets grandes. Correção: carregamento preguiçoso em
__getitem__, arquivos com mapeamento de memória ouIterableDataset. - Tipos de tensor inconsistentes - misturar float/int causa erros no modelo. Correção: converter explicitamente em
__getitem__. - Embaralhar dados de validação - desnecessário e torna as curvas de perda ruidosas. Correção:
shuffle=Falsepara loaders de validação/teste.
Alternativas
| Alternativa | Usar Quando | Não Usar Quando |
|---|---|---|
DataLoader | Treinamento em lote padrão | Transmitir dados infinitos (usar IterableDataset) |
torchvision.datasets | Benchmarks comuns de imagem | Formatos de dados personalizados |
HuggingFace datasets | Datasets de NLP/texto | Classificação de imagem simples |
| WebDataset | Treinamento em larga escala na web | Pequenos datasets locais |
FAQs
Quando preciso de um Dataset personalizado?
- Os dados não estão em um formato padrão (CSV, binário personalizado, multimodal).
- Pré-processamento por amostra é caro e deve ser preguiçoso.
- Datasets integrados não correspondem ao seu esquema.
O que é collate_fn?
def pad_collate(batch):
xs, ys = zip(*batch)
lengths = [len(x) for x in xs]
padded = torch.nn.utils.rnn.pad_sequence(xs, batch_first=True)
return padded, torch.tensor(ys), torch.tensor(lengths)
loader = DataLoader(ds, collate_fn=pad_collate)- Personaliza a montagem do lote para sequências de comprimento variável.
Como acelerar o carregamento de dados?
- Aumente
num_workersaté que a CPU esteja saturada. - Use
pin_memory=Truecom CUDA. - Pré-processe e armazene em cache no disco (LMDB, parquet, arquivos .pt).
O que é persistent_workers?
DataLoader(ds, num_workers=4, persistent_workers=True)- Mantém os processos trabalhadores ativos entre as épocas.
- Evita o overhead de reinicialização em treinamento de múltiplas épocas.
Posso usar pandas DataFrames diretamente?
- Converta para tensores em
__getitem__ou pré-carregue em__init__para dados pequenos. - Para dados grandes, leia uma linha por chamada de
__getitem__.
Como os transforms de treino e validação diferem?
- Treino: aumento aleatório (flip, crop, color jitter).
- Validação: apenas redimensionamento e normalização determinísticos.
- Nunca aumente dados de validação.
O que é IterableDataset?
- Para transmitir dados sem acesso aleatório (
__getitem__). - Sem
shuffle- implemente o embaralhamento no iterador ou buffer. - Usado para feeds de dados em escala web ou em tempo real.
Como reproduzir o embaralhamento?
generator = torch.Generator().manual_seed(42)
loader = DataLoader(ds, shuffle=True, generator=generator)- Uma semente de gerador fixa garante ordem de lote reproduzível.
Qual tamanho de lote devo usar?
- O maior que couber na memória da GPU sem OOM.
- Potências de 2 frequentemente otimizam kernels de GPU.
- Acumulação de gradiente simula lotes maiores.
Como lidar com desequilíbrio de classes no loader?
from torch.utils.data import WeightedRandomSampler
sampler = WeightedRandomSampler(weights, num_samples=len(weights))
loader = DataLoader(ds, sampler=sampler)- Um sampler ponderado sobreamostra classes minoritárias.
DataLoader funciona no Apple Silicon?
- Sim, em CPU e MPS (Metal Performance Shaders).
pin_memorynão tem efeito no MPS - usedevice="mps".
Como depurar um DataLoader lento?
- Perfilar com
num_workers=0vs4para isolar I/O vs computação. - Verificar se
__getitem__realiza trabalho pesado (decodificação de imagens em tempo real).
Relacionados
- Training Loops - consumindo lotes
- PyTorch Basics - tipos de tensor
- GPUs & Mixed Precision - pin_memory e non_blocking
- Transfer Learning & Fine-Tuning - transforms pré-treinados
- Distributed Training - DistributedSampler
Versões da Stack: Esta página foi escrita para Python 3.14.0 (stable 3.14, maintenance 3.13), FastAPI 0.115+, Django 5.2, Flask 3.1, Pydantic 2, PyTorch 2.6+, pandas 2.2+, Polars 1.x, ruff 0.9+, e uv 0.6+.