PyTorch 的数据加载器 "too many open files" 没有文件应该打开时出错
PyTorch's dataloader "too many open files" error when no files should be open
所以这是说明问题的最小代码:
这是数据集:
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 循环中给出了奇怪的打开文件错误…
我的 torch 版本是 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
我做错了什么?
我知道如何修复错误,但我没有完整的解释为什么会发生。
首先,解决方案:你需要确保图像数据存储为numpy.array
s,当你调用json.loads
时它会加载它们作为 python list
的 float
。这导致 torch.utils.data.DataLoader
将列表中的每个浮点数单独转换为 torch.DoubleTensor
.
看看 torch.utils.data.DataLoader
中的 default_collate
- 你的 __getitem__
returns 一个 dict
是一个映射,所以 default_collate
得到再次调用 dict
的每个元素。第一对是 int
s,但随后你得到的图像数据是 list
,即 collections.Sequence
- 这是调用 default_collate
时事情变得古怪的地方在列表的每个元素上。这显然不是您想要的。我不知道 torch
中关于 list
与 numpy.array
的内容的假设是什么,但考虑到错误,似乎违反了该假设。
修复非常简单,只需确保两个图像波段是 numpy.array
s,例如 __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 文件,并测试了该虚拟文件的修复。
所以这是说明问题的最小代码:
这是数据集:
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 循环中给出了奇怪的打开文件错误… 我的 torch 版本是 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
我做错了什么?
我知道如何修复错误,但我没有完整的解释为什么会发生。
首先,解决方案:你需要确保图像数据存储为numpy.array
s,当你调用json.loads
时它会加载它们作为 python list
的 float
。这导致 torch.utils.data.DataLoader
将列表中的每个浮点数单独转换为 torch.DoubleTensor
.
看看 torch.utils.data.DataLoader
中的 default_collate
- 你的 __getitem__
returns 一个 dict
是一个映射,所以 default_collate
得到再次调用 dict
的每个元素。第一对是 int
s,但随后你得到的图像数据是 list
,即 collections.Sequence
- 这是调用 default_collate
时事情变得古怪的地方在列表的每个元素上。这显然不是您想要的。我不知道 torch
中关于 list
与 numpy.array
的内容的假设是什么,但考虑到错误,似乎违反了该假设。
修复非常简单,只需确保两个图像波段是 numpy.array
s,例如 __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 文件,并测试了该虚拟文件的修复。