文章目录
前言
CV方向的深度学习算法的结构都大概差不多,大概由6部分构成:DataLoader,Loss、optimizer、lr_scheduler、module、结果可视化。接下来我会一一进行总结。
一、DataLoader
Dataloader的作用是加载数据集,为网络的训练提供数据。构建时首先复写Dataset类, Dataset类里的__getitem__ 函数被用来获取单个的数据,然后传入到DataLoader中组合成batch,再使用collate_fn所指定的函数对这个batch做一些操作,比如padding啊之类的。
- 因为不同的数据保存的格式都不一样,还要经过不同的处理变换,所以我们会经常去复写Dataset类。
- 我复写时的习惯是在__init__中构建所有样本和标签的索引列表self.data,在__getitem__里对样本和标签进行变换。
class MyDatasets(Dataset):
"""
通过包含数据路径和要指定为分类的类名
data_path:数据路径,到train或者val
img_true:二分类中,指定的类
transform: 数据处理,对图像进行随机裁剪, 以及转换成tensor。外界定义好是train的tranform或者是val的transform,然后传进来。也可以在里面定义
"""
def __init__(self, data_path, img_true, transform=None):
super(ImageDataset,self).__init__()
data_floder = os.listdir(data_path)
data = []
for item in data_floder:
img_list = os.listdir(os.path.join(data_path,item))
for img in img_list:
if item == img_true:
data.append((os.path.join(data_path,item,img),int(1)))
else:
data.append((os.path.join(data_path,item,img),int(0)))
self.data = data
self.transform = transform # 对输入图像进行预处理,这里并没有做,预设为None
def __getitem__(self,idx):
image_name, labels = self.data[idx]
image = Image.open(image_name)
if self.transform:
data = self.transform(image)
return data,labels
def __len__(self):
return len(self.data)
Dataset类构建好之后,就可以传入到DataLoader中组合成batch,继续上代码。
torch.utils.data.DataLoader(dataset, batch_size=1, shuffle=False, sampler=None,
batch_sampler=None, num_workers=0, collate_fn=None,
pin_memory=False, drop_last=False, timeout=0)
参数:
- dataset(Dataset): 传入的数据集
- batch_size(int, optional): 每个batch有多少个样本
- shuffle(bool, optional): 在每个epoch开始的时候,对数据进行重新排序
- sampler(Sampler, optional): 自定义从数据集中取样本的策略,如果指定这个参数,那么shuffle必须为False
- batch_sampler(Sampler, optional): 与sampler类似,但是一次只返回一个batch的indices(索引),需要注意的是,一旦指定了这个参数,那么batch_size,shuffle,sampler,drop_last就不能再制定了(互斥——Mutually exclusive)
- num_workers (int, optional): 这个参数决定了有几个进程来处理data loading。0意味着所有的数据都会被load进主进程。(默认为0)
- collate_fn (callable, optional): 将一个list的sample组成一个mini-batch的函数
- pin_memory (bool, optional): 如果设置为True,那么data loader将会在返回它们之前,将tensors拷贝到CUDA中的固定内存(CUDA pinned memory)中.
- drop_last (bool, optional): 如果设置为True:这个是对最后的未完成的batch来说的,比如你的batch_size设置为64,而一个epoch只有100个样本,那么训练的时候后面的36个就被扔掉了…
如果为False(默认),那么会继续正常执行,只是最后的batch_size会小一点。 - timeout(numeric, optional): 如果是正数,表明等待从worker进程中收集一个batch等待的时间,若超出设定的时间还没有收集到,那就不收集这个内容了。这个numeric应总是大于等于0。默认为0
- worker_init_fn (callable, optional): 每个worker初始化函数,是事先定义好的,可以用来分配每个worker的任务(num_workers >0时才需要他),如果num_workers >0(开启多进程)却没有手动配置每个进程的工作空间的话,默认每个进程的工作空间是整个dataset,因此每个进程都会遍历一次整个数据集,导致产生重复数据。
直接用代码来举个例子:
def worker_init_fn(worker_id):
worker_info = torch.utils.data.get_worker_info()
dataset = worker_info.dataset # the dataset copy in this worker process
overall_start = dataset.start
overall_end = dataset.end
# configure the dataset to only process the split workload
per_worker = int(math.ceil((overall_end - overall_start) / float(worker_info.num_workers)))
worker_id = worker_info.id
dataset.start = overall_start + worker_id * per_worker
dataset.end = min(dataset.start + per_worker, overall_end)