PyTorch - преобразование набора данных CIFAR в `TensorDataset`

Я обучаю ResNet34 на наборе данных CIFAR. По определенной причине мне нужно преобразовать набор данных в TensorDataset. Мое решение основано на следующем: https://stackoverflow.com/a/44475689/15072863 с некоторыми отличиями (возможно, они критичны, но я не понимаю почему). Похоже, я делаю это неправильно.

Погрузчик поезда:

transform_train = transforms.Compose([
    transforms.RandomCrop(32, padding=4),
    transforms.RandomHorizontalFlip(),
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010))])

train_ds = torchvision.datasets.CIFAR10('/files/', train=True, transform=transform_train, download=True)

xs, ys = [], []
for x, y in train_ds:
  xs.append(x)
  ys.append(y)

# 1) Standard Version
# cifar_train_loader = DataLoader(train_ds, batch_size=batch_size_train, shuffle=True, num_workers=num_workers)

# 2) TensorDataset version, seems to be incorrect
cifar_tensor_ds = TensorDataset(torch.stack(xs), torch.tensor(ys, dtype=torch.long))
cifar_train_loader = DataLoader(cifar_tensor_ds, batch_size=batch_size_train, shuffle=True, num_workers=num_workers)

Я не думаю, что это важно, но тестовый загрузчик определяется как обычно:

transform_test = transforms.Compose([
    transforms.ToTensor(),
    transforms.Normalize((0.4914, 0.4822, 0.4465), (0.2023, 0.1994, 0.2010)),
])

cifar_test_loader = DataLoader(
  torchvision.datasets.CIFAR10('/files/', train=False, transform=transform_test, download=True),
  batch_size=batch_size_test, shuffle=False, num_workers=num_workers)

Я знаю, что что-то не так с тем, как я использую TensorDataset, поскольку;

  1. С TensorDataset я достигаю 100% точности поезда, 80% точности теста
  2. Со стандартным набором данных я достигаю 99% точности поезда (никогда не 100%), точности теста 90%.

Итак, что я делаю не так?

P.S .: Моя конечная цель - разбить набор данных на 10 наборов данных в зависимости от их класса. Есть лучший способ сделать это? Конечно, я могу определить свой подкласс DataSet, но вручную разделить его и создать TensorDataset оказалось проще.


person Dmitry    schedule 27.01.2021    source источник


Ответы (1)


При использовании стандартного набора данных каждый раз, когда вы загружаете изображение, к нему применяется случайное преобразование (отражение + обрезка). Как следствие, практически каждое изображение каждой эпохи уникально, увиденное только один раз. Итак, у вас есть nb_epochs * len(dataset) разные входы.

С вашим пользовательским набором данных вы сначала читаете все изображения dset CIFAR (каждое из них со случайным преобразованием), сохраняете их все, а затем используете сохраненный тензор в качестве входных данных для обучения. Таким образом, в каждую эпоху сеть видит одни и те же входы.

Поскольку сеть уже смогла достичь высокой точности с помощью случайных преобразований, удаление ее делает ее еще проще и, следовательно, еще больше повышает точность.

О, и вам обязательно нужно переопределить собственный подкласс Dataset. Это даже не сложно, и работать с ним будет намного проще. Вам просто нужно извлечь 10 разных наборов данных, либо вручную переместив изображения в их папки, либо используя какие-то переиндексируемые массивы или что-то в этом роде. В любом случае, вам нужно будет сделать это только один раз, так что не беда

person trialNerror    schedule 28.01.2021
comment
Спасибо. В своем посте я указал неверные цифры: точность тестирования была ниже для TensorDataset. Ваше объяснение имеет смысл. - person Dmitry; 28.01.2021