timm
ViT_Fast / datasets.py
1999xia's picture
Upload folder using huggingface_hub
54ee1eb verified
Raw
History Blame Contribute Delete
11.6 kB
import torch
import numpy as np
from torch.utils.data import DataLoader, Subset
from torchvision import datasets, transforms
from PIL import Image
import os
# Full replacement for ToTensor - use torch.tensor with numpy array conversion
def _to_tensor(pic):
if isinstance(pic, np.ndarray):
if pic.ndim == 2:
pic = pic[:, :, None]
# Use torch.tensor with explicit numpy array conversion
img = torch.tensor(pic.copy().transpose(2, 0, 1), dtype=torch.float32) / 255.0
return img.contiguous()
# Handle PIL Image
if not isinstance(pic, Image.Image):
raise TypeError(f"pic should be PIL Image or ndarray. Got {type(pic)}")
# Convert PIL to numpy then tensor
img = np.array(pic, copy=True)
if img.ndim == 2:
img = img[:, :, None]
img = torch.tensor(img.transpose(2, 0, 1), dtype=torch.float32) / 255.0
return img.contiguous()
class ToTensorFixed:
def __call__(self, pic):
return _to_tensor(pic)
def get_cifar10_loader(batch_size=64, data_dir='./data', num_workers=0, image_size=224):
transform_train = transforms.Compose([
transforms.Resize(image_size),
transforms.RandomCrop(image_size, padding=image_size//8),
transforms.RandomHorizontalFlip(),
ToTensorFixed(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])
transform_test = transforms.Compose([
transforms.Resize(image_size),
ToTensorFixed(),
transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])
train_dataset = datasets.CIFAR10(root=data_dir, train=True, download=True, transform=transform_train)
test_dataset = datasets.CIFAR10(root=data_dir, train=False, download=True, transform=transform_test)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers, pin_memory=True)
return train_loader, test_loader, 10
def get_cifar100_loader(batch_size=64, data_dir='./data', num_workers=0, image_size=224, use_randaugment=False):
transform_list = [
transforms.Resize(image_size),
transforms.RandomCrop(image_size, padding=image_size//8),
transforms.RandomHorizontalFlip(),
]
if use_randaugment:
transform_list.append(transforms.RandAugment(num_ops=2, magnitude=9))
transform_list += [
ToTensorFixed(),
transforms.Normalize((0.5071, 0.4867, 0.4408), (0.2675, 0.2565, 0.2761)),
]
transform_train = transforms.Compose(transform_list)
transform_test = transforms.Compose([
transforms.Resize(image_size),
ToTensorFixed(),
transforms.Normalize((0.5071, 0.4867, 0.4408), (0.2675, 0.2565, 0.2761)),
])
train_dataset = datasets.CIFAR100(root=data_dir, train=True, download=True, transform=transform_train)
test_dataset = datasets.CIFAR100(root=data_dir, train=False, download=True, transform=transform_test)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers, pin_memory=True)
return train_loader, test_loader, 100
def get_tiny_imagenet_loader(batch_size=64, data_dir='./data/tiny-imagenet', num_workers=0, image_size=224):
"""Tiny-ImageNet loader with optional resize to 224x224 for ViT."""
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
transform_train = transforms.Compose([
transforms.Resize(image_size),
transforms.RandomCrop(image_size, padding=image_size // 8),
transforms.RandomHorizontalFlip(),
ToTensorFixed(),
normalize,
])
transform_test = transforms.Compose([
transforms.Resize(image_size),
ToTensorFixed(),
normalize,
])
train_dataset = datasets.ImageFolder(os.path.join(data_dir, 'train'), transform=transform_train)
test_dataset = datasets.ImageFolder(os.path.join(data_dir, 'val'), transform=transform_test)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True, num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False, num_workers=num_workers, pin_memory=True)
return train_loader, test_loader, 200
def get_oxford_pets_loader(batch_size=32, data_dir='./data', num_workers=0, image_size=224, val_ratio=0.2):
"""Oxford-IIIT Pets loader with train/val split from the trainval set.
Official split: trainval (3,680) + test (3,669), 37 classes.
We further split trainval into train (80%) and val (20%).
Used in ViT paper (Dosovitskiy et al., 2021).
"""
from torchvision.datasets import OxfordIIITPet
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
transform_train = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.RandomCrop(image_size, padding=image_size // 8),
transforms.RandomHorizontalFlip(),
ToTensorFixed(),
normalize,
])
transform_test = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.CenterCrop(image_size),
ToTensorFixed(),
normalize,
])
# Load trainval set, then split into train + val
full_train_dataset = OxfordIIITPet(
root=data_dir, split='trainval', download=True, transform=transform_train)
test_dataset = OxfordIIITPet(
root=data_dir, split='test', download=True, transform=transform_test)
n_train = len(full_train_dataset)
n_val = int(n_train * val_ratio)
n_train_split = n_train - n_val
gen = torch.Generator().manual_seed(42)
train_dataset, val_dataset = torch.utils.data.random_split(
full_train_dataset, [n_train_split, n_val], generator=gen)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True,
num_workers=num_workers, pin_memory=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
return train_loader, val_loader, test_loader, 37
def _make_generic_loader(dataset_class, batch_size, data_dir, num_workers, image_size,
val_ratio, train_split, test_split, num_classes, normalize=None):
"""Helper for datasets with train/test splits and optional val split from train."""
if normalize is None:
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
transform_train = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.RandomCrop(image_size, padding=image_size // 8),
transforms.RandomHorizontalFlip(),
ToTensorFixed(),
normalize,
])
transform_test = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.CenterCrop(image_size),
ToTensorFixed(),
normalize,
])
full_train = dataset_class(root=data_dir, split=train_split, download=True, transform=transform_train)
test_dataset = dataset_class(root=data_dir, split=test_split, download=True, transform=transform_test)
n_val = int(len(full_train) * val_ratio)
n_train = len(full_train) - n_val
gen = torch.Generator().manual_seed(42)
train_dataset, val_dataset = torch.utils.data.random_split(full_train, [n_train, n_val], generator=gen)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True,
num_workers=num_workers, pin_memory=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
return train_loader, val_loader, test_loader, num_classes
def get_food101_loader(batch_size=32, data_dir='./data', num_workers=0, image_size=224, val_ratio=0.1):
"""Food-101: 101 classes, 75,750 train / 25,250 test."""
from torchvision.datasets import Food101
return _make_generic_loader(Food101, batch_size, data_dir, num_workers, image_size,
val_ratio, 'train', 'test', 101)
def get_stanford_cars_loader(batch_size=32, data_dir='./data', num_workers=0, image_size=224, val_ratio=0.1):
"""Stanford Cars: 196 classes, 8,144 images total."""
from torchvision.datasets import StanfordCars
return _make_generic_loader(StanfordCars, batch_size, data_dir, num_workers, image_size,
val_ratio, 'train', 'test', 196)
def get_dtd_loader(batch_size=32, data_dir='./data', num_workers=0, image_size=224, val_ratio=0.1):
"""DTD (Describable Textures): 47 classes, 5,640 images."""
from torchvision.datasets import DTD
return _make_generic_loader(DTD, batch_size, data_dir, num_workers, image_size,
val_ratio, 'train', 'test', 47)
def get_flowers102_loader(batch_size=32, data_dir='./data', num_workers=0, image_size=224, val_ratio=0.2):
"""Flowers-102: 102 classes, 1020 train / 1020 val / 6149 test.
Official split: train (1020), val (1020), test (6149).
We combine train+val, then split 80/20 for train/val.
"""
from torchvision.datasets import Flowers102
normalize = transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
transform_train = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.RandomCrop(image_size, padding=image_size // 8),
transforms.RandomHorizontalFlip(),
ToTensorFixed(),
normalize,
])
transform_test = transforms.Compose([
transforms.Resize(int(image_size * 1.14)),
transforms.CenterCrop(image_size),
ToTensorFixed(),
normalize,
])
# Combine train + val splits for more training data
train_part = Flowers102(root=data_dir, split='train', download=True, transform=transform_train)
val_part = Flowers102(root=data_dir, split='val', download=True, transform=transform_train)
test_dataset = Flowers102(root=data_dir, split='test', download=True, transform=transform_test)
from torch.utils.data import ConcatDataset
full_train = ConcatDataset([train_part, val_part])
n_val = int(len(full_train) * val_ratio)
n_train = len(full_train) - n_val
gen = torch.Generator().manual_seed(42)
train_dataset, val_dataset = torch.utils.data.random_split(full_train, [n_train, n_val], generator=gen)
train_loader = DataLoader(train_dataset, batch_size=batch_size, shuffle=True,
num_workers=num_workers, pin_memory=True)
val_loader = DataLoader(val_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
test_loader = DataLoader(test_dataset, batch_size=batch_size, shuffle=False,
num_workers=num_workers, pin_memory=True)
return train_loader, val_loader, test_loader, 102