Use Dataloaders
Dataloader是为模型提供数据的部分,一个dataloader通常从数据集中获取行信息,处理为模型需要的格式。
How the Existing Dataloader Works
Detectron2提供了两个方法从config来创建一个默认的dataloader:build_detection_{train, test}_loader,下面是工作原理:
-
它首先用一个注册数据集的名称拿到该数据集,让后用一个轻量级的格式加载一个list[dict]来表示该数据集。这些数据集还没准备好被模型使用(比如还需要加载图片到内存,随机数据增强还未应用等)。具体的数据集格式,以及如何进行数据增强,可以在datasets中查看。
-
每个dict都会被mapper方法进行处理:
- 用户可以通过build_detection_{train,test}_loader方法中的mapper参数的传入来自定义mapping方法,默认额mapper是DatasetMapper
- mapper的输出格式可以是任意的,只要符合模型的输入格式要求即可
- mapper的作用之一是将一个数据item的轻量化表示变成模型输入的格式(包括读图片,随机增强,转Tensor等)
-
mapper的输出是Batch后的(支持list)
-
Batched的数据是dataloader的输出,也是模型的model.forward()的输入
Write a Custom Dataloader
使用一个自定义的mapper传入到build_detection_{train,test}_loader,可以支持自定义数据的加载。例如,如果你想讲所有的图片放缩到固定大小,再输入训练,可以进行以下代码:
import detectron2.data.transforms as T
from detectron2.data import DatasetMapper
dataloader = build_detection_train_loader(cfg, mapper=DatasetMapper(cfg, is_train=True, augmentations=[T.Resize(800, 800)]))
# 使用这个dataloader代替默认
如果默认的DatasetMapper不能满足你的需要,你可以编写一个自定义mapper函数,例如下:
from detectron2.data import detection_utils as utils
# 展示如何编写一个最小mapper,与默认DataSetMapper类似
def mapper(dataset_dict):
dataset_dict = copy.deepcopy(dataset_dict) # 需要保证原始数据不被改变
# 也可以使用其他方式读取图片
image = utils.read_image(dataset_dict["file_name"], format="BGR")
# 可以使用其他增强
transform = T.Resize(800, 800).get_transform(image)
image = torch.from_numpy(transform.apply_image(image).transpose(2,0,1))
anno = [
utils.tranform_instance_annotation(annotation, [transfom], image.shape[1:])
for annotation in dataset_dict.pop("annotation")
]
return {
# 返回模型需要的格式
"image": image,
"instances": utils.annotation_to_instances(annos, image.shape[1:])
}
dataloader = build_detection_train_loader(cfg, mapper=mapper)
如果你想自定义的不仅仅是mapper方法(例如实现采样算法,不同的batching逻辑等),build_detection_train_loader不会起作用,你需要编写一个不同的dataloader。编写的dataloader是一个简单的数据迭代器,你可以再其中添加任意功能,只要输出符合模型输入即可。
Use a Custom Dataloader
如果使用DefaultTrainer,你可以覆写DefaultTrainer的build_{train,test}_loader方法来使用你的自定义dataloader。
如果你自定义编写train loop,你可以轻易的添加自定义dataloader。