没有文件应该打开时PyTorch的dataloader"太多打开文件"错误

Yon*_*ren 12 python python-3.x pytorch

所以这是一个说明问题的最小代码:

这是数据集:

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
Run Code Online (Sandbox Code Playgroud)

这是失败的代码:

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)
Run Code Online (Sandbox Code Playgroud)

它在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
Run Code Online (Sandbox Code Playgroud)

我在这做错了什么?

Mat*_*yra 6

我知道如何修复该错误,但我没有完整的解释为什么会发生这种情况。

首先,解决方案:您需要确保图像数据存储为numpy.arrays,当您调用json.loads它时将它们加载为slist的 python s float。这会导致将torch.utils.data.DataLoader列表中的每个浮点数单独转换为torch.DoubleTensor.

看看default_collatein torch.utils.data.DataLoader- your __getitem__returns a ,dict它是一个映射,因此default_collate会在 的每个元素上再次调用dict。第一对是ints,但随后你会得到图像数据,即 a list,即 a collections.Sequence- 这就是事情变得有趣的地方,因为default_collate在列表的每个元素上调用。这显然不是你想要的。我不知道a与 atorch的内容的假设是什么,但考虑到错误,似乎违反了该假设。listnumpy.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
Run Code Online (Sandbox Code Playgroud)

或者在加载 json 之后,无论在哪里执行,只要执行即可,并不重要。


为什么会出现上面的结果呢too many open files

我不知道,但正如评论所指出的,这可能与进程间通信以及从两个队列中获取和添加数据的锁定文件有关。

脚注:train.json由于比赛仍在进行中,无法从 Kaggle 下载(??)。我制作了一个应该具有相同结构的虚拟 json 文件,并测试了对该虚拟文件的修复。

  • 对我来说,将以下内容放在程序开头解决了我的问题:`torch.multiprocessing.set_sharing_strategy('file_system')` (3认同)