运行-Pytorch 中(据称)空批次的时间错误
Run-time error for (allegedly) empty batches in Pytorch
(更新了对问题的进一步见解)
我有一个包含 3000 张图像的数据集,它通过以下行进入 DataLoader:
training_left_eyes = torch.utils.data.DataLoader(train_dataset, batch_size=2,shuffle=True, drop_last=True)
print(len(training_left_eyes)) #Outputs 1500
我的训练循环是这样的:
for i,(data,output) in enumerate(training_left_eyes):
data,output = data.to(device),output.to(device)
prediction = net(data)
loss = costFunc(prediction,output)
closs = loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("batch #{}".format(i))
if i%100 == 0:
print('[%d %d] loss: %.8f' % (epoch+1,i+1,closs/1000))
closs = 0
张量 "data" 和 "output"(标签)中的信息是正确的,系统工作正常,直到达到批号 1500。我的所有批次都已满,为 3000/2=1500没有剩余。一旦到达最后一批,就会出现一个 RunTimeError,说明存在 0 维输入大小。但我不知道为什么会发生这种情况,因为 enumerate(training_left_eyes) 应该遍历已满的 DataLoader 的值。
我在网上搜索了如何解决这个问题,有些人提到了 DataLoader 上的 "drop_last=True" 属性,尽管这样做是为了防止半空批次进入模型我还是试过了没有用。
我开始想太多了,似乎无法靠自己解决问题。我可以简单地插入一个 if 语句,但我认为这将是非常糟糕的做法,我想学习正确的解决方案。
如果有帮助,这是我的自定义数据集:
class LeftEyeDataset(torch.utils.data.Dataset):
"""Left eye retinography dataset. Normal/Not-normal"""
def __init__(self, csv_file, root_dir, transform=None):
"""
Args:
csv_file (string): Path to the csv file with annotations.
root_dir (string): Directory with all the images.
transform (callable, optional): Optional transform to be applied
on a sample.
"""
self.labels = label_mapping(csv_file)
self.root_dir = root_dir
self.transform = transform
self.names = name_mapping(csv_file)
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
img_name = self.root_dir +'/'+ self.names[idx]
image = io.imread(img_name)
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image,label
def label_mapping(csv_file) -> np.array:
df = read_excel(excel_file, 'Sheet1')
x= []
for key,value in df['Left-Diagnostic Keywords'].iteritems():
if value=='normal fundus':
x.append(1)
else:
x.append(0)
x_tensor = torch.LongTensor(x)
return x_tensor
def name_mapping(csv_file) -> list:
#Reads the names of the excel file
df = read_excel(excel_file, 'Sheet1')
names= list()
serie = df['Left-Fundus']
for i in range(serie.size):
names.append(df['Left-Fundus'][i])
return names
如果需要,我可以提供任何额外的代码。
更新: 经过一段时间尝试解决问题后,我设法查明发生了什么。出于某种原因,在最后一批中,进入网络的数据很好,但就在第一层之前发生了一些事情,它消失了。在下一张图片中,您可以看到我在输入 forward(self,x) 之前所做的打印以及紧接着的打印。尺寸一直对齐到批号 61(我在此示例中将其从 1500 减少),其中它以某种方式打印了两次。在该行之后,出现上述错误。
经过橡皮鸭调试了一下,发现问题不在训练上,而在验证集上。代码读取
for i,(data,output) in validate_left_eyes:
data,output = data.to(device),output.to(device)
prediction = net(data)
Validate_left_eyes_ 没有被 enumerate() 包装,因此第一批数据是空的。然后问题就解决了。
我很抱歉这部分代码没有出现在我的问题中,因此答案不是那么直接。
(更新了对问题的进一步见解)
我有一个包含 3000 张图像的数据集,它通过以下行进入 DataLoader:
training_left_eyes = torch.utils.data.DataLoader(train_dataset, batch_size=2,shuffle=True, drop_last=True)
print(len(training_left_eyes)) #Outputs 1500
我的训练循环是这样的:
for i,(data,output) in enumerate(training_left_eyes):
data,output = data.to(device),output.to(device)
prediction = net(data)
loss = costFunc(prediction,output)
closs = loss.item()
optimizer.zero_grad()
loss.backward()
optimizer.step()
print("batch #{}".format(i))
if i%100 == 0:
print('[%d %d] loss: %.8f' % (epoch+1,i+1,closs/1000))
closs = 0
张量 "data" 和 "output"(标签)中的信息是正确的,系统工作正常,直到达到批号 1500。我的所有批次都已满,为 3000/2=1500没有剩余。一旦到达最后一批,就会出现一个 RunTimeError,说明存在 0 维输入大小。但我不知道为什么会发生这种情况,因为 enumerate(training_left_eyes) 应该遍历已满的 DataLoader 的值。
我在网上搜索了如何解决这个问题,有些人提到了 DataLoader 上的 "drop_last=True" 属性,尽管这样做是为了防止半空批次进入模型我还是试过了没有用。
我开始想太多了,似乎无法靠自己解决问题。我可以简单地插入一个 if 语句,但我认为这将是非常糟糕的做法,我想学习正确的解决方案。
如果有帮助,这是我的自定义数据集:
class LeftEyeDataset(torch.utils.data.Dataset):
"""Left eye retinography dataset. Normal/Not-normal"""
def __init__(self, csv_file, root_dir, transform=None):
"""
Args:
csv_file (string): Path to the csv file with annotations.
root_dir (string): Directory with all the images.
transform (callable, optional): Optional transform to be applied
on a sample.
"""
self.labels = label_mapping(csv_file)
self.root_dir = root_dir
self.transform = transform
self.names = name_mapping(csv_file)
def __len__(self):
return len(self.labels)
def __getitem__(self, idx):
if torch.is_tensor(idx):
idx = idx.tolist()
img_name = self.root_dir +'/'+ self.names[idx]
image = io.imread(img_name)
label = self.labels[idx]
if self.transform:
image = self.transform(image)
return image,label
def label_mapping(csv_file) -> np.array:
df = read_excel(excel_file, 'Sheet1')
x= []
for key,value in df['Left-Diagnostic Keywords'].iteritems():
if value=='normal fundus':
x.append(1)
else:
x.append(0)
x_tensor = torch.LongTensor(x)
return x_tensor
def name_mapping(csv_file) -> list:
#Reads the names of the excel file
df = read_excel(excel_file, 'Sheet1')
names= list()
serie = df['Left-Fundus']
for i in range(serie.size):
names.append(df['Left-Fundus'][i])
return names
如果需要,我可以提供任何额外的代码。
更新: 经过一段时间尝试解决问题后,我设法查明发生了什么。出于某种原因,在最后一批中,进入网络的数据很好,但就在第一层之前发生了一些事情,它消失了。在下一张图片中,您可以看到我在输入 forward(self,x) 之前所做的打印以及紧接着的打印。尺寸一直对齐到批号 61(我在此示例中将其从 1500 减少),其中它以某种方式打印了两次。在该行之后,出现上述错误。
经过橡皮鸭调试了一下,发现问题不在训练上,而在验证集上。代码读取
for i,(data,output) in validate_left_eyes:
data,output = data.to(device),output.to(device)
prediction = net(data)
Validate_left_eyes_ 没有被 enumerate() 包装,因此第一批数据是空的。然后问题就解决了。
我很抱歉这部分代码没有出现在我的问题中,因此答案不是那么直接。