[英]Pytorch DataLoader fails when the number of examples are not exactly divided by the batch size
我在pytorch中编写了一个自定义数据加载器类。 但是,当在一个纪元内遍历所有批次时,它将失败。 例如,假设我有100个数据示例,我的批处理大小为9。它将在第10次迭代中失败,原因是批处理大小不同,这将使批处理大小为1而不是10。我将自定义数据加载器放在下面。 我还介绍了如何从for循环内的加载程序中提取数据。
class FlatDirectoryAudioDataset(tdata.Dataset): #customized dataloader
def __init__(self, data_dir, transform=None):
self.data_dir = data_dir
self.transform = transform
self.files = self.__setup_files()
def __len__(self):
"""
compute the length of the dataset
:return: len => length of dataset
"""
return len(self.files)
def __setup_files(self):
file_names = os.listdir(self.data_dir)
files = [] # initialize to empty list
for file_name in file_names:
possible_file = os.path.join(self.data_dir, file_name)
if os.path.isfile(possible_file) and (file_name.lower().endswith('.wav') or file_name.lower().endswith('.mp3')): #&& (possible_file.lower().endswith('.wav') or possible_file.lower().endswith('.mp3')):
files.append(possible_file)
# return the files list
return files
def __getitem__ (self,index):
sample, _ = librosa.load(self.files[index], 16000)
if self.transform:
sample=self.transform(sample)
sample = torch.from_numpy(sample)
return sample
from torch.utils.data import DataLoader
my_dataset=FlatDirectoryAudioDataset(source_directory,source_folder,source_label,transform = None,label=True)
dataloader_my = DataLoader(
my_dataset,
batch_size=batch_size,
num_workers=0,
shuffle=True)
for (i,batch) in enumerate(dataloader_my,0):
print(i)
if batch.shape[0]!=16:
print(batch.shape)
assert batch.shape[0]==16,"Something wrong with the batch size"
使用drop_last = True utils.DataLoader(数据集,batch_size = batch_size,随机播放= True,drop_last = True)
设置drop_last=True
删除最后一个不完整的批次
根据您的代码制作的Dataloader精简版,批次大小没有错误。
使用9作为batch_size
并具有100个项目,最后一个批次只有一个项目。 运行下面的代码即可生成。
设置drop_last = False,最后一行被打印,并且'exception'被打印。
0 <class 'torch.Tensor'> torch.Size([9, 1])
1 <class 'torch.Tensor'> torch.Size([9, 1])
2 <class 'torch.Tensor'> torch.Size([9, 1])
3 <class 'torch.Tensor'> torch.Size([9, 1])
4 <class 'torch.Tensor'> torch.Size([9, 1])
5 <class 'torch.Tensor'> torch.Size([9, 1])
6 <class 'torch.Tensor'> torch.Size([9, 1])
7 <class 'torch.Tensor'> torch.Size([9, 1])
8 <class 'torch.Tensor'> torch.Size([9, 1])
9 <class 'torch.Tensor'> torch.Size([9, 1])
10 <class 'torch.Tensor'> torch.Size([9, 1])
# depends on drop_last=True|False
11 <class 'torch.Tensor'> torch.Size([1, 1])
Different batch size (last batch) torch.Size([1, 1])
因此该批次产生了足够好的批次物料,使其总数达到100
from torch.utils.data import DataLoader
import os
import numpy as np
import torch
import torch.utils.data.dataset as tdata
class FlatDirectoryAudioDataset(tdata.Dataset): # customized dataloader
def __init__(self):
self.files = self.__setup_files()
def __len__(self):
return len(self.files)
def __setup_files(self):
return np.array(range(100))
def __getitem__(self, index):
file = self.files[index]
sample = np.array([file])
sample = torch.from_numpy(sample)
return sample
data = FlatDirectoryAudioDataset()
my_dataset = FlatDirectoryAudioDataset()
batch_size = 9
dataloader_my = DataLoader(
my_dataset,
batch_size=batch_size,
num_workers=0,
shuffle=True,
drop_last=True)
for i, sample in enumerate(dataloader_my, 0):
print(i, print(type(sample), sample.shape)
if sample.shape[0] != batch_size:
print("Different batch size (last batch)", sample.shape)
我编写了一个名为nonechucks的库来精确地做到这一点(以防万一您的批处理量不足,而不是因为无法精确划分而存在的不良样本)。 它使您可以动态处理数据集中的不良样品(包括自动确定批次大小)。 你可以简单地包装现有的PyTorch Dataset
与周围SafeDataset
如下:
bad_dataset = Dataset(...)
import nonechucks as nc
dataset = nc.SafeDataset(bad_dataset)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.