# PyDataProvider2的使用

PyDataProvider是PaddlePaddle使用Python提供数据的推荐接口。使用该接口用户可以只关注如何 从文件中读取每一条数据，而不用关心数据如何传输给PaddlePaddle，数据如何存储等等。该数据 接口使用多线程读取数据，并提供了简单的Cache功能。

## 简单的使用场景

这里以MNIST手写识别为例，来说明简单的PyDataProvider如何使用。MNIST是一个包含有 70,000张灰度图片的数字分类数据集。对于MNIST而言，标签是0-9的数字，而特征即为 28*28的像素灰度值。这里我们使用简单的文本文件表示MNIST图片，样例数据如下。

    5;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.215686 0.533333 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.67451 0.992157 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.070588 0.886275 0.992157 0 0 0 0 0 0 0 0 0 0 0.192157 0.070588 0 0 0 0 0 0 0 0 0 0 0 0 0 0.670588 0.992157 0.992157 0 0 0 0 0 0 0 0 0 0.117647 0.933333 0.858824 0.313725 0 0 0 0 0 0 0 0 0 0 0 0.090196 0.858824 0.992157 0.831373 0 0 0 0 0 0 0 0 0 0.141176 0.992157 0.992157 0.611765 0.054902 0 0 0 0 0 0 0 0 0 0 0.258824 0.992157 0.992157 0.529412 0 0 0 0 0 0 0 0 0 0.368627 0.992157 0.992157 0.419608 0.003922 0 0 0 0 0 0 0 0 0 0.094118 0.835294 0.992157 0.992157 0.517647 0 0 0 0 0 0 0 0 0 0.603922 0.992157 0.992157 0.992157 0.603922 0.545098 0.043137 0 0 0 0 0 0 0 0.447059 0.992157 0.992157 0.956863 0.062745 0 0 0 0 0 0 0 0 0.011765 0.666667 0.992157 0.992157 0.992157 0.992157 0.992157 0.745098 0.137255 0 0 0 0 0 0.152941 0.866667 0.992157 0.992157 0.521569 0 0 0 0 0 0 0 0 0 0.070588 0.992157 0.992157 0.992157 0.803922 0.352941 0.745098 0.992157 0.945098 0.317647 0 0 0 0 0.580392 0.992157 0.992157 0.764706 0.043137 0 0 0 0 0 0 0 0 0 0.070588 0.992157 0.992157 0.776471 0.043137 0 0.007843 0.27451 0.882353 0.941176 0.176471 0 0 0.180392 0.898039 0.992157 0.992157 0.313725 0 0 0 0 0 0 0 0 0 0 0.070588 0.992157 0.992157 0.713725 0 0 0 0 0.627451 0.992157 0.729412 0.062745 0 0.509804 0.992157 0.992157 0.776471 0.035294 0 0 0 0 0 0 0 0 0 0 0.494118 0.992157 0.992157 0.968627 0.168627 0 0 0 0.423529 0.992157 0.992157 0.364706 0 0.717647 0.992157 0.992157 0.317647 0 0 0 0 0 0 0 0 0 0 0 0.533333 0.992157 0.984314 0.945098 0.603922 0 0 0 0.003922 0.466667 0.992157 0.988235 0.976471 0.992157 0.992157 0.788235 0.007843 0 0 0 0 0 0 0 0 0 0 0 0.686275 0.882353 0.364706 0 0 0 0 0 0 0.098039 0.588235 0.992157 0.992157 0.992157 0.980392 0.305882 0 0 0 0 0 0 0 0 0 0 0 0 0.101961 0.67451 0.321569 0 0 0 0 0 0 0 0.105882 0.733333 0.976471 0.811765 0.713725 0 0 0 0 0 0 0 0 0 0 0 0 0 0.65098 0.992157 0.321569 0 0 0 0 0 0 0 0 0 0.25098 0.007843 0 0 0 0 0 0 0 0 0 0 0 0 0 0 1 0.94902 0.219608 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.968627 0.764706 0.152941 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.498039 0.25098 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
    0;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.298039 0.333333 0.333333 0.333333 0.337255 0.333333 0.333333 0.109804 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.027451 0.223529 0.776471 0.964706 0.988235 0.988235 0.988235 0.992157 0.988235 0.988235 0.780392 0.098039 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.14902 0.698039 0.988235 0.992157 0.988235 0.901961 0.87451 0.568627 0.882353 0.976471 0.988235 0.988235 0.501961 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.188235 0.647059 0.988235 0.988235 0.745098 0.439216 0.098039 0 0 0 0.572549 0.988235 0.988235 0.988235 0 0 0 0 0 0 0 0 0 0 0 0 0 0.2 0.933333 0.992157 0.941176 0.247059 0 0 0 0 0 0 0.188235 0.898039 0.992157 0.992157 0 0 0 0 0 0 0 0 0 0 0 0.039216 0.639216 0.933333 0.988235 0.913725 0.278431 0 0 0 0 0 0 0 0.113725 0.843137 0.988235 0.988235 0 0 0 0 0 0 0 0 0 0 0 0.235294 0.988235 0.992157 0.988235 0.815686 0.07451 0 0 0 0 0 0 0 0.333333 0.988235 0.988235 0.552941 0 0 0 0 0 0 0 0 0 0 0.211765 0.878431 0.988235 0.992157 0.701961 0.329412 0.109804 0 0 0 0 0 0 0 0.698039 0.988235 0.913725 0.145098 0 0 0 0 0 0 0 0 0 0.188235 0.890196 0.988235 0.988235 0.745098 0.047059 0 0 0 0 0 0 0 0 0 0.882353 0.988235 0.568627 0 0 0 0 0 0 0 0 0 0.2 0.933333 0.992157 0.992157 0.992157 0.447059 0.294118 0 0 0 0 0 0 0 0 0.447059 0.992157 0.768627 0 0 0 0 0 0 0 0 0 0 0.623529 0.988235 0.988235 0.988235 0.988235 0.992157 0.47451 0 0 0 0 0 0 0 0.188235 0.933333 0.87451 0.509804 0 0 0 0 0 0 0 0 0 0 0.992157 0.988235 0.937255 0.792157 0.988235 0.894118 0.082353 0 0 0 0 0 0 0.027451 0.647059 0.992157 0.654902 0 0 0 0 0 0 0 0 0 0 0 0.623529 0.988235 0.913725 0.329412 0.376471 0.184314 0 0 0 0 0 0 0.027451 0.513725 0.988235 0.635294 0.219608 0 0 0 0 0 0 0 0 0 0 0 0.196078 0.929412 0.988235 0.988235 0.741176 0.309804 0 0 0 0 0 0 0.529412 0.988235 0.678431 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.223529 0.992157 0.992157 1 0.992157 0.992157 0.992157 0.992157 1 0.992157 0.992157 0.882353 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.023529 0.478431 0.654902 0.658824 0.952941 0.988235 0.988235 0.988235 0.992157 0.988235 0.729412 0.278431 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.196078 0.647059 0.764706 0.764706 0.768627 0.580392 0.047059 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;
    4;0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.180392 0.470588 0.623529 0.623529 0.623529 0.588235 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.243137 0.494118 0.862745 0.870588 0.960784 0.996078 0.996078 0.996078 0.996078 0.992157 0.466667 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.317647 0.639216 0.639216 0.639216 0.639216 0.639216 0.470588 0.262745 0.333333 0.929412 0.694118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.811765 0.694118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.811765 0.694118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.811765 0.694118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.184314 0.992157 0.694118 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.192157 0.996078 0.384314 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.454902 0.980392 0.219608 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.564706 0.941176 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.588235 0.776471 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.945098 0.560784 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.054902 0.952941 0.356863 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.337255 0.917647 0.109804 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.698039 0.701961 0.019608 0.4 0.662745 0.662745 0.662745 0.662745 0.662745 0.662745 0.662745 0.376471 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.090196 0.639216 0.972549 0.945098 0.913725 0.996078 0.996078 0.996078 0.996078 1 0.996078 0.996078 1 0.996078 0 0 0 0 0 0 0 0 0 0 0.007843 0.105882 0.717647 0.776471 0.905882 0.996078 0.996078 0.988235 0.980392 0.862745 0.537255 0.223529 0.223529 0.368627 0.376471 0.6 0.6 0.6 0 0 0 0 0 0 0 0 0.262745 0.470588 0.6 0.996078 0.996078 0.996078 0.996078 0.847059 0.356863 0.156863 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.909804 0.705882 0.823529 0.635294 0.490196 0.219608 0.113725 0.062745 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0.152941 0.152941 0.156863 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0;

其数据使用;间隔，第一段数据为这张图片的label，第二段数据为这个图片的像素值。 首先我们将这个数据文件(例如文件名是’mnist_train.txt’)写入train.list。那么 train.list即为

    mnist_train.txt

那么对应的dataprovider既为

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    from paddle.trainer.PyDataProvider2 import *

    # Define a py data provider
    @provider(input_types=[dense_vector(28 * 28), integer_value(10)])
    def process(settings, filename):  # settings is not used currently.
        f = open(filename, 'r')  # open one of training file

        for line in f:  # read each line
            label, pixel = line.split(';')

            # get features and label
            pixels_str = pixel.split(' ')

            pixels_float = []
            for each_pixel_str in pixels_str:
                pixels_float.append(float(each_pixel_str))

            # give data to paddle.
            yield pixels_float, int(label)

        f.close()  # close file

其中第一行是引入PaddlePaddle的PyDataProvider2包。主要函数是process函数。process函数 具有两个参数，第一个参数是 settings 。这个参数在这个样例里没有使用，具 体可以参考 settings 。第二个参数是filename，这个参数被PaddlePaddle进程传入，为 train.list中的一行(即train.list若干数据文件路径的某一个路径)。

`@provider` 是一个Python的 Decorator 。这行的作用是设置DataProvider的一些属性，并且标记process函数是一个DataProvider。 如果不了解 Decorator 是什么也没关系， 只需要知道这只是一个标记属性的方法就可以了。

属性 input_types 是设置这个DataProvider返回什么样的数据。这里设置的是返回一个 28*28的稠密向量和一个[0-9]，10维的整数值。 input_types 具体可以设置成什么其他格 式，请参考 input_types 的文档。

process函数是实现数据输入的主函数，在这个函数中，实现了打开文本文件，从文本文件中读取 每一行，并将每行转换成和 input_types 一致的特征，并在23行返回给PaddlePaddle进程。需要注意 的是， 返回的顺序需要和 input_types 中定义的顺序一致。

同时，返回数据在PaddlePaddle中是仅仅返回一条完整的训练样本，并且使用关键词 `yield` 。 在PyDataProvider中，可以为一个数据文件返回多条训练样本(就像这个样例一样)，只需要在 process函数调用多次 `yield` 即可。 `yield` 是Python的一个关键词，相关的概 念是 `generator` 。使用这个关键词，可以在一个函数里，多次返回变量。

在训练配置里，只需要使用一行代码即可以设置训练引用这个DataProvider。这个设置为

    from paddle.trainer_config_helpers import *

    define_py_data_sources2(
        train_list='train.list',
        test_list=None,
        module='mnist_provider',
        obj='process')
    img = data_layer(name='pixel', size=784)
    label = data_layer(name='label', size=10)

这里说明了训练数据是 ‘train.list’，而没有测试数据。引用的DataProvider是 ‘mnist_provider’ 这个模块中的 ‘process’ 函数。

同时，根据模型配置文件中 `data_layer` 的名字，用户也可以显式指定返回的数据对应关系。例如:

     1
     2
     3
     4
     5
     6
     7
     8
     9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    from paddle.trainer.PyDataProvider2 import *

    # Define a py data provider
    @provider(
        input_types={'pixel': dense_vector(28 * 28),
                     'label': integer_value(10)})
    def process(settings, filename):  # settings is not used currently.
        f = open(filename, 'r')  # open one of training file

        for line in f:  # read each line
            label, pixel = line.split(';')

            # get features and label
            pixels_str = pixel.split(' ')

            pixels_float = []
            for each_pixel_str in pixels_str:
                pixels_float.append(float(each_pixel_str))

            # give data to paddle.
            yield {"pixel": pixels_float, 'label': int(label)}

        f.close()  # close file

如果用户不指定返回数据的对应关系，那么PaddlePaddle会粗略的根据layer的声明顺序， 来确定对应关系。这个对应关系可能不正确。所以推荐使用显式指定返回值和数据对应关系。

至此，简单的PyDataProvider样例就说明完毕了。对于用户来说，讲数据发送给PaddlePaddle，仅仅需要 知道如何从 一个文件 里面读取 一条 样本。而PaddlePaddle进程帮助用户做了

- 将数据组合成Batch训练
- Shuffle训练数据
- 多线程数据读取
- 缓存训练数据到内存(可选)
- CPU->GPU双缓存

是不是很简单呢？

## 序列模型数据提供

序列模型是指数据的某一维度是一个序列形式，即包含时间步信息。所谓时间步信息， 不一定和时间有关系，只是说明数据的顺序是重要的。例如，文本信息就是一个序列 数据。

这里举例的数据是英文情感分类的数据。数据是给一段英文文本，分类成正面情绪和 负面情绪两类(用0和1表示)。样例数据为

    0       I saw this movie at the AFI Dallas festival . It all takes place at a lake house and it looks wonderful .
    1       This documentary makes you travel all around the globe . It contains rare and stunning sequels from the wilderness .
    ...

这里，DataProvider可以是

    from paddle.trainer.PyDataProvider2 import *

    def on_init(settings, dictionary, **kwargs):
        # on_init will invoke when data provider is initialized. The dictionary
        # is passed from trainer_config, and is a dict object with type
        # (word string => word id).

        # set input types in runtime. It will do the same thing as
        # @provider(input_types) will do, but it is set dynamically during runtime.
        settings.input_types = [
            # The text is a sequence of integer values, and each value is a word id.
            # The whole sequence is the sentences that we want to predict its
            # sentimental.
            integer_value(
                len(dictionary), seq_type=SequenceType),  # text input

            # label positive/negative
            integer_value(2)
        ]

        # save dictionary as settings.dictionary. It will be used in process
        # method.
        settings.dictionary = dictionary

    @provider(init_hook=on_init)
    def process(settings, filename):
        f = open(filename, 'r')

        for line in f:  # read each line of file
            label, sentence = line.split('\t')  # get label and sentence
            words = sentence.split(' ')  # get words

            # convert word string to word id
            # the word not in dictionary will be ignored.
            word_ids = []

            for each_word in words:
                if each_word in settings.dictionary:
                    word_ids.append(settings.dictionary[each_word])

            # give data to paddle.
            yield word_ids, int(label)

        f.close()

这个序列模型比较复杂。主要是增加了初始化机制。其中 `on_init` 函数是使用 @provider 中的 init_hook 配置参数配置给DataProvider的。这个函数会在 DataProvider创建的时候执行。这个初始化函数具有如下参数:

- 第一个参数是 settings 对象。
- 其他参数均使用key word argument形式传入。有部分参数是Paddle自动生成的， 参考 init_hook 。这里的 `dictionary` 是从训练配置传入的dict对象。 即从单词字符串到单词id的字典。

传入这个变量的方式为

    from paddle.trainer_config_helpers import *

    dictionary = dict()
    ...  #  read dictionary from outside

    define_py_data_sources2(
        train_list='train.list',
        test_list=None,
        module='sentimental_provider',
        obj='process',
        # above codes same as mnist sample.
        args={  # pass to provider.
            'dictionary': dictionary
        })

这个声明基本上和mnist的样例一致。除了

- 在配置中读取了字典
- 在声明DataProvider的时候传入了dictionary作为参数。

在 `on_init` 函数中，配置了 input_types 。这个和在 @provider 中配置 input_types 效果一致，但是在 on_init 中配置 input_types 是在运行时执行的，所以 可以根据不同的数据配置不同的输入类型。这里的输入特征是词id的序列，所以将 `seq_type` 设置成了序列(同时，也可以使用 `integer_sequence` 类型来设置)。

同时，将字典存入了settings 对象。这个字典可以在 `process` 函数中使用。 `process` 函数中的 settings 和 `on_init` 中的settings 是同一个对象。

而在 `process` 函数中，基本的处理逻辑也和mnist逻辑一致。依次返回了文件中的每条数据。

至此，基本的PyDataProvider使用介绍完毕了。具体DataProvider还具有什么功能，请参考下节reference。

## 参考(Reference)

### @provider

`@provider` 是一个Python的 Decorator ，他可以将某一个函数标记成一个PyDataProvider。它包含的参数有:

- input_types 是数据输入格式。具体有哪些格式，参考 input_types 。
- should_shuffle 是个DataProvider是不是要做shuffle，如果不设置的话，训练的时候默认shuffle， 测试的时候默认不shuffle。
- min_pool_size 是设置DataProvider在内存中最小暂存的数据条数。这个也是PaddlePaddle所能够保证的shuffle粒度。 设置成-1的话，会预先读取全部数据到内存中。
- pool_size 是设置DataProvider在内存中暂存的数据条数。设置成-1的话，即不在乎内存暂存多少条数据。
- can_over_batch_size 表示是否允许Paddle暂存略微多余pool_size的数据。这样做可以避免很多死锁问题。 一般推荐设置成True
- calc_batch_size 传入的是一个函数，这个函数以一条数据为参数，返回batch_size的大小。默认情况下一条数据 是一个batch size，但是有时为了计算均衡性，可以将一条数据设置成多个batch size
- cache 是数据缓存的策略，参考 cache
- init_hook 是初始化时调用的函数，参考 init_hook
- check 设置成true的话，会根据input_types检查数据的合法性。
- check_fail_continue 如果设置成true的话，即使在check中数据不合法，也会扔到这条数据，继续训练。 如果 check是false的话，没有作用。

### input_types

PaddlePaddle的数据包括四种主要类型，和三种序列模式。其中，四种数据类型是

- dense_vector 表示稠密的浮点数向量。
- sparse_binary_vector 表示稀疏的零一向量，即大部分值为0，有值的位置只能取1
- sparse_vector 表示稀疏的向量，即大部分值为0，有值的部分可以是任何浮点数
- integer 表示整数标签。

而三种序列模式为

- SequenceType.NO_SEQUENCE 即不是一条序列
- SequenceType.SEQUENCE 即是一条时间序列
- SequenceType.SUB_SEQUENCE 即是一条时间序列，且序列的每一个元素还是一个时间序列。

不同的数据类型和序列模式返回的格式不同，列表如下

| NO_SEQUENCE | SEQUENCE | SUB_SEQUENCE
--- | --- | --- | ---
dense_vector | [f, f, ...] | [[f, ...], [f, ...], ...] | [[[f, ...], ...], [[f, ...], ...],...]
sparse_binary_vector | [i, i, ...] | [[i, ...], [i, ...], ...] | [[[i, ...], ...], [[i, ...], ...],...]
sparse_vector | [(i,f), (i,f), ...] | [[(i,f), ...], [(i,f), ...], ...] | [[[(i,f), ...], ...], [[(i,f), ...], ...],...]
integer_value | i | [i, i, ...] | [[i, ...], [i, ...], ...]

其中，f代表一个浮点数，i代表一个整数。

### init_hook

init_hook可以传入一个函数。这个函数在初始化的时候会被调用。这个函数的参数是:

- 第一个参数是 settings 对象。这个对象和process的第一个参数一致。具有的属性有
    - settings.input_types 设置输入类型。参考 input_types
    - settings.logger 一个logging对象
- 其他参数都使用key word argument传入。这些参数包括paddle定义的参数，和用户传入的参数。
    - Paddle定义的参数包括:
        - is_train bool参数，表示这个DataProvider是训练用的DataProvider或者测试用的 DataProvider
        - file_list 所有文件列表。
    - 用户定义的参数使用args在训练配置中设置。

注意，PaddlePaddle保留添加参数的权力，所以init_hook尽量使用 `**kwargs` , 来接受不使用的 函数来保证兼容性。

### cache

DataProvider提供了两种简单的Cache策略。他们是

- CacheType.NO_CACHE 不缓存任何数据，每次都会从python端读取数据
- CacheType.CACHE_PASS_IN_MEM 第一个pass会从python端读取数据，剩下的pass会直接从内存里 读取数据。

## 注意事项

### 可能的内存泄露问题

PaddlePaddle将train.list中的每一行，都传递给process函数，从而生成多个generator。 即如果train.list中，有100个训练文件，即会生成100个generator。这个本身不是一个很 严重的问题。

但是，如果在训练时，每一条训练数据都是一个文件，并且，训练数据非常多的情况下，就 会生成多个generator。每个generator在没有调用的时候，是几乎不占内存的。但是，当调 用过一次的时候，generator便会存下当前的上下文(Context)。而这个Context可能会非常 大。并且，generator至少调用两次才会知道是否停止。所以，即使在process里面只会有一 个yield，也需要两次随机选择到同样的generator的时候，才会释放该段内存。

    def func():
        yield 0

    f = func()  # 创建generator
    tmp = next(f)  # 调用一次，返回0
    tmp = next(f)  # 调用第二次的时候，才会Stop Iteration

而如果按顺序调用这些generator就不会出现这个问题。

所以最佳实践推荐不要将每一个样本都放入train.list。而是将样本的地址放入另一个文本 文件，train.list写入那个文本文件的地址。 或者在python generator的上下文中尽量留 下非常少的变量引用。例如

    def real_process(fn):
        # ... read from fn
        return result   # 当函数返回的时候，python可以解除掉内部变量的引用。

    def process(fn):
        yield real_process(fn)

这个问题是PyDataProvider读数据时候的逻辑问题，基本上不能整体修正。

### 内存不够用的情况

PyDataProvider2会尽量使用内存。所以如果对于内存比较小的机器，推荐设置 `pool_size` 变量，而这个变量推荐大于训练的batch size，并且在内存足够 的情况下越大越好。