#python #numpy #deep-learning #pytorch #torch
#python #numpy #глубокое обучение #pytorch #torch
Вопрос:
Я пытаюсь вычислить среднее и std для массива тензоров факела. Мой набор данных содержит 720 обучающих изображений, и каждое из этих изображений имеет 4 ориентира, где X и Y представляют 2D-точку на изображении.
to_tensor = transforms.ToTensor()
landmarks_arr = []
for i in range(len(train_dataset)):
landmarks_arr.append(to_tensor(train_dataset[i]['landmarks']))
mean = torch.mean(torch.stack(landmarks_arr, dim=0))#, dim=(0, 2, 3))
std = torch.std(torch.stack(landmarks_arr, dim=0)) #, dim=(0, 2, 3))
print(mean.shape)
print("mean is {} and std is {}".format(mean, std))
Результат:
torch.Size([])
mean is nan and std is nan
Существует пара проблем, описанных выше:
- Почему to_tensor не преобразует значения между 0 и 1?
- как правильно вычислить среднее значение?
- Должен ли я делить на 255 и где?
У меня есть:
len(landmarks_arr)
720
и
landmarks_arr[0].shape
torch.Size([1, 4, 2])
и
landmarks_arr[0]
tensor([[[502.2869, 240.4949],
[688.0000, 293.0000],
[346.0000, 317.0000],
[560.8283, 322.6830]]], dtype=torch.float64)
Ответ №1:
- Из документов pytorch ToTensor():
Преобразует PIL-изображение или numpy.ndarray (H x W x C) в диапазоне [0, 255] в torch.Плавающий тензор формы (C x H x W) в диапазоне [0.0, 1.0], если PIL-изображение принадлежит одному из режимов (L, LA, P, I, F, RGB, YCbCr, RGBA, CMYK, 1) или если numpy.ndarray имеет dtype = np.uint8
В других случаях тензоры возвращаются без масштабирования.
Поскольку ваши значения ориентиров не являются PIL-изображением и не находятся в пределах [0, 255], масштабирование не применяется.
- Ваш расчет кажется правильным. Кажется, что у вас может быть некоторое значение NaN в ваших данных.
Вы можете попробовать что-то вроде
for i in range(len(train_dataset)):
landmarks = to_tensor(train_dataset[i]['landmarks'])
landmarks[landmarks != landmarks] = 0 # this will set all nan to zero
landmarks_arr.append(landmarks)
в вашем цикле. Или assert для nan в цикле, чтобы найти виновника (ов):
for i in range(len(train_dataset)):
landmarks = to_tensor(train_dataset[i]['landmarks'])
assert(not torch.isnan(landmarks).any()), f'nan encountered in sample {i}' # will trigger if a landmark contains nan
landmarks_arr.append(landmarks)
- Нет, см. 1). Вы можете разделить на максимальные координаты ориентиров, хотя и ограничить их [0, 1], если вы того пожелаете.
Комментарии:
1. почему я должен делить на максимальную координату, если to_tensor уже помещает их между [0, 1]?
2. потому
toTensor
что помещает изображения PIL между [0,1]. Ваша цель / ориентиры останутся неизменными. Итак, если вы хотите нормализовать свой ориентир на [0,1], вы можете разделить на максимальную координату.3. ————————————————————————— Трассировка ошибки утверждения (последний последний вызов) <ipython-input-20-19e49f3367ed> в <модуле> 7 для i в диапазоне (len(train_dataset)): 8 ориентиров = to_tensor(train_dataset[i][‘ориентиры’]) —-> 9 assert(не torch.isnan(ориентиры).any()), f’nan, встречающиеся в образце {i}’ #, будут срабатывать, если ориентир содержит nan 10 landmarks_arr.append(ориентиры) 11 Ошибка утверждения: nan встречается в образце 56
4. Безусловно, было бы более эффективно вычислять максимум по всему массиву, а не перебирать отдельные записи.