ValueError: опция сэмплера является взаимоисключающей с тасовкой Pytorch - PullRequest
1 голос
/ 04 апреля 2020

Я работаю над проектом по распознаванию лиц, используя pytorch и mtcnn, и после того, как я обучил мой набор обучающих данных, теперь я хочу сделать прогноз на наборе тестовых данных

это мой обученный код

optimizer = optim.Adam(resnet.parameters(), lr=0.001)
scheduler = MultiStepLR(optimizer, [5, 10])

trans = transforms.Compose([
   np.float32,
   transforms.ToTensor(),
   fixed_image_standardization
])
dataset = datasets.ImageFolder(data_dir, transform=trans)
img_inds = np.arange(len(dataset))
np.random.shuffle(img_inds)
train_inds = img_inds[:int(0.8 * len(img_inds))]
val_inds = img_inds[int(0.8 * len(img_inds)):]

train_loader = DataLoader(
   dataset,
   num_workers=workers,
   batch_size=batch_size,
   sampler=SubsetRandomSampler(train_inds)
)
val_loader = DataLoader(
   dataset,
   shuffle=True,
   num_workers=workers,
   batch_size=batch_size,
   sampler=SubsetRandomSampler(val_inds)
)

и если удалить sampler=SubsetRandomSampler(val_inds) и поставить val_inds, вместо этого возникнет эта ошибка

val_inds ^ SyntaxError: позиционный аргумент следует за ключевым аргументом

я хочу сделать прогноз (выбрать случайным образом из набора тестовых данных) в pytorch - вот почему я должен использовать shuffle=True я следовал за этим репо fa cenet -pytorch

Ответы [ 3 ]

1 голос
/ 05 апреля 2020

TLDR; Удалите shuffle=True в этом случае, поскольку SubsetRandomSampler уже перетасовывает данные.

Что делает torch.utils.data.SubsetRandomSampler (пожалуйста, обратитесь к документации, если сомневаетесь ), это займет список индексы и возвращают их случайным образом.

В вашем случае indices соответствует training (это индексы элементов в обучающей части данных ) и validation.

Давайте предположим, что они выглядят так:

train_indices = [0, 2, 3, 4, 5, 6, 9, 10, 12, 13, 15]
val_indices = [1, 7, 8, 11, 14]

Во время каждого прохода SubsetRandomSampler будет возвращать одно число из этих списков в случайном порядке и они будут снова рандомизированы после того как все они были возвращены .

Так что SubsetRandomSampler может вернуть что-то вроде этого для val_indices (аналогично для train_indices):

val_indices = [1, 8, 11, 7, 14]  # Epoch 1
val_indices = [11, 7, 8, 14, 1]  # Epoch 2
val_indices = [7, 1, 14, 8, 11]  # Epoch 3

Теперь каждый из этого цифры указатель к вашему оригиналу dataset. Обратите внимание, что оба validation перетасовываются таким образом, как и train без использования shuffle=True + оба делятся, как и должно быть.

Дополнительная информация

  • shuffle использует torch.utils.data.RandomSampler под капотом, если указано shuffle=True, см. исходный код . Это, в свою очередь, эквивалентно использованию torch.utils.data.SubsetRandomSampler с указанием всех индексов (np.arange(len(datatest))).
  • вам не нужно предварительно перемешивать np.random.shuffle(img_inds), так как индексы будут перетасовываться во время каждый проход в любом случае
  • не используйте numpy, если torch обеспечивает те же функции . Существует torch.arange, смешивание обеих библиотек практически никогда не требуется.

Вывод

Одиночное изображение

Просто передайте его через сеть для получения вывода, например:

module.eval()
with torch.no_grad():
    output = module(dataset[5380])

Первая строка переводит модель в режим оценки (изменяет поведение некоторого слоя), менеджер контекста отключает градиент (так как он не нужен для прогнозов). Они почти всегда используются при «проверке вывода нейронной сети».

Проверка набора данных проверки

Что-то в этом духе, обратите внимание на те же идеи, что и для одного изображения:

module.eval()

total_batches = 0
batch_accuracy = 0
for images, labels in val_loader:
    total_batches += 1
    with torch.no_grad():
        output = module(images)
        # In case it outputs logits without activation
        # If it outputs activation you may have to use argmax or > 0.5 for binary case
        # Item gets float from torch.tensor
        batch_accuracy += torch.mean(labels == (output > 0.0)).item()

print("Overall accuracy: {}".format(batch_accuracy / total_batches))

Другие случаи

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

0 голосов
/ 05 апреля 2020

Вы можете использовать Dataloader с shuffle = True, но только когда sampler = False. С этим флагом выборки из набора данных будут выбираться случайным образом ( do c).

Edit1

Я согласен с @SzymonMaszke: с SubsetRandomSampler нет необходимости использовать случайное перемешивание, поскольку ваши данные уже выбраны случайным образом.

0 голосов
/ 04 апреля 2020

Я не уверен, в каком формате вы тестируете данные, но для случайного выбора выборки из набора данных вы можете использовать random.choice из модуля random.

...