Pytorch's dataloader" слишком много открытых файлов " ошибка, когда файлы не должны быть открыты

Так это минимальный код, который иллюстрирует проблему:

- Это набор данных:

class IceShipDataset(Dataset):
    BAND1='band_1'
    BAND2='band_2'
    IMAGE='image'

    @staticmethod
    def get_band_img(sample,band):
        pic_size=75
        img=np.array(sample[band])
        img.resize(pic_size,pic_size)
        return img

    def __init__(self,data,transform=None):
        self.data=data
        self.transform=transform

    def __len__(self):
        return len(self.data)  

    def __getitem__(self, idx):

        sample=self.data[idx]
        band1_img=IceShipDataset.get_band_img(sample,self.BAND1)
        band2_img=IceShipDataset.get_band_img(sample,self.BAND2)
        img=np.stack([band1_img,band2_img],2)
        sample[self.IMAGE]=img
        if self.transform is not None:
                sample=self.transform(sample)
        return sample

и это код, который не выполняется:

PLAY_BATCH_SIZE=4
#load data. There are 1604 examples.
with open('train.json','r') as f:
        data=f.read()
data=json.loads(data)

ds=IceShipDataset(data)
playloader = torch.utils.data.DataLoader(ds, batch_size=PLAY_BATCH_SIZE,
                                          shuffle=False, num_workers=4)
for i,data in enumerate(playloader):
        print(i)

это дает эту странную ошибку открытых файлов в цикле for… Мой факел версия 0.3.0.post4

Если вы хотите файл json, он доступен в Kaggle (https://www.kaggle.com/c/statoil-iceberg-classifier-challenge)

Я должен упомянуть, что эта ошибка не имеет ничего общего с состоянием моего ноутбука:

yoni@yoni-Lenovo-Z710:~$ lsof | wc -l
89114
yoni@yoni-Lenovo-Z710:~$ cat /proc/sys/fs/file-max
791958

что я здесь делаю не так?

1 ответов


я знаю как исправить ошибку, но у меня нет полного объяснения, почему это происходит.

во-первых, решение: вы должны убедиться, что данные изображения хранятся в виде numpy.arrays, Когда вы вызываете json.loads он загружает их как python listС floats. Это вызывает torch.utils.data.DataLoader чтобы индивидуально преобразовать каждый поплавок в списке в torch.DoubleTensor.

посмотреть default_collate на torch.utils.data.DataLoader - код __getitem__ возвращает dict, который является отображением, так что default_collate снова вызывается для каждого элемента dict. Первая пара ints, но затем вы получаете данные изображения, которое является list, то есть a collections.Sequence - вот где все становится фанки, как default_collate вызывается для каждого элемента списка. Это явно не то, что вы хотели. Я не знаю, какое предположение в torch о содержании list и numpy.array, но, учитывая ошибку, кажется, что это предположение нарушается.

исправление довольно тривиально, просто убедитесь, что две полосы изображений numpy.arrays, например в __init__

def __init__(self,data,transform=None):
    self.data=[]
    for d in data:
        d[self.BAND1] = np.asarray(d[self.BAND1])
        d[self.BAND2] = np.asarray(d[self.BAND2])
        self.data.append(d)
    self.transform=transform

или после загрузки json, что когда-либо-не имеет значения, где вы это делаете, пока вы это делаете.


почему вышеуказанные результаты в too many open files?

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

Примечание:train.json не было доступно для загрузки из Kaggle из-за того, что конкурс все еще открыт (??). Я сделал фиктивный файл json, который должен иметь ту же структуру и протестировал исправление этого фиктивного файла.