首页 > 技术文章 > paddle02-paddle.io(数据读取相关) 【完】

NSEW 2021-05-06 13:29 原文

paddle.io

⭐ 多进程数据读取器相关API 2/3/4接口组成

1.  构造数据集;   paddle.io.Dataset()
2. mini-batch数据生成:   
  * 2.1 mini-batch 数据下标索引选择
          * paddle.io.BatchSampler()
  * 2.2 利用mini-batch 索引生成 mini-batch数据:  paddle.io.DataLoader()

  • 1)paddle.io.Dataset() 得到标准数据集:内容、长度、索引访问
  • 2)paddle.io.DataLoader() 生成mini-batch 数据迭代器
  • mini-batch 组成:
    • 3.1paddle.io.Dataloader() 中: Dataset + batch_size, shuffle, drop_last 自动构建

      paddle.io.Dataset()
      paddle.io.DataLoader(Dataset=, batch_size=, shuffle=, drop_last=,)
      
      mini-batch 的下标索引生成方式?  
      
    • 3.2paddle.DataLoader() 中 Dataset + Batch_sampler()中 shuffle, drop_last, batch_size

      paddle.io.Dataset()
      paddle.io.DataLoader(dataset=, batch_sampler=)
      
      paddle.io.BatchSampler(dataset=, shuffle=, batch_size=, drop_last=,)
      
      利用BatchSampler 生成 mini-batch 数据的索引, 索引生成方式?  
      
    • 3.3paddle.io.DataLoader() 中 DataLoader() + Batch_Sampler() 中的 sampler=()

      paddle.io.Dataset()
      paddle.io.DataLoader(dataset=, batch_sampler=)
      
      paddle.io.BatchSampler(sampler=, shuffle=, batch_size, drop_out=)
      paddle.io.Sampler(data_source) / paddle.io.RandomSampler() 等等几种采样方式   
      利用BatchSampler 生成 mini-batch 数据的索引,  索引生成方式由 sampler= 指定
      

mini-batch 数据生成接口

  • 1.class paddle.io.DataLoader(dataset, feed_list= None, places= None, return_list=False, batch_sampler= None, batch_size=1, shuffle= False, drop_last= False, collate_fn= None, num_workers=0) 多进程数据读取器

    DataLoader 返回一个 迭代器, 其根据 batch_sampler 给定的顺序迭代一次给定的 dataset.  
    DataLoader 支持单线程 和 多线程 的数据加载方式,当 num_workers 大于0时,将使用多进程方式异步加载数据。  
    DataLoader 当前支持 map-style 和 iterable-style 的数据集, map-style 的数据集可通过 下标索引样本, 参考: paddle.io.Dataset;  iterable-style 数据集只能 迭代式地获取样本,类似 Python 迭代器, 参考: paddle.io.IterableDataset  
    batch_sampler 参考 paddle.io.BatchSampler  
    
    * 参数: 
        1.⭐dataset: Dataset类型, DataLoader 从此参数给定的数据集中加载数据,此参数必须是: paddle.io.Dataset 或 paddle.io.IterableDataset 的一个 子类实例。   
        2.feed_list: list[tensor] / tuple[tensor], 由 paddle.static.data() 创建。当 return_list 为False时,此参数必须设置。默认值为None  
        3. 不懂.places (list(Place)|tuple(Place)) - 数据需要放置到的Place列表。在静态图和动态图模式中,此参数均必须设置。在动态图模式中,此参数列表长度必须是1。默认值为None
        4.不懂: return_list (bool) - 每个设备上的数据是否以list形式返回。若return_list = False,每个设备上的返回数据均是str -> Tensor的映射表,其中映射表的key是每个输入变量的名称。若return_list = True,则每个设备上的返回数据均是list(Tensor)。在动态图模式下,此参数必须为True。默认值为False  
        5.⭐ batch_sampler: BatchSampler, paddle.io.BatchSampler 或 其子类地实例, DataLoader 通过 batch_sampler 产生地 mini-batch 索引列表来 dataset中索引样本并组成 mini-batch, 默认值None.  
        6.⭐ batch_size: int/None, 每个 mini-batch 中样本个数, 为 batch_sampler 的代替参数,若 batch_sampler 未设置,会根据 batch_size, shuffle, drop_last 创建一个 paddle.io.BatchSampler。 默认值: 1.  
        7.⭐ shuffle: bool, 生成 mini-batch 索引列表时,是否对索引打乱顺序,未 batch_sampler地替代参数, 若 batch_sampler 未设置,会根据 batch_size, shuffle, drop_last 创建一个 paddle.io.BatchSampler。 默认值: False.  
        8.⭐ drop_last: bool, 是否丢弃因数据集样本数不能被 batch_size 整除而产生的最后一个 不完整地 mini-batch, 若 batch_sampler 未设置,会根据 batch_size, shuffle, drop_last 创建一个 paddle.io.BatchSampler。 默认值: False.  
        9. collate_fn:(callable) - 通过此参数指定如果将样本列表组合为mini-batch数据,当 collate_fn 为None时,默认为将样本个字段在第0维上堆叠(同 np.stack(..., axis=0) )为mini-batch的数据。默认值为None。
        10.num_workers: int, 用于加载数据的 子进程个数,若0,则不开启子进程,在主进程中进行数据加载。 默认值:0  
        11.use_buffer_reader: bool, 是否使用缓存读取器。若 use_buffer_reader 为 True, DataLoader 会异步地 预读取下一个 mini-batch 的数据, 可加速数据读取过程,但同时会占用少量地 CPU/GPU存储,即一个 batch 地存储空间,默认值: True.  
        12.use_shared_memory: bool, 是否使用共享内存来提升 子进程 将数据放入进程间队列地速度,该参数仅在 多进程模式下有效(即:num_workers > 0), 请确认机器上有足够地共享内存空间,默认:False.  
        13.timeout: int, 从子进程输出队列获取mini-batch数据的超时时间。默认值为0.  
        14.worker_init_fn: callable, 子进程初始化函数, 此函数会被 子进程初始化时 被调用,并传递 worker_id 作为参数,默认值:None.  
    
    返回: 迭代 dataset 数据的迭代器,迭代器返回的数据中每个元素都是 一个tensor.  
    返回类型: DataLoader   
    
    loader = DataLoader(dataset,
                    batch_size=BATCH_SIZE,
                    shuffle=True,
                    drop_last=True,
                    num_workers=2)
    
    • 方法: from_generator() 此API将被弃用,推荐使用 paddle.io.DataLoader()
    • 方法: from_dataset() 此API将被 弃用,推荐使用 paddle.io.DataLoader()
  • 2.paddle.io.get_worker_info() 获取当前子进程相关信息

    获取 paddle.io.DataLoader 子进程信息的函数,用于 paddle.io.IterableDataset 中划分子进程数据。子进程信息包含以下字段:
        num_workers: 子进程数。
        id: 子进程逻辑序号,从0到 num_workers - 1
        dataset: 各子进程中数据集实例。
    
  • 3.paddle.io.default_collate_fn() 多进程DataLoader 中默认组 batch 函数

  • 4.paddle.io.default_convert_fn() 多进程DataLoader中默认转换函数,在多进程DataLoader中不组batch时使用,只将数据转换为Tensor而不组batch

一、数据集定义相关API

  • 1.class paddle.io.Dataset() 映射式(map-style)数据集基类定义接口

    概述 Dataset 的方法和行为的抽象类。  
    映射式(map-style) 数据集需要继承这个基类,映射式数据集 可以通过一个键值 索引并获取指定样本的数据集,所有映射式数据集必须实现以下方法: 
    1.___getitem__: 根据给定索引 获取数据集中指定样本,在 paddle.io.DataLoader 中需要使用此函数通过下标获取样本。  
    2.__len__: 返回数据集样本个数, paddle.io.BatchSampler 中需要样本个数生成 下标序列。 
    
    from paddle.io import Dataset  
    
    # define a random dataset 
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples  
        
        def __getitem__(self, idx):
            image = np.random.random([784]).astype("float32")
            label = np.random.randint(0, 9, (1, ).astype("int64")
    
            return image, label  
    
        def __len__(self):
            return self.num_samples  
    
    dataset = RandomDataset(10)
    for i in range(len(dataset)):
        print(dataset[i])
    
  • 2.paddle.io.IterableDataset() 迭代式(iterable-style)数据集基类定义接口

    概述 迭代式(iterable-style)数据集的方法和行为的抽象类  
    迭代式(iterable-style)数据集需要继承这个基类,迭代式数据集只能  依次迭代式  获取样本的数据集,类似python中的迭代器。迭代式数据集需要实现以下方法: 
    * __iter__ : 依次返回数据赝本  
    注意: 迭代式数据集不需要实现: __getitem__ 和 __len__, 也不可以调用 迭代式数据集的这两个方法。   
    
    from paddle.io import Dataset
    
    # define a random dataset
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples
    
        def __iter__(self):
            for i in range(self.num_samples):
                image = np.random.random([784]).astype('float32')
                label = np.random.randint(0, 9, (1, )).astype('int64')
                yield image, label
    
    dataset = RandomDataset(10)
    for img, lbl in dataset:
        print(img, lbl)
    
    • 当 paddle.io.DataLoader 中 num_workers > 0 时,每个子进程都会遍历全量的数据集返回全量样本,所以数据集会重复 num_workers 次,如果需要数据集样本不会重复返回,可通过如下两种方法避免样本重复,两种方法中都需要通过 paddle.io.get_worker_info 获取各子进程的信息。
    • 1.通过 iter 函数划分各子进程的数据
    • 2.通过各子进程初始化函数 worker_inif_fn 划分子进程数据
  • 3.paddle.io.TensorDateset() 张量(Tensor)数据集基类定义接口

二、采样器相关API

  • 1.class paddle.io.Sampler(data_source=None) 采样器基类定义接口

    概括数据集采样器行为和方法的基类  
    所有数据采样器必须继承这个基类,并实现以下方法: 
        * __iter__: 迭代返回数据样本下标。  
        * __len__: data_source 中的样本数  
    
    参数: 
        data_source: Dataset, 参数必须式:padlde.io.Dataset()  或  paddle.io.IterableDataset 的一个子类实例 或 实现了 __len__ 的 python对象,用于生成样本下标,默认None。  
    
    from paddle.io import Dataset, Sampler
    
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples
    
        def __getitem__(self, idx):
            image = np.random.random([784]).astype('float32')
            label = np.random.randint(0, 9, (1, )).astype('int64')
            return image, label
    
        def __len__(self):
            return self.num_samples
    
    class MySampler(Sampler):
        def __init__(self, data_source):
            self.data_source = data_source
    
        def __iter__(self):
            return iter(range(len(self.data_source)))
    
        def __len__(self):
            return len(self.data_source)
    
    sampler = MySampler(data_source=RandomDataset(100))
    
    for index in sampler:
        print(index)
    
  • 2.paddle.io.SequenceSampler(data_source= None) 顺序采样器接口

    顺序迭代 data_source 返回样本下标,即一次返回 0, 1, 2, ..., len(data_source) - 1
    
    参数: data_source: Dataset ,此参数必须是 paddle.io.Dataset 或 paddle.io.IterableDataset 的一个子类实例或实现了 __len__ 的Python对象,用于生成样本下标。默认值为None  
    
    返回: 返回样本下标的迭代器  
    返回类型: SequenceSampler
    
    from paddle.io import Dataset, SequenceSampler
    
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples
    
        def __getitem__(self, idx):
            image = np.random.random([784]).astype('float32')
            label = np.random.randint(0, 9, (1, )).astype('int64')
            return image, label
    
        def __len__(self):
            return self.num_samples
    
    sampler = SequenceSampler(data_source=RandomDataset(100))
    
    for index in sampler:
        print(index)    
    
    
  • 3.paddle.io.RandomSampler(data_source=None, replacement=False, num_samples=None, generator=None) 随机采样器接口

    随机迭代样本,产生重排下标,如果 replacement = False ,则会采样整个数据集;如果 replacement = True ,则会按照 num_samples 指定的样本数采集  
    
    参数: 
        1.data_source: Dataset, 此参数必须是 paddle.io.Dataset 或 paddle.io.IterableDataset 的一个子类实例或实现了 __len__ 的Python对象,用于生成样本下标。默认值为None   
        2. replacement: bool, False:默认,采样整个数据集, True: 按照 num_samples指定的样本数采集。  
        3. num_samples: int, 如果replacement=True, 则按照此参数采集对应的样本数,默认值: None  
        4. generator: Generator, 指定采样 data_source 的采样器,默认值:None.   
    返回: 
        RandomSampler, 返回随机采样下标的 采样器。  
    
    from paddle.io import Dataset, RandomSampler
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples
    
        def __getitem__(self, idx):
            image = np.random.random([784]).astype('float32')
            label = np.random.randint(0, 9, (1, )).astype('int64')
            return image, label
    
        def __len__(self):
            return self.num_samples
    sampler = RandomSampler(data_source=RandomDataset(100))
    for index in sampler:
        print(index)
    
  • 4.paddle.io.WeightedRandomSampler(weights, num_samples, replacement= True) 带权重随机采样器接口

三、批采样器相关API

  • 1.paddle.io.BatchSampler(dataset= None, sampler= None, shuffle= False, batch_size= 1, drop_last= False) 批采样器接口

    批采样器的基础实现,用于 paddle.io.DataLoader 中迭代式获取 mini-batch 的样本下标数据,数组长度= batch_size.  
    所有用于 paddle.io.DataLoader 中的批采样器都必须是 paddle.io.BatchSampler 的子类并实现方法: 
        1. __iter__: 迭代式返回批样本下标数据。  
        2. __len__: mini-batch 数量  
    
    参数: 
        1.dataset: Dataset, 此参数必须是 paddle.io.Dataset 或 paddle.io.IterableDataset 的一个子类实例或实现了 __len__ 的Python对象,用于生成样本下标。默认值为None   
        2.sampler: Sampler, 此参数必须是 paddle.io.Sampler 的子类实例,用于迭代式获取样本下标。dataset 和 sampler 参数只能设置一个。默认值为None   
        3.shuffle: bool, 是否需要在生成样本下标时打乱顺序,默认值: False  
        4.batch_size: int, mini-batch 中包含的样本数,默认值: 1
        5.drop_last: bool, 是否需要丢弃最后无法凑整一个 mini-batch 的样本,默认值: False  
    
    返回: 返回样本下标数组的迭代器。  
    返回类型: BatchSampler
    
    
    # 1. init with dataset
    class RandomDataset(Dataset):
        def __init__(self, num_samples):
            self.num_samples = num_samples
    
        def __getitem__(self, idx):
            image = np.random.random([784]).astype('float32')
            label = np.random.randint(0, 9, (1, )).astype('int64')
            return image, label
    
        def __len__(self):
            return self.num_samples
    bs = BatchSampler(dataset=RandomDataset(100),
                shuffle=False,
                batch_size=16,
                drop_last=False)
    for batch_indices in bs:
        print(batch_indices)
    
    
    # 2.init with sampler
    sampler = RandomSampler(RandomDataset(100))
    bs = BatchSampler(sampler=sampler,
                batch_size=8,
                drop_last=True)
    
    for batch_indices in bs:
        print(batch_indices)
    
  • 2.paddle.io.DistributedBatchSampler() 分布式批采样器接口,用于分布式 多卡场景

数据集操作相关API

  • paddle.io.ChainDataset() 数据集样本级联接口

  • paddle.io.ComposeDataset() 数据集字段接口组合

  • paddle.io.Subset() 数据集取子集接口

推荐阅读