From 9a601dd2bfd69ef4c5837861580b8b7f54041653 Mon Sep 17 00:00:00 2001 From: RaindragonD Date: Fri, 28 Jun 2019 23:55:01 +0800 Subject: [PATCH] update api_cn (#954) * update api_cn; fix the error of reverting layers_cn to 1.4; include previous changes * update layers_cn; add code example to elementwise_mod * delete recordio_writer_cn; revert index_cn * update api_cn after review * fix io_cn.rst * update layers_cn * update io_cn --- doc/fluid/api_cn/backward_cn.rst | 72 +- doc/fluid/api_cn/clip_cn.rst | 64 +- doc/fluid/api_cn/data/data_reader_cn.rst | 212 +- doc/fluid/api_cn/data/dataset_cn.rst | 4 +- doc/fluid/api_cn/data_feeder_cn.rst | 162 +- doc/fluid/api_cn/dataset_cn.rst | 199 +- doc/fluid/api_cn/executor_cn.rst | 484 +-- doc/fluid/api_cn/fluid_cn.rst | 1774 ++++++++--- doc/fluid/api_cn/initializer_cn.rst | 39 +- doc/fluid/api_cn/io_cn.rst | 465 ++- doc/fluid/api_cn/layers_cn.rst | 3648 +++++++++++++++++----- doc/fluid/api_cn/metrics_cn.rst | 932 +++--- doc/fluid/api_cn/nets_cn.rst | 21 +- doc/fluid/api_cn/optimizer_cn.rst | 1639 ++++++---- doc/fluid/api_cn/profiler_cn.rst | 35 +- doc/fluid/api_cn/recordio_writer_cn.rst | 77 - doc/fluid/api_cn/regularizer_cn.rst | 44 +- doc/fluid/api_cn/transpiler_cn.rst | 258 +- doc/fluid/api_cn/unique_name_cn.rst | 95 + 19 files changed, 7248 insertions(+), 2976 deletions(-) delete mode 100644 doc/fluid/api_cn/recordio_writer_cn.rst create mode 100644 doc/fluid/api_cn/unique_name_cn.rst diff --git a/doc/fluid/api_cn/backward_cn.rst b/doc/fluid/api_cn/backward_cn.rst index 9e23d7b86..4c095dac4 100644 --- a/doc/fluid/api_cn/backward_cn.rst +++ b/doc/fluid/api_cn/backward_cn.rst @@ -25,67 +25,59 @@ append_backward 返回: 成对参数及其相应的梯度。键是参数,值是梯度变量。 -返回类型: list[(Variable,Variable)] +返回类型: list[(Variable,Variable)] 抛出: - ``AssertionError`` - 如果loss不是Variable的实例。 **示例代码** -.. code-block:: python +.. code-block:: python # 网络配置 - # ... + # 损失计算 + x = fluid.layers.data(name='x', shape=[13], dtype='float32') + y = fluid.layers.data(name='y', shape=[1], dtype='float32') + + y_predict = fluid.layers.fc(input=x, size=1, act=None) + loss = fluid.layers.square_error_cost(input=y_predict, label=y) + avg_loss = fluid.layers.mean(loss) param_grad_list = fluid.backward.append_backward(loss=avg_loss) +.. _cn_api_fluid_backward_gradients: +gradients +------------------------------- +.. py:function:: paddle.fluid.backward.gradients(targets, inputs, target_gradients=None, no_grad_set=None) +将目标梯度反向传播到输入。 +参数: + - **targets** (Variable|list[Variable]) – 目标变量 + - **inputs** (Variable|list[Variable]) – 输入变量 + - **target_gradients** (Variable|list[Variable]|None) – 目标的梯度变量,应与目标变量形状相同;如果设置为None,则以1初始化所有梯度变量 + - **no_grad_sethread** (set[string]) – 在Block 0中不具有梯度的变量,所有block中被设置 ``stop_gradient=True`` 的变量将被自动加入该set +返回:数组,包含与输入对应的梯度。如果一个输入不影响目标函数,则对应的梯度变量为None +返回类型:(list[Variable]) +**示例代码** +.. code-block:: python + import paddle.fluid as fluid - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + x = fluid.layers.data(name='x', shape=[2,8,8], dtype='float32') + x.stop_gradient=False + y = fluid.layers.conv2d(x, 4, 1, bias_attr=False) + y = fluid.layers.relu(y) + y = fluid.layers.conv2d(y, 4, 1, bias_attr=False) + y = fluid.layers.relu(y) + z = fluid.gradients([y], x) + print(z) \ No newline at end of file diff --git a/doc/fluid/api_cn/clip_cn.rst b/doc/fluid/api_cn/clip_cn.rst index 9a7641206..a4004ba99 100644 --- a/doc/fluid/api_cn/clip_cn.rst +++ b/doc/fluid/api_cn/clip_cn.rst @@ -28,8 +28,23 @@ ErrorClipByValue .. code-block:: python - var = fluid.framework.Variable(..., error_clip=ErrorClipByValue(max=5.0), ...) - + import paddle.fluid as fluid + BATCH_SIZE = 128 + CLIP_MAX = 2e-6 + CLIP_MIN = -1e-6 + prog = fluid.framework.Program() + with fluid.program_guard(main_program=prog): + image = fluid.layers.data(name='x', shape=[784], dtype='float32') + hidden1 = fluid.layers.fc(input=image, size=128, act='relu') + hidden2 = fluid.layers.fc(input=hidden1, size=64, act='relu') + predict = fluid.layers.fc(input=hidden2, size=10, act='softmax') + label = fluid.layers.data(name='y', shape=[1], dtype='int64') + cost = fluid.layers.cross_entropy(input=predict, label=label) + avg_cost = fluid.layers.mean(cost) + prog_clip = prog.clone() + prog_clip.block(0).var(hidden1.name)._set_error_clip( + fluid.clip.ErrorClipByValue( + max=CLIP_MAX, min=CLIP_MIN) @@ -70,12 +85,27 @@ GradientClipByGlobalNorm .. code-block:: python + import paddle.fluid as fluid + prog = fluid.framework.Program() + startup_program = fluid.framework.Program() + with fluid.program_guard( + main_program=prog, startup_program=startup_program): + image = fluid.layers.data(name='x', shape=[784], dtype='float32') + label = fluid.layers.data(name='y', shape=[1], dtype='int64') + hidden1 = fluid.layers.fc(input=image, size=128, act='relu') + hidden2 = fluid.layers.fc(input=hidden1, size=64, act='relu') + predict = fluid.layers.fc(input=hidden2, size=10, act='softmax') + cost = fluid.layers.cross_entropy(input=predict, label=label) + avg_cost = fluid.layers.mean(cost) + prog_clip = prog.clone() + avg_cost_clip = prog_clip.block(0).var(avg_cost.name) p_g_clip = fluid.backward.append_backward(loss=avg_cost_clip) with fluid.program_guard(main_program=prog_clip): - fluid.clip.set_gradient_clip( - fluid.clip.GradientClipByGlobalNorm(clip_norm=2.0)) - p_g_clip = fluid.clip.append_gradient_clip_ops(p_g_clip) + fluid.clip.set_gradient_clip( + fluid.clip.GradientClipByGlobalNorm(clip_norm=2.0)) + p_g_clip = fluid.clip.append_gradient_clip_ops(p_g_clip) + @@ -108,12 +138,14 @@ GradientClipByNorm .. code-block:: python + import paddle.fluid as fluid w_param_attrs = fluid.ParamAttr(name=None, - initializer=fluid.initializer.UniformInitializer(low=-1.0, high=1.0, seed=0), - learning_rate=1.0, - regularizer=fluid.regularizer.L1Decay(1.0), - trainable=True, - clip=fluid.clip.GradientClipByNorm(clip_norm=2.0)) + initializer=fluid.initializer.UniformInitializer(low=-1.0, high=1.0, seed=0), + learning_rate=1.0, + regularizer=fluid.regularizer.L1Decay(1.0), + trainable=True, + gradient_clip=fluid.clip.GradientClipByNorm(clip_norm=2.0)) + x = fluid.layers.data(name='x', shape=[10], dtype='float32') y_predict = fluid.layers.fc(input=x, size=1, param_attr=w_param_attrs) @@ -147,12 +179,14 @@ GradientClipByValue .. code-block:: python + import paddle.fluid as fluid w_param_attrs = fluid.ParamAttr(name=None, - initializer=fluid.initializer.UniformInitializer(low=-1.0, high=1.0, seed=0), - learning_rate=1.0, - regularizer=fluid.regualrizer.L1Decay(1.0), - trainable=True, - clip=fluid.clip.GradientClipByValue(-1.0, 1.0)) + initializer=fluid.initializer.UniformInitializer(low=-1.0, high=1.0, seed=0), + learning_rate=1.0, + regularizer=fluid.regualrizer.L1Decay(1.0), + trainable=True, + gradient_clip=fluid.clip.GradientClipByValue(-1.0, 1.0)) + x = fluid.layers.data(name='x', shape=[10], dtype='float32') y_predict = fluid.layers.fc(input=x, size=1, param_attr=w_param_attrs) diff --git a/doc/fluid/api_cn/data/data_reader_cn.rst b/doc/fluid/api_cn/data/data_reader_cn.rst index 3510cb0da..b46b1559c 100644 --- a/doc/fluid/api_cn/data/data_reader_cn.rst +++ b/doc/fluid/api_cn/data/data_reader_cn.rst @@ -19,11 +19,12 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut .. code-block:: python - place = fluid.CPUPlace() - img = fluid.layers.data(name='image', shape=[1, 28, 28]) - label = fluid.layers.data(name='label', shape=[1], dtype='int64') - feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) - result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) + import paddle.fluid as fluid + place = fluid.CPUPlace() + img = fluid.layers.data(name='image', shape=[1, 28, 28]) + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) + result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) 如果您想在使用多个GPU训练模型时预先将数据单独输入GPU端,可以使用decorate_reader函数。 @@ -33,10 +34,16 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut .. code-block:: python - place=fluid.CUDAPlace(0) - feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) - reader = feeder.decorate_reader( - paddle.batch(flowers.train(), batch_size=16)) + import paddle + import paddle.fluid as fluid + + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[3, 224, 224], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader( + paddle.batch(paddle.dataset.flowers.train(), batch_size=16), multi_devices=False) 参数: @@ -44,23 +51,39 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut - **place** (Place) – place表示将数据输入CPU或GPU,如果要将数据输入GPU,请使用fluid.CUDAPlace(i)(i表示GPU的ID),如果要将数据输入CPU,请使用fluid.CPUPlace()。 - **program** (Program) –将数据输入的Program,如果Program为None,它将使用default_main_program() 。默认值None。 -抛出异常: ``ValueError`` – 如果某些变量未在Program中出现 +抛出异常: ``ValueError`` – 如果某些变量未在Program中出现 **代码示例** .. code-block:: python - # ... - place = fluid.CPUPlace() - feed_list = [ - main_program.global_block().var(var_name) for var_name in feed_vars_name - ] # feed_vars_name is a list of variables' name. - feeder = fluid.DataFeeder(feed_list, place) - for data in reader(): - outs = exe.run(program=main_program, - feed=feeder.feed(data)) + import numpy as np + import paddle + import paddle.fluid as fluid + place = fluid.CPUPlace() + + def reader(): + yield [np.random.random([4]).astype('float32'), np.random.random([3]).astype('float32')], + + main_program = fluid.Program() + startup_program = fluid.Program() + + with fluid.program_guard(main_program, startup_program): + data_1 = fluid.layers.data(name='data_1', shape=[1, 2, 2]) + data_2 = fluid.layers.data(name='data_2', shape=[1, 1, 3]) + out = fluid.layers.fc(input=[data_1, data_2], size=2) + # ... + + feeder = fluid.DataFeeder([data_1, data_2], place) + + exe = fluid.Executor(place) + exe.run(startup_program) + for data in reader(): + outs = exe.run(program=main_program, + feed=feeder.feed(data), + fetch_list=[out]) .. py:method:: feed(iterable) @@ -74,6 +97,24 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut 返回类型: dict +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield random.random([784]).astype('float32'), random.random([1]).astype('int64'), random.random([256]).astype('float32') + + data_1 = fluid.layers.data(name='data_1', shape=[1, 28, 28]) + data_2 = fluid.layers.data(name='data_2', shape=[1], dtype='int64') + data_3 = fluid.layers.data(name='data_3', shape=[16, 16], dtype='float32') + feeder = fluid.DataFeeder(['data_1','data_2', 'data_3'], fluid.CPUPlace()) + + result = feeder.feed(reader()) + .. py:method:: feed_parallel(iterable, num_places=None) @@ -92,7 +133,35 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut .. note:: - 设备数量和mini-batches数量必须一致。 + 设备数量和mini-batches数量必须一致。 + +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=10): + for i in range(limit): + yield [random.random([784]).astype('float32'), random.randint(10)], + + x = fluid.layers.data(name='x', shape=[1, 28, 28]) + y = fluid.layers.data(name='y', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(['x','y'], fluid.CPUPlace()) + place_num = 2 + places = [fluid.CPUPlace() for x in range(place_num)] + data = [] + exe = fluid.Executor(fluid.CPUPlace()) + exe.run(fluid.default_startup_program()) + program = fluid.CompiledProgram(fluid.default_main_program()).with_data_parallel(places=places) + for item in reader(): + data.append(item) + if place_num == len(data): + exe.run(program=program, feed=list(feeder.feed_parallel(data, place_num)), fetch_list=[]) + data = [] + .. py:method:: decorate_reader(reader, multi_devices, num_places=None, drop_last=True) @@ -108,7 +177,32 @@ DataFeeder将reader返回的数据转换为可以输入Executor和ParallelExecut 返回类型: dict -抛出异常: ``ValueError`` – 如果drop_last为False并且数据batch和设备数目不匹配。 +抛出异常: ``ValueError`` – 如果drop_last为False并且数据batch和设备数目不匹配。 + +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield (random.random([784]).astype('float32'), random.random([1]).astype('int64')), + + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[1, 28, 28], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader(reader, multi_devices=False) + + exe = fluid.Executor(place) + exe.run(fluid.default_startup_program()) + for data in reader(): + exe.run(feed=data) + .. _cn_api_paddle_data_reader_reader: @@ -118,10 +212,10 @@ Reader 在训练和测试时,PaddlePaddle需要读取数据。为了简化用户编写数据读取代码的工作,我们定义了 - - reader是一个读取数据(从文件、网络、随机数生成器等)并生成数据项的函数。 - - reader creator是返回reader函数的函数。 - - reader decorator是一个函数,它接受一个或多个reader,并返回一个reader。 - - batch reader是一个函数,它读取数据(从reader、文件、网络、随机数生成器等)并生成一批数据项。 + - reader是一个读取数据(从文件、网络、随机数生成器等)并生成数据项的函数。 + - reader creator是返回reader函数的函数。 + - reader decorator是一个函数,它接受一个或多个reader,并返回一个reader。 + - batch reader是一个函数,它读取数据(从reader、文件、网络、随机数生成器等)并生成一批数据项。 Data Reader Interface @@ -131,7 +225,7 @@ Data Reader Interface .. code-block:: python - iterable = data_reader() + iterable = data_reader() 从iterable生成的元素应该是单个数据条目,而不是mini batch。数据输入可以是单个项目,也可以是项目的元组,但应为 :ref:`user_guide_paddle_support_data_types` (如, numpy 1d array of float32, int, list of int) @@ -140,22 +234,22 @@ Data Reader Interface .. code-block:: python - def reader_creator_random_image(width, height): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height) - return reader + def reader_creator_random_image(width, height): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height) + return reader 多项目数据读取器创建者的示例实现: .. code-block:: python - def reader_creator_random_image_and_label(width, height, label): - def reader(): - while True: - yield numpy.random.uniform(-1, 1, size=width*height), label - return reader + def reader_creator_random_image_and_label(width, height, label): + def reader(): + while True: + yield numpy.random.uniform(-1, 1, size=width*height), label + return reader .. py:function:: paddle.reader.map_readers(func, *readers) @@ -198,7 +292,7 @@ Data Reader Interface 返回:新的数据读取器 -抛出异常: ``ComposeNotAligned`` – reader的输出不一致。 当check_alignment设置为False,不会升高。 +抛出异常: ``ComposeNotAligned`` – reader的输出不一致。 当check_alignment设置为False,不会升高。 @@ -274,32 +368,32 @@ PipeReader通过流从一个命令中读取数据,将它的stdout放到管道 .. code-block:: python - def example_reader(): - for f in myfiles: - pr = PipeReader("cat %s"%f) - for l in pr.get_line(): - sample = l.split(" ") - yield sample + def example_reader(): + for f in myfiles: + pr = PipeReader("cat %s"%f) + for l in pr.get_line(): + sample = l.split(" ") + yield sample .. py:method:: get_line(cut_lines=True, line_break='\n') param cut_lines: - cut buffer to lines + cut buffer to lines -type cut_lines: bool +type cut_lines: bool param line_break: - line break of the file, like + line break of the file, like or type line_break: - string + string -return: one line or a buffer of bytes +return: one line or a buffer of bytes -rtype: string +rtype: string @@ -315,11 +409,11 @@ multiprocess.queue需要/dev/shm的rw访问权限,某些平台不支持。 .. code-block:: python - reader0 = reader(["file01", "file02"]) - reader1 = reader(["file11", "file12"]) - reader1 = reader(["file21", "file22"]) - reader = multiprocess_reader([reader0, reader1, reader2], - queue_size=100, use_pipe=False) + reader0 = reader(["file01", "file02"]) + reader1 = reader(["file11", "file12"]) + reader1 = reader(["file21", "file22"]) + reader = multiprocess_reader([reader0, reader1, reader2], + queue_size=100, use_pipe=False) @@ -338,11 +432,11 @@ Fakereader将缓存它读取的第一个数据,并将其输出data_num次。 .. code-block:: python - def reader(): - for i in range(10): - yield i + def reader(): + for i in range(10): + yield i - fake_reader = Fake()(reader, 100) + fake_reader = Fake()(reader, 100) Creator包包含一些简单的reader creator,可以在用户Program中使用。 @@ -374,4 +468,4 @@ Creator包包含一些简单的reader creator,可以在用户Program中使用 路径:recordio文件的路径,可以是字符串或字符串列表。 -返回: recordio文件的数据读取器 +返回:recordio文件的数据读取器 diff --git a/doc/fluid/api_cn/data/dataset_cn.rst b/doc/fluid/api_cn/data/dataset_cn.rst index aee1d2e5d..286a3bd0c 100644 --- a/doc/fluid/api_cn/data/dataset_cn.rst +++ b/doc/fluid/api_cn/data/dataset_cn.rst @@ -18,7 +18,7 @@ MNIST数据集。 MNIST训练数据集的creator。 -它返回一个reader creator, reader中的每个样本的图像像素范围是[0,1],标签范围是[0,9]。 +它返回一个reader creator, reader中的每个样本的图像像素范围是[-1,1],标签范围是[0,9]。 返回: 训练数据的reader creator @@ -30,7 +30,7 @@ MNIST训练数据集的creator。 MNIST测试数据集的creator。 -它返回一个reader creator, reader中的每个样本的图像像素范围是[0,1],标签范围是[0,9]。 +它返回一个reader creator, reader中的每个样本的图像像素范围是[-1,1],标签范围是[0,9]。 返回: 测试数据集的reader creator diff --git a/doc/fluid/api_cn/data_feeder_cn.rst b/doc/fluid/api_cn/data_feeder_cn.rst index d157397c1..321f72013 100644 --- a/doc/fluid/api_cn/data_feeder_cn.rst +++ b/doc/fluid/api_cn/data_feeder_cn.rst @@ -14,65 +14,107 @@ DataFeeder ``DataFeeder`` 负责将reader(读取器)返回的数据转成一种特殊的数据结构,使它们可以输入到 ``Executor`` 和 ``ParallelExecutor`` 中。 -reader通常返回一个minibatch条目列表。在列表中每一条目都是一个样本(sample),它是由具有一至多个特征的列表或元组组成的。 +reader通常返回一个minibatch条目列表。在列表中每一条目都是一个样本(sample),它是由具有一至多个特征的列表或元组组成的。 以下是简单用法: -.. code-block:: python - - place = fluid.CPUPlace() - img = fluid.layers.data(name='image', shape=[1, 28, 28]) - label = fluid.layers.data(name='label', shape=[1], dtype='int64') - feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) - result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) - +.. code-block:: python + + import paddle.fluid as fluid + place = fluid.CPUPlace() + img = fluid.layers.data(name='image', shape=[1, 28, 28]) + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) + result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) + 在多GPU模型训练时,如果需要提前分别向各GPU输入数据,可以使用 ``decorate_reader`` 函数。 -.. code-block:: python +.. code-block:: python + + import paddle + import paddle.fluid as fluid - place=fluid.CUDAPlace(0) - feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) - reader = feeder.decorate_reader( - paddle.batch(flowers.train(), batch_size=16)) + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[3, 224, 224], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader( + paddle.batch(paddle.dataset.flowers.train(), batch_size=16), multi_devices=False) 参数: - - **feed_list** (list) – 向模型输入的变量表或者变量表名 - - **place** (Place) – place表明是向GPU还是CPU中输入数据。如果想向GPU中输入数据, 请使用 ``fluid.CUDAPlace(i)`` (i 代表 the GPU id);如果向CPU中输入数据, 请使用 ``fluid.CPUPlace()`` - - **program** (Program) – 需要向其中输入数据的Program。如果为None, 会默认使用 ``default_main_program()``。 缺省值为None + - **feed_list** (list) – 向模型输入的变量表或者变量表名 + - **place** (Place) – place表明是向GPU还是CPU中输入数据。如果想向GPU中输入数据, 请使用 ``fluid.CUDAPlace(i)`` (i 代表 the GPU id);如果向CPU中输入数据, 请使用 ``fluid.CPUPlace()`` + - **program** (Program) – 需要向其中输入数据的Program。如果为None, 会默认使用 ``default_main_program()``。 缺省值为None -弹出异常: ``ValueError`` – 如果一些变量不在此 Program 中 +弹出异常: ``ValueError`` – 如果一些变量不在此 Program 中 **代码示例** -.. code-block:: python - - # ... - place = fluid.CPUPlace() - feed_list = [ - main_program.global_block().var(var_name) for var_name in feed_vars_name - ] # feed_vars_name 是一个由变量名组成的列表 - feeder = fluid.DataFeeder(feed_list, place) - for data in reader(): - outs = exe.run(program=main_program, - feed=feeder.feed(data)) - - +.. code-block:: python + + import numpy as np + import paddle + import paddle.fluid as fluid + + place = fluid.CPUPlace() + def reader(): + yield [np.random.random([4]).astype('float32'), np.random.random([3]).astype('float32')], + + main_program = fluid.Program() + startup_program = fluid.Program() + + with fluid.program_guard(main_program, startup_program): + data_1 = fluid.layers.data(name='data_1', shape=[1, 2, 2]) + data_2 = fluid.layers.data(name='data_2', shape=[1, 1, 3]) + out = fluid.layers.fc(input=[data_1, data_2], size=2) + # ... + feeder = fluid.DataFeeder([data_1, data_2], place) + + exe = fluid.Executor(place) + exe.run(startup_program) + for data in reader(): + outs = exe.run(program=main_program, + feed=feeder.feed(data), + fetch_list=[out]) + + + + .. py:method:: feed(iterable) 根据feed_list(数据输入表)和iterable(可遍历的数据)提供的信息,将输入数据转成一种特殊的数据结构,使它们可以输入到 ``Executor`` 和 ``ParallelExecutor`` 中。 -参数: - - **iterable** (list|tuple) – 要输入的数据 +参数: + - **iterable** (list|tuple) – 要输入的数据 返回: 转换结果 -返回类型: dict +返回类型: dict + +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield random.random([784]).astype('float32'), random.random([1]).astype('int64'), random.random([256]).astype('float32') + + data_1 = fluid.layers.data(name='data_1', shape=[1, 28, 28]) + data_2 = fluid.layers.data(name='data_2', shape=[1], dtype='int64') + data_3 = fluid.layers.data(name='data_3', shape=[16, 16], dtype='float32') + feeder = fluid.DataFeeder(['data_1','data_2', 'data_3'], fluid.CPUPlace()) + + result = feeder.feed(reader()) .. py:method:: feed_parallel(iterable, num_places=None) @@ -80,7 +122,7 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 该方法获取的多个minibatch,并把每个minibatch提前输入进各个设备中。 -参数: +参数: - **iterable** (list|tuple) – 要输入的数据 - **num_places** (int) – 设备数目。默认为None。 @@ -91,12 +133,38 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 .. note:: 设备(CPU或GPU)的数目必须等于minibatch的数目 +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=10): + for i in range(limit): + yield [random.random([784]).astype('float32'), random.randint(10)], + + x = fluid.layers.data(name='x', shape=[1, 28, 28]) + y = fluid.layers.data(name='y', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(['x','y'], fluid.CPUPlace()) + place_num = 2 + places = [fluid.CPUPlace() for x in range(place_num)] + data = [] + exe = fluid.Executor(fluid.CPUPlace()) + exe.run(fluid.default_startup_program()) + program = fluid.CompiledProgram(fluid.default_main_program()).with_data_parallel(places=places) + for item in reader(): + data.append(item) + if place_num == len(data): + exe.run(program=program, feed=list(feeder.feed_parallel(data, place_num)), fetch_list=[]) + data = [] + .. py:method:: decorate_reader(reader, multi_devices, num_places=None, drop_last=True) - 将reader返回的输入数据batch转换为多个mini-batch,之后每个mini-batch都会被输入进各个设备(CPU或GPU)中。 参数: @@ -111,9 +179,29 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 弹出异常: ValueError – 如果 ``drop_last`` 值为False并且reader返回的minibatch数目与设备数目不相等时,产生此异常 +**代码示例** - +.. code-block:: python + import numpy.random as random + import paddle + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield (random.random([784]).astype('float32'), random.random([1]).astype('int64')), + + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[1, 28, 28], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader(reader, multi_devices=False) + + exe = fluid.Executor(place) + exe.run(fluid.default_startup_program()) + for data in reader(): + exe.run(feed=data) diff --git a/doc/fluid/api_cn/dataset_cn.rst b/doc/fluid/api_cn/dataset_cn.rst index 09d1f7add..55fd8363e 100644 --- a/doc/fluid/api_cn/dataset_cn.rst +++ b/doc/fluid/api_cn/dataset_cn.rst @@ -14,28 +14,221 @@ DatasetFactory .. py:class:: paddle.fluid.dataset.DatasetFactory -DatasetFactory是一个按数据集名称创建数据集的 "工厂" ,可以创建“QueueDataset”或“InMemoryDataset”,默认为“QueueDataset”。 +DatasetFactory是一个按数据集名称创建数据集的 "工厂",可以创建“QueueDataset”,“InMemoryDataset”或“FileInstantDataset”,默认为“QueueDataset”。 + **代码示例** .. code-block:: python - dataset = paddle.fluid.DatasetFactory.create_dataset(“InMemoryDataset”) + import paddle.fluid as fluid + dataset = paddle.fluid.DatasetFactory().create_dataset("InMemoryDataset") .. py:method:: create_dataset(datafeed_class='QueueDataset') -创建“QueueDataset”或“InMemoryDataset”,默认为“QueueDataset”。 +创建“QueueDataset”,“InMemoryDataset” 或 “FileInstantDataset”,默认为“QueueDataset”。 + + +参数: + - **datafeed_class** (str) – datafeed类名,为QueueDataset或InMemoryDataset。默认为QueueDataset。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + dataset = fluid.DatasetFactory().create_dataset() + + + +.. _cn_api_fluid_dataset_InMemoryDataset: + +InMemoryDataset +------------------------------- + +.. py:class:: paddle.fluid.dataset.InMemoryDataset + +InMemoryDataset会向内存中加载数据并在训练前缓冲数据。此类由DatasetFactory创建。 + +**代码示例**: + +.. code-block:: python + + dataset = paddle.fluid.DatasetFactory().create_dataset(“InMemoryDataset”) + + +.. py:method:: load_into_memory() + +向内存中加载数据。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + + +.. py:method:: local_shuffle() + +局域shuffle。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + dataset.local_shuffle() + + +.. py:method:: global_shuffle(fleet=None) + +全局shuffle。 + +只能用在分布式模式(单机多进程或多机多进程)中。您如果在分布式模式中运行,应当传递fleet而非None。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + from paddle.fluid.incubate.fleet.parameter_server.pslib import fleet + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + dataset.global_shuffle(fleet) + +参数: + - **fleet** (Fleet) – fleet单例。默认为None。 + +.. py:method:: release_memory() +当数据不再使用时,释放InMemoryDataset内存数据。 +**代码示例**: +.. code-block:: python + + import paddle.fluid as fluid + from paddle.fluid.incubate.fleet.parameter_server.pslib import fleet + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + dataset.global_shuffle(fleet) + exe = fluid.Executor(fluid.CPUPlace()) + exe.run(fluid.default_startup_program()) + exe.train_from_dataset(fluid.default_main_program(), dataset)dataset.release_memory() + dataset.release_memory() + +.. py:method:: get_memory_data_size(fleet=None) + +用户可以调用此函数以了解加载进内存后所有workers中的ins数量。 + +.. note:: + 该函数可能会导致性能不佳,因为它具有barrier。 + +参数: + - **fleet** (Fleet) – fleet对象。 + +返回:内存数据的大小。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + from paddle.fluid.incubate.fleet.parameter_server.pslib import fleet + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + print dataset.get_memory_data_size(fleet) + + +.. py:method:: get_shuffle_data_size(fleet=None) + +获取shuffle数据大小,用户可以调用此函数以了解局域/全局shuffle后所有workers中的ins数量。 + +.. note:: + 该函数可能会导致局域shuffle性能不佳,因为它具有barrier。但其不影响局域shuffle。 + +参数: + - **fleet** (Fleet) – fleet对象。 + +返回:shuffle数据的大小。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + from paddle.fluid.incubate.fleet.parameter_server.pslib import fleet + dataset = fluid.DatasetFactory().create_dataset("InMemoryDataset") + filelist = ["a.txt", "b.txt"] + dataset.set_filelist(filelist) + dataset.load_into_memory() + dataset.global_shuffle(fleet) + print dataset.get_shuffle_data_size(fleet) +.. _cn_api_fluid_dataset_QueueDataset: +QueueDataset +------------------------------- + +.. py:class:: paddle.fluid.dataset.QueueDataset + +流式处理数据。 + +**代码示例**: + +.. code-block:: python + + import paddle.fluid as fluid + dataset = fluid.DatasetFactory().create_dataset("QueueDataset") + + + +.. py:method:: local_shuffle() + +局域shuffle数据 +QueueDataset中不支持局域shuffle,可能抛出NotImplementedError +**代码示例**: +.. code-block:: python + + import paddle.fluid as fluid + dataset = fluid.DatasetFactory().create_dataset("QueueDataset") + dataset.local_shuffle() + + + +.. py:method:: global_shuffle(fleet=None) + +全局shuffle数据 + +QueueDataset中不支持全局shuffle,可能抛出NotImplementedError + +**代码示例**: + +.. code-block:: python + import paddle.fluid as fluid + from paddle.fluid.incubate.fleet.parameter_server.pslib import fleet + dataset = fluid.DatasetFactory().create_dataset("QueueDataset") + dataset.global_shuffle(fleet) diff --git a/doc/fluid/api_cn/executor_cn.rst b/doc/fluid/api_cn/executor_cn.rst index 60e61812f..8216ab047 100644 --- a/doc/fluid/api_cn/executor_cn.rst +++ b/doc/fluid/api_cn/executor_cn.rst @@ -1,196 +1,288 @@ -################# - fluid.executor -################# - - - -.. _cn_api_fluid_executor_Executor: - -Executor -------------------------------- - - -.. py:class:: paddle.fluid.executor.Executor (place) - - - - - - -执行引擎(Executor)使用python脚本驱动,仅支持在单GPU环境下运行。多卡环境下请参考 ``ParallelExecutor`` 。 -Python Executor可以接收传入的program,并根据feed map(输入映射表)和fetch_list(结果获取表) -向program中添加feed operators(数据输入算子)和fetch operators(结果获取算子)。 -feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量(或识别类场景中的命名)。 - -应注意,执行器会执行program中的所有算子而不仅仅是依赖于fetch_list的那部分。 - -Executor将全局变量存储到全局作用域中,并为临时变量创建局部作用域。 -当每一mini-batch上的前向/反向运算完成后,局部作用域的内容将被废弃, -但全局作用域中的变量将在Executor的不同执行过程中一直存在。 - -program中所有的算子会按顺序执行。 - -**示例代码** - -.. code-block:: python - - # 新建一个执行引擎Executor名为exe。 - place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() - exe = fluid.Executor(place) - - # 仅运行一次startup program. - # 不需要优化/编译这个startup program. - exe.run(fluid.default_startup_program()) - - # 无需编译,直接运行main program - loss, = exe.run(fluid.default_main_program(), - feed=feed_dict, - fetch_list=[loss.name]) - - # 另一种方法是,编译这个main program然后运行. 参考CompiledProgram - compiled_prog = compiler.CompiledProgram( - fluid.default_main_program()).with_data_parallel( - loss_name=loss.name) - loss, = exe.run(compiled_prog, - feed=feed_dict, - fetch_list=[loss.name]) - - -参数: - - **place** (core.CPUPlace|core.CUDAPlace(n)) – 指明了 ``Executor`` 的执行场所 - - - -提示:你可以用 ``Executor`` 来调试基于并行GPU实现的复杂网络,他们有完全一样的参数也会产生相同的结果。 - - -.. py:method:: close() - - -关闭这个执行器(Executor)。调用这个方法后不可以再使用这个执行器。 对于分布式训练, 该函数会释放在PServers上涉及到目前训练器的资源。 - -**示例代码** - -.. code-block:: python - - cpu = core.CPUPlace() - exe = Executor(cpu) - ... - exe.close() - - -.. py:method:: run(program=None, feed=None, fetch_list=None, feed_var_name='feed', fetch_var_name='fetch', scope=None, return_numpy=True,use_program_cache=False) - - -调用该执行器对象的此方法可以执行program。通过feed map提供待学习数据,以及借助fetch_list得到相应的结果。 -Python执行器(Executor)可以接收传入的program,并根据输入映射表(feed map)和结果获取表(fetch_list) -向program中添加数据输入算子(feed operators)和结果获取算子(fetch operators)。 -feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量(或识别类场景中的命名)。 - -应注意,执行器会执行program中的所有算子而不仅仅是依赖于fetch_list的那部分。 - -参数: - - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) - - **feed** (dict) – 前向输入的变量,数据,词典dict类型, 例如 {“image”: ImageData, “label”: LabelData} - - **fetch_list** (list) – 用户想得到的变量或者命名的列表, run会根据这个列表给与结果 - - **feed_var_name** (str) – 前向算子(feed operator)变量的名称 - - **fetch_var_name** (str) – 结果获取算子(fetch operator)的输出变量名称 - - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。缺省为全局域 - - **return_numpy** (bool) – 如果为True,则将结果张量(fetched tensor)转化为numpy - - **use_program_cache** (bool) – 当program较上次比没有改动则将其置为True - -返回: 根据fetch_list来获取结果 - -返回类型: list(numpy.array) - - -**示例代码** - -.. code-block:: python - - data = fluid.layers.data(name='X', shape=[1], dtype='float32') - out = fluid.layers.create_tensor(dtype='float32') - hidden = fluid.layers.fc(input=data, size=10) - fluid.layers.assign(hidden,out) - loss = fluid.layers.mean(out) - adam = fluid.optimizer.Adam() - # adam.minimize(loss) - - -.. code-block:: python - - cpu = core.CPUPlace() - exe = fluid.Executor(cpu) - exe.run(fluid.default_startup_program()) - -.. code-block:: python - - x = numpy.random.random(size=(10, 1)).astype('float32') - outs = exe.run( - feed={'X': x}, - fetch_list=[loss.name]) - - - - - - - - - - -.. _cn_api_fluid_executor_global_scope: - -global_scope -------------------------------- - -.. py:function:: paddle.fluid.executor.global_scope () - - -获取全局/默认作用域实例。很多api使用默认 ``global_scope`` ,例如 ``Executor.run`` 。 - -返回:全局/默认作用域实例 - -返回类型:Scope - - - - - - -.. _cn_api_fluid_executor_scope_guard: - -scope_guard -------------------------------- - -.. py:function:: paddle.fluid.executor.scope_guard (scope) - - -修改全局/默认作用域(scope), 运行时中的所有变量都将分配给新的scope。 - -参数: - - **scope** - 新的全局/默认 scope。 - -**代码示例** - -.. code-block:: python - - import paddle.fluid as fluid - - new_scope = fluid.Scope() - with fluid.scope_guard(new_scope): - ... - - - - - - - - - - - - - - +################# + fluid.executor +################# + + + +.. _cn_api_fluid_executor_Executor: + +Executor +------------------------------- + + +.. py:class:: paddle.fluid.executor.Executor (place) + + + + +执行引擎(Executor)使用python脚本驱动,支持在单/多GPU、单/多CPU环境下运行。 +Python Executor可以接收传入的program,并根据feed map(输入映射表)和fetch_list(结果获取表) +向program中添加feed operators(数据输入算子)和fetch operators(结果获取算子)。 +feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量(或识别类场景中的命名)。 + +应注意,执行器会执行program中的所有算子而不仅仅是依赖于fetch_list的那部分。 + +Executor将全局变量存储到全局作用域中,并为临时变量创建局部作用域。 +当每一mini-batch上的前向/反向运算完成后,局部作用域的内容将被废弃, +但全局作用域中的变量将在Executor的不同执行过程中一直存在。 + + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import paddle.fluid.compiler as compiler + import numpy + import os + + use_cuda = True + place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() + exe = fluid.Executor(place) + + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + # 仅运行一次startup program + # 不需要优化/编译这个startup program + startup_program.random_seed=1 + exe.run(startup_program) + + # 无需编译,直接运行main program + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = exe.run(train_program, + feed={"X": x}, + fetch_list=[loss.name]) + + # 另一种方法是,编译这个main program然后运行。 + # 参考CompiledProgram以获取更多信息。 + # 注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + # 否则fluid会把逻辑核的所有数目设为CPU_NUM, + # 在这种情况下,输入的batch size应大于CPU_NUM, + # 否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) + + compiled_prog = compiler.CompiledProgram( + train_program).with_data_parallel( + loss_name=loss.name) + loss_data, = exe.run(compiled_prog, + feed={"X": x}, + fetch_list=[loss.name]) + + +参数: + - **place** (fluid.CPUPlace|fluid.CUDAPlace(n)) – 指明了 ``Executor`` 的执行场所 + + + +.. py:method:: close() + + +关闭这个执行器(Executor)。 + +调用这个方法后不可以再使用这个执行器。 对于分布式训练, 该函数会释放在PServers上和目前Trainer有关联的资源。 + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + + cpu = fluid.CPUPlace() + exe = fluid.Executor(cpu) + # 执行训练或测试过程 + exe.close() + + +.. py:method:: run(program=None, feed=None, fetch_list=None, feed_var_name='feed', fetch_var_name='fetch', scope=None, return_numpy=True,use_program_cache=False) + + +调用该执行器对象的此方法可以执行program。通过feed map提供待学习数据,以及借助fetch_list得到相应的结果。 +Python执行器(Executor)可以接收传入的program,并根据输入映射表(feed map)和结果获取表(fetch_list) +向program中添加数据输入算子(feed operators)和结果获取算子(fetch operators)。 +feed map为该program提供输入数据。fetch_list提供program训练结束后用户预期的变量(或识别类场景中的命名)。 + +应注意,执行器会执行program中的所有算子而不仅仅是依赖于fetch_list的那部分。 + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import numpy + + #首先创建执行引擎 + place = fluid.CPUPlace() # fluid.CUDAPlace(0) + exe = fluid.Executor(place) + + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + adam = fluid.optimizer.Adam() + adam.minimize(loss) + + #仅运行startup程序一次 + exe.run(fluid.default_startup_program()) + + x = numpy.random.random(size=(10, 1)).astype('float32') + outs = exe.run(feed={'X': x}, + fetch_list=[loss.name]) + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **feed** (dict) – 前向输入的变量,数据,词典dict类型, 例如 {“image”: ImageData, “label”: LabelData} + - **fetch_list** (list) – 用户想得到的变量或者命名的列表, 该方法会根据这个列表给出结果 + - **feed_var_name** (str) – 前向算子(feed operator)变量的名称 + - **fetch_var_name** (str) – 结果获取算子(fetch operator)的输出变量名称 + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。缺省为全局域 + - **return_numpy** (bool) – 如果为True,则将结果张量(fetched tensor)转化为numpy + - **use_program_cache** (bool) – 是否跨批使用缓存程序设置。设置为True时,只有当(1)程序没有用数据并行编译,并且(2)program、 feed变量名和fetch_list变量名与上一步相比没有更改时,运行速度才会更快。 + +返回: 根据fetch_list来获取结果 + +返回类型: list(numpy.array) + + +.. py:method:: infer_from_dataset(program=None, dataset=None, scope=None, thread=0, debug=False, fetch_list=None, fetch_info=None, print_period=100) + +infer_from_dataset的文档与train_from_dataset几乎完全相同,只是在分布式训练中,推进梯度将在infer_from_dataset中禁用。 infer_from_dataset()可以非常容易地用于多线程中的评估。 + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **dataset** (paddle.fluid.Dataset) – 在此函数外创建的数据集,用户应当在调用函数前提供完整定义的数据集。必要时请检查Dataset文件。默认为None + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。默认为全局域 + - **thread** (int) – 用户想要在这个函数中运行的线程数量。线程的实际数量为min(Dataset.thread_num, thread),如果thread > 0,默认为0 + - **debug** (bool) – 是否开启debug模式,默认为False + - **fetch_list** (Variable List) – 返回变量列表,每个变量都会在训练过程中被打印出来,默认为None + - **fetch_info** (String List) – 每个变量的打印信息,默认为None + - **print_period** (int) – 每两次打印之间间隔的mini-batches的数量,默认为100 + +返回: None + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + place = fluid.CPUPlace() # 使用GPU时可设置place = fluid.CUDAPlace(0) + exe = fluid.Executor(place) + x = fluid.layers.data(name="x", shape=[10, 10], dtype="int64") + y = fluid.layers.data(name="y", shape=[1], dtype="int64", lod_level=1) + dataset = fluid.DatasetFactory().create_dataset() + dataset.set_use_var([x, y]) + dataset.set_thread(1) + filelist = [] # 您可以设置您自己的filelist,如filelist = ["dataA.txt"] + dataset.set_filelist(filelist) + exe.run(fluid.default_startup_program()) + exe.infer_from_dataset(program=fluid.default_main_program(),dataset=dataset) + + +.. py:method:: train_from_dataset(program=None, dataset=None, scope=None, thread=0, debug=False, fetch_list=None, fetch_info=None, print_period=100) + +从预定义的数据集中训练。 数据集在paddle.fluid.dataset中定义。 给定程序(或编译程序),train_from_dataset将使用数据集中的所有数据样本。 输入范围可由用户给出。 默认情况下,范围是global_scope()。训练中的线程总数是thread。 训练中使用的线程数将是数据集中threadnum的最小值,同时也是此接口中线程的值。 可以设置debug,以便执行器显示所有算子的运行时间和当前训练任务的吞吐量。 + +注意:train_from_dataset将销毁每次运行在executor中创建的所有资源。 + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **dataset** (paddle.fluid.Dataset) – 在此函数外创建的数据集,用户应当在调用函数前提供完整定义的数据集。必要时请检查Dataset文件。默认为None + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。默认为全局域 + - **thread** (int) – 用户想要在这个函数中运行的线程数量。线程的实际数量为min(Dataset.thread_num, thread),如果thread > 0,默认为0 + - **debug** (bool) – 是否开启debug模式,默认为False + - **fetch_list** (Variable List) – 返回变量列表,每个变量都会在训练过程中被打印出来,默认为None + - **fetch_info** (String List) – 每个变量的打印信息,默认为None + - **print_period** (int) – 每两次打印之间间隔的mini-batches的数量,默认为100 + +返回: None + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + + place = fluid.CPUPlace() # 通过设置place = fluid.CUDAPlace(0)使用GPU + exe = fluid.Executor(place) + x = fluid.layers.data(name="x", shape=[10, 10], dtype="int64") + y = fluid.layers.data(name="y", shape=[1], dtype="int64", lod_level=1) + dataset = fluid.DatasetFactory().create_dataset() + dataset.set_use_var([x, y]) + dataset.set_thread(1) + filelist = [] # 您可以设置您自己的filelist,如filelist = ["dataA.txt"] + dataset.set_filelist(filelist) + exe.run(fluid.default_startup_program()) + exe.infer_from_dataset(program=fluid.default_main_program(), + dataset=dataset) + + +.. _cn_api_fluid_executor_global_scope: + +global_scope +------------------------------- + +.. py:function:: paddle.fluid.global_scope() + + +获取全局/默认作用域实例。很多api使用默认 ``global_scope`` ,例如 ``Executor.run`` 。 + +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import numpy + + fluid.global_scope().var("data").get_tensor().set(numpy.ones((2, 2)), fluid.CPUPlace()) + numpy.array(fluid.global_scope().find_var("data").get_tensor()) + +返回:全局/默认作用域实例 + +返回类型:Scope + + + + + + +.. _cn_api_fluid_executor_scope_guard: + +scope_guard +------------------------------- + +.. py:function:: paddle.fluid.executor.scope_guard (scope) + + +修改全局/默认作用域(scope), 运行时中的所有变量都将分配给新的scope。 + +参数: + - **scope** - 新的全局/默认 scope。 + +**代码示例** + +.. code-block:: python + + import numpy + + new_scope = fluid.Scope() + with fluid.scope_guard(new_scope): + fluid.global_scope().var("data").get_tensor().set(numpy.ones((2, 2)), fluid.CPUPlace()) + numpy.array(new_scope.find_var("data").get_tensor()) + + + + + + + + + + + + + diff --git a/doc/fluid/api_cn/fluid_cn.rst b/doc/fluid/api_cn/fluid_cn.rst index e0ac4df79..9fa5927bf 100644 --- a/doc/fluid/api_cn/fluid_cn.rst +++ b/doc/fluid/api_cn/fluid_cn.rst @@ -13,59 +13,125 @@ BuildStrategy **代码示例** -.. code-block:: python - +.. code-block:: python + + import paddle.fluid as fluid build_strategy = fluid.BuildStrategy() build_strategy.reduce_strategy = fluid.BuildStrategy.ReduceStrategy.Reduce - train_exe = fluid.ParallelExecutor(use_cuda=True, - loss_name=loss.name, - build_strategy=build_strategy) - train_loss, = train_exe.run([loss.name], feed=feed_dict) +.. py:attribute:: debug_graphviz_path +str类型。它表明了以graphviz格式向文件中写入SSA图的路径,有利于调试。 默认值为""。 +**代码示例** -.. py:attribute:: debug_graphviz_path +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.debug_graphviz_path = "" -str类型。它表明了以graphviz格式向文件中写入SSA图的路径,有利于调试。 默认值为""。 .. py:attribute:: enable_sequential_execution 类型是BOOL。 如果设置为True,则ops的执行顺序将与program中的执行顺序相同。 默认为False。 +**代码示例** +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.enable_sequential_execution = True + + +.. py:attribute:: fuse_broadcast_ops + +bool类型。它表明了是否融合(fuse)broadcast ops。值得注意的是,在Reduce模式中,融合broadcast ops可以使程序运行更快,因为这个过程等同于延迟执行所有的broadcast ops。在这种情况下,所有的nccl streams仅用于一段时间内的NCCLReduce操作。默认为False。 + .. py:attribute:: fuse_elewise_add_act_ops bool类型。它表明了是否融合(fuse)elementwise_add_op和activation_op。这会使整体执行过程更快一些。默认为False。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.fuse_elewise_add_act_ops = True + + .. py:attribute:: fuse_relu_depthwise_conv BOOL类型,fuse_relu_depthwise_conv指示是否融合relu和depthwise_conv2d,它会节省GPU内存并可能加速执行过程。 此选项仅适用于GPU设备。 默认为False。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.fuse_relu_depthwise_conv = True .. py:attribute:: gradient_scale_strategy str类型。在 ``ParallelExecutor`` 中,存在三种定义 *loss@grad* 的方式,分别为 ``CoeffNumDevice``, ``One`` 与 ``Customized``。默认情况下, ``ParallelExecutor`` 根据设备数目来设置 *loss@grad* 。如果你想自定义 *loss@grad* ,你可以选择 ``Customized`` 方法。默认为 ``CoeffNumDevice`` 。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.gradient_scale_strategy = True + +.. py:attribute:: memory_optimize +bool类型。设为True时可用于减少总内存消耗。为实验性属性,一些变量可能会被优化策略重用/移除。如果你需要在使用该特征时获取某些变量,请把变量的persistable property设为True。默认为False。 .. py:attribute:: reduce_strategy str类型。在 ``ParallelExecutor`` 中,存在两种减少策略(reduce strategy),即 ``AllReduce`` 和 ``Reduce`` 。如果你需要在所有执行场所上独立地进行参数优化,可以使用 ``AllReduce`` 。反之,如果使用 ``Reduce`` 策略,所有参数的优化将均匀地分配给不同的执行场所,随之将优化后的参数广播给其他执行场所。在一些模型中, ``Reduce`` 策略执行速度更快一些。默认值为 ``AllReduce`` 。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.reduce_strategy = fluid.BuildStrategy.ReduceStrategy.Reduce + .. py:attribute:: remove_unnecessary_lock BOOL类型。如果设置为True, GPU操作中的一些锁将被释放,ParallelExecutor将运行得更快,默认为 True。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.remove_unnecessary_lock = True + + .. py:attribute:: sync_batch_norm 类型为bool,sync_batch_norm表示是否使用同步的批正则化,即在训练阶段通过多个设备同步均值和方差。 -当前的实现不支持FP16训练和CPU。仅在一台机器上进行同步式批正则,不适用于多台机器。 +当前的实现不支持FP16培训和CPU。仅在一台机器上进行同步式批正则,不适用于多台机器。 默认为 False。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + build_strategy = fluid.BuildStrategy() + build_strategy.sync_batch_norm = True + .. _cn_api_fluid_CompiledProgram: @@ -84,22 +150,34 @@ CompiledProgram用于转换程序以进行各种优化。例如, - 预先计算一些逻辑,以便每次运行更快。 - 转换Program,使其可以在多个设备中运行。 -- 转换Program以进行优化预测或分布式训练。 +- 转换Program以进行优化预测或分布式训练。注意:此部分尚未完成。 **代码示例** -.. code-block:: python - - place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() - exe = fluid.Executor(place) - exe.run(startup) - compiled_prog = compiler.CompiledProgram(main).with_data_parallel( - loss_name=loss.name) - for i in range(5): - test_loss, = exe.run(compiled_prog, - feed=feed_dict, - fetch_list=[loss.name]) - +.. code-block:: python + + import paddle.fluid as fluid + import paddle.fluid.compiler as compiler + import numpy + import os + + place = fluid.CUDAPlace(0) # fluid.CPUPlace() + exe = fluid.Executor(place) + + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + fluid.default_startup_program().random_seed=1 + exe.run(fluid.default_startup_program()) + compiled_prog = compiler.CompiledProgram( + fluid.default_main_program()) + + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = exe.run(compiled_prog, + feed={"X": x}, + fetch_list=[loss.name]) 参数: - **program_or_graph** (Graph|Program): 如果它是Program,那么它将首先被降成一个graph,以便进一步优化。如果它是一个graph(以前可能优化过),它将直接用于进一步的优化。注意:只有使用 with_data_parallel 选项编译时才支持graph。 @@ -107,6 +185,42 @@ CompiledProgram用于转换程序以进行各种优化。例如, 配置Program使其以数据并行方式运行。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + import paddle.fluid.compiler as compiler + import numpy + import os + + use_cuda = True + place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() + #注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + #否则fluid会把逻辑核的所有数目设为CPU_NUM, + #在这种情况下,输入的batch size应大于CPU_NUM, + #否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) + + exe = fluid.Executor(place) + + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + fluid.default_startup_program().random_seed=1 + exe.run(fluid.default_startup_program()) + compiled_prog = compiler.CompiledProgram( + fluid.default_main_program()).with_data_parallel( + loss_name=loss.name) + + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = exe.run(compiled_prog, + feed={"X": x}, + fetch_list=[loss.name]) + 参数: - **loss_name** (str) - 损失函数名称必须在训练过程中设置。 默认None。 - **build_strategy** (BuildStrategy) - build_strategy用于构建图,因此它可以在具有优化拓扑的多个设备/核上运行。 有关更多信息,请参阅 ``fluid.BuildStrategy`` 。 默认None。 @@ -144,6 +258,11 @@ cpu_places 返回类型:out (list(fluid.CPUPlace)) +**代码示例** + +.. code-block:: python + + cpu_places = fluid.cpu_places() .. _cn_api_fluid_CPUPlace: @@ -156,9 +275,11 @@ CPUPlace CPUPlace是设备的描述符。它代表一个CPU,可以访问CPUPlace对应的内存。 +**代码示例** +.. code-block:: python - + cpu_place = fluid.CPUPlace() .. _cn_api_fluid_create_lod_tensor: @@ -183,13 +304,21 @@ create_lod_tensor 4. 利用offset-based LoD来设置LoD 例如: - 假如我们想用LoD Tensor来承载一词序列的数据,其中每个词由一个整数来表示。现在,我们意图创建一个LoD Tensor来代表两个句子,其中一个句子有两个词,另外一个句子有三个。 - 那么数 ``data`` 可以是一个numpy数组,形状为(5,1)。同时, ``recursive_seq_lens`` 为 [[2, 3]],表明各个句子的长度。这个长度为基准的 ``recursive_seq_lens`` 将在函数中会被转化为以偏移量为基准的 LoD [[0, 2, 5]]。 +假如我们想用LoD Tensor来承载一词序列的数据,其中每个词由一个整数来表示。现在,我们意图创建一个LoD Tensor来代表两个句子,其中一个句子有两个词,另外一个句子有三个。那么数 ``data`` 可以是一个numpy数组,形状为(5,1)。同时, ``recursive_seq_lens`` 为 [[2, 3]],表明各个句子的长度。这个长度为基准的 ``recursive_seq_lens`` 将在函数中会被转化为以偏移量为基准的 LoD [[0, 2, 5]]。 + +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.create_lod_tensor(np.ndarray([5, 30]), [[2, 3]], fluid.CPUPlace()) + +参考 :ref:`api_guide_tensor` 以获取更多关于LoD的信息。 参数: - - **data** (numpy.ndarray|list|LoDTensor) – 容纳着待复制数据的一个numpy数组、列表或LoD Tensor - - **recursive_seq_lens** (list) – 一组列表的列表, 表明了由用户指明的length-based level of detail信息 - - **place** (Place) – CPU或GPU。 指明返回的新LoD Tensor存储地点 + - **data** (numpy.ndarray|list|LoDTensor) – 容纳着待复制数据的一个numpy数组、列表或LoD Tensor + - **recursive_seq_lens** (list) – 一组列表的列表, 表明了由用户指明的length-based level of detail信息 + - **place** (Place) – CPU或GPU。 指明返回的新LoD Tensor存储地点 返回: 一个fluid LoDTensor对象,包含数据和 ``recursive_seq_lens`` 信息 @@ -233,9 +362,15 @@ create_random_int_lodtensor - **low** (int) – 随机数下限 - **high** (int) – 随机数上限 -返回: 一个fluid LoDTensor对象,包含数据和 ``recursive_seq_lens`` 信息 +返回: 一个fluid LoDTensor对象,包含张量数据和 ``recursive_seq_lens`` 信息 +**代码示例** +.. code-block:: python + + import paddle.fluid as fluid + + t = fluid.create_random_int_lodtensor(recursive_seq_lens=[[2, 3]],base_shape=[30], place=fluid.CPUPlace(), low=0, high=10) .. _cn_api_fluid_cuda_pinned_places: @@ -258,7 +393,13 @@ cuda_pinned_places 返回类型:out(list(fluid.CUDAPinnedPlace)) +**代码示例** + +.. code-block:: python + cuda_pinned_places_cpu_num = fluid.cuda_pinned_places() + # 或者 + cuda_pinned_places = fluid.cuda_pinned_places(1) .. _cn_api_fluid_cuda_places: @@ -283,9 +424,11 @@ cuda_places 返回类型:out (list(fluid.CUDAPlace)) +**代码示例** +.. code-block:: python - + cuda_places = fluid.cuda_places() .. _cn_api_fluid_CUDAPinnedPlace: @@ -296,8 +439,11 @@ CUDAPinnedPlace CUDAPinnedPlace是一个设备描述符,它所指代的存储空间可以被GPU和CPU访问。 +**代码示例** +.. code-block:: python + place = fluid.CUDAPinnedPlace() .. _cn_api_fluid_CUDAPlace: @@ -308,9 +454,11 @@ CUDAPlace CUDAPlace是一个设备描述符,它代表一个GPU,并且每个CUDAPlace有一个dev_id(设备id)来表明当前CUDAPlace代表的卡数。dev_id不同的CUDAPlace所对应的内存不可相互访问。 +**代码示例** +.. code-block:: python - + gpu_place = fluid.CUDAPlace(0) @@ -326,34 +474,33 @@ DataFeedDesc 这个类目前只用于AsyncExecutor(有关类AsyncExecutor的简要介绍,请参阅注释) -DataFeedDesc应由来自磁盘的有效protobuf消息初始化: - -.. code-block:: python - - data_feed = fluid.DataFeedDesc('data.proto') +DataFeedDesc应由来自磁盘的有效protobuf消息初始化。 可以参考 :code:`paddle/fluid/framework/data_feed.proto` 查看我们如何定义message 一段典型的message可能是这样的: -.. code-block:: text - - name: "MultiSlotDataFeed" - batch_size: 2 - multi_slot_desc { - slots { - name: "words" - type: "uint64" - is_dense: false - is_used: true - } - slots { - name: "label" - type: "uint64" - is_dense: false - is_used: true - } - } +.. code-block:: python + + f = open("data.proto", "w") + print >> f, 'name: "MultiSlotDataFeed"' + print >> f, 'batch_size: 2' + print >> f, 'multi_slot_desc {' + print >> f, ' slots {' + print >> f, ' name: "words"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, ' slots {' + print >> f, ' name: "label"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, '}' + f.close() + data_feed = fluid.DataFeedDesc('data.proto') 但是,用户通常不应该关心消息格式;相反,我们鼓励他们在将原始日志文件转换为AsyncExecutor可以接受的训练文件的过程中,使用 :code:`Data Generator` 生成有效数据描述。 @@ -361,17 +508,18 @@ DataFeedDesc也可以在运行时更改。一旦你熟悉了每个字段的含 .. code-block:: python + data_feed = fluid.DataFeedDesc('data.proto') data_feed.set_batch_size(128) - data_feed.set_dense_slots('wd') # The slot named 'wd' will be dense - data_feed.set_use_slots('wd') # The slot named 'wd' will be used + data_feed.set_dense_slots('wd') # 名为'wd'的slot将被设置为密集的 + data_feed.set_use_slots('wd') # 名为'wd'的slot将被用于训练 - #Finally, the content can be dumped out for debugging purpose: + # 最后,可以打印变量详细信息便于排出错误 print(data_feed.desc()) 参数: - - **proto_file** (string) - 包含数据feed中描述的磁盘文件 + - **proto_file** (string) - 包含数据feed中描述的磁盘文件 .. py:method:: set_batch_size(batch_size) @@ -380,14 +528,32 @@ DataFeedDesc也可以在运行时更改。一旦你熟悉了每个字段的含 参数: - - batch_size:batch size + - batch_size:batch size **代码示例:** .. code-block:: python - data_feed = fluid.DataFeedDesc('data.proto') - data_feed.set_batch_size(128) + f = open("data.proto", "w") + print >> f, 'name: "MultiSlotDataFeed"' + print >> f, 'batch_size: 2' + print >> f, 'multi_slot_desc {' + print >> f, ' slots {' + print >> f, ' name: "words"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, ' slots {' + print >> f, ' name: "label"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, '}' + f.close() + data_feed = fluid.DataFeedDesc('data.proto') + data_feed.set_batch_size(128) .. py:method:: set_dense_slots(dense_slots_name) @@ -397,18 +563,36 @@ DataFeedDesc也可以在运行时更改。一旦你熟悉了每个字段的含 参数: - - **dense_slots_name** : slot名称的列表,这些slot将被设置为密集的 + - **dense_slots_name** : slot名称的列表,这些slot将被设置为密集的 **代码示例:** .. code-block:: python - data_feed = fluid.DataFeedDesc('data.proto') - data_feed.set_dense_slots(['words']) + f = open("data.proto", "w") + print >> f, 'name: "MultiSlotDataFeed"' + print >> f, 'batch_size: 2' + print >> f, 'multi_slot_desc {' + print >> f, ' slots {' + print >> f, ' name: "words"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, ' slots {' + print >> f, ' name: "label"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, '}' + f.close() + data_feed = fluid.DataFeedDesc('data.proto') + data_feed.set_dense_slots(['words']) .. note:: - 默认情况下,所有slot都是稀疏的 + 默认情况下,所有slot都是稀疏的 .. py:method:: set_use_slots(use_slots_name) @@ -416,18 +600,36 @@ DataFeedDesc也可以在运行时更改。一旦你熟悉了每个字段的含 设置一个特定的slot是否用于训练。一个数据集包含了很多特征,通过这个函数可以选择哪些特征将用于指定的模型。 参数: - - **use_slots_name** :将在训练中使用的slot名列表 + - **use_slots_name** :将在训练中使用的slot名列表 **代码示例:** .. code-block:: python - - data_feed = fluid.DataFeedDesc('data.proto') - data_feed.set_use_slots(['words']) + + f = open("data.proto", "w") + print >> f, 'name: "MultiSlotDataFeed"' + print >> f, 'batch_size: 2' + print >> f, 'multi_slot_desc {' + print >> f, ' slots {' + print >> f, ' name: "words"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, ' slots {' + print >> f, ' name: "label"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, '}' + f.close() + data_feed = fluid.DataFeedDesc('data.proto') + data_feed.set_use_slots(['words']) .. note:: - 默认值不用于所有slot + 默认值不用于所有slot .. py:method:: desc() @@ -439,9 +641,27 @@ DataFeedDesc也可以在运行时更改。一旦你熟悉了每个字段的含 **代码示例:** .. code-block:: python - - data_feed = fluid.DataFeedDesc('data.proto') - print(data_feed.desc()) + + f = open("data.proto", "w") + print >> f, 'name: "MultiSlotDataFeed"' + print >> f, 'batch_size: 2' + print >> f, 'multi_slot_desc {' + print >> f, ' slots {' + print >> f, ' name: "words"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, ' slots {' + print >> f, ' name: "label"' + print >> f, ' type: "uint64"' + print >> f, ' is_dense: false' + print >> f, ' is_used: true' + print >> f, ' }' + print >> f, '}' + f.close() + data_feed = fluid.DataFeedDesc('data.proto') + print(data_feed.desc()) @@ -463,22 +683,29 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 以下是简单用法: -.. code-block:: python +.. code-block:: python - place = fluid.CPUPlace() - img = fluid.layers.data(name='image', shape=[1, 28, 28]) - label = fluid.layers.data(name='label', shape=[1], dtype='int64') - feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) - result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) + import paddle.fluid as fluid + place = fluid.CPUPlace() + img = fluid.layers.data(name='image', shape=[1, 28, 28]) + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + feeder = fluid.DataFeeder([img, label], fluid.CPUPlace()) + result = feeder.feed([([0] * 784, [9]), ([1] * 784, [1])]) 在多GPU模型训练时,如果需要提前分别向各GPU输入数据,可以使用 ``decorate_reader`` 函数。 -.. code-block:: python +.. code-block:: python + + import paddle + import paddle.fluid as fluid - place=fluid.CUDAPlace(0) - feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) - reader = feeder.decorate_reader( - paddle.batch(flowers.train(), batch_size=16)) + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[3, 224, 224], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader( + paddle.batch(paddle.dataset.flowers.train(), batch_size=16), multi_devices=False) @@ -494,17 +721,34 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 **代码示例** -.. code-block:: python +.. code-block:: python - # ... - place = fluid.CPUPlace() - feed_list = [ - main_program.global_block().var(var_name) for var_name in feed_vars_name - ] # feed_vars_name 是一个由变量名组成的列表 - feeder = fluid.DataFeeder(feed_list, place) - for data in reader(): - outs = exe.run(program=main_program, - feed=feeder.feed(data)) + import numpy as np + import paddle + import paddle.fluid as fluid + + place = fluid.CPUPlace() + + def reader(): + yield [np.random.random([4]).astype('float32'), np.random.random([3]).astype('float32')], + + main_program = fluid.Program() + startup_program = fluid.Program() + + with fluid.program_guard(main_program, startup_program): + data_1 = fluid.layers.data(name='data_1', shape=[1, 2, 2]) + data_2 = fluid.layers.data(name='data_2', shape=[1, 1, 3]) + out = fluid.layers.fc(input=[data_1, data_2], size=2) + # ... + + feeder = fluid.DataFeeder([data_1, data_2], place) + + exe = fluid.Executor(place) + exe.run(startup_program) + for data in reader(): + outs = exe.run(program=main_program, + feed=feeder.feed(data), + fetch_list=[out])) .. py:method:: feed(iterable) @@ -513,11 +757,29 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 根据feed_list(数据输入表)和iterable(可遍历的数据)提供的信息,将输入数据转成一种特殊的数据结构,使它们可以输入到 ``Executor`` 和 ``ParallelExecutor`` 中。 参数: - - **iterable** (list|tuple) – 要输入的数据 + - **iterable** (list|tuple) – 要输入的数据 返回: 转换结果 -返回类型: dict +返回类型: dict + +**代码示例** + +.. code-block:: python + + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield random.random([784]).astype('float32'), random.random([1]).astype('int64'), random.random([256]).astype('float32') + + data_1 = fluid.layers.data(name='data_1', shape=[1, 28, 28]) + data_2 = fluid.layers.data(name='data_2', shape=[1], dtype='int64') + data_3 = fluid.layers.data(name='data_3', shape=[16, 16], dtype='float32') + feeder = fluid.DataFeeder(['data_1','data_2', 'data_3'], fluid.CPUPlace()) + + result = feeder.feed(reader()) .. py:method:: feed_parallel(iterable, num_places=None) @@ -536,7 +798,32 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 .. note:: 设备(CPU或GPU)的数目必须等于minibatch的数目 +**代码示例** + +.. code-block:: python + import numpy.random as random + import paddle.fluid as fluid + + def reader(limit=10): + for i in range(limit): + yield [random.random([784]).astype('float32'), random.randint(10)], + + x = fluid.layers.data(name='x', shape=[1, 28, 28]) + y = fluid.layers.data(name='y', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(['x','y'], fluid.CPUPlace()) + place_num = 2 + places = [fluid.CPUPlace() for x in range(place_num)] + data = [] + exe = fluid.Executor(fluid.CPUPlace()) + exe.run(fluid.default_startup_program()) + program = fluid.CompiledProgram(fluid.default_main_program()).with_data_parallel(places=places) + for item in reader(): + data.append(item) + if place_num == len(data): + exe.run(program=program, feed=list(feeder.feed_parallel(data, place_num)), fetch_list=[]) + data = [] .. py:method:: decorate_reader(reader, multi_devices, num_places=None, drop_last=True) @@ -556,11 +843,29 @@ reader通常返回一个minibatch条目列表。在列表中每一条目都是 抛出异常: ``ValueError`` – 如果 ``drop_last`` 值为False并且data batch与设备不匹配时,产生此异常 +**代码示例** +.. code-block:: python - - - + import numpy.random as random + import paddle + import paddle.fluid as fluid + + def reader(limit=5): + for i in range(limit): + yield (random.random([784]).astype('float32'), random.random([1]).astype('int64')), + + place=fluid.CUDAPlace(0) + data = fluid.layers.data(name='data', shape=[1, 28, 28], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + feeder = fluid.DataFeeder(place=place, feed_list=[data, label]) + reader = feeder.decorate_reader(reader, multi_devices=False) + + exe = fluid.Executor(place) + exe.run(fluid.default_startup_program()) + for data in reader(): + exe.run(feed=data) @@ -586,13 +891,39 @@ default_main_program ``Executor.run()`` 会默认执行 ``default_main_program`` 。 -返回: main program - -返回类型: Program +返回: main program +返回类型: Program +**代码示例** +.. code-block:: python + import paddle.fluid as fluid + + # Sample Network: + data = fluid.layers.data(name='image', shape=[3, 224, 224], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + + conv1 = fluid.layers.conv2d(data, 4, 5, 1, act=None) + bn1 = fluid.layers.batch_norm(conv1, act='relu') + pool1 = fluid.layers.pool2d(bn1, 2, 'max', 2) + conv2 = fluid.layers.conv2d(pool1, 16, 5, 1, act=None) + bn2 = fluid.layers.batch_norm(conv2, act='relu') + pool2 = fluid.layers.pool2d(bn2, 2, 'max', 2) + + fc1 = fluid.layers.fc(pool2, size=50, act='relu') + fc2 = fluid.layers.fc(fc1, size=102, act='softmax') + + loss = fluid.layers.cross_entropy(input=fc2, label=label) + loss = fluid.layers.mean(loss) + opt = fluid.optimizer.Momentum( + learning_rate=0.1, + momentum=0.9, + regularization=fluid.regularizer.L2Decay(1e-4)) + opt.minimize(loss) + + print(fluid.default_main_program()) @@ -620,17 +951,25 @@ startup_program会使用内在的operators(算子)去初始化他们,并 该函数将返回默认的或当前的startup_program。用户可以使用 ``fluid.program_guard`` 去切换program。 -返回: startup program - -返回类型: Program - - - - +返回: startup program +返回类型: Program +**代码示例:** +.. code-block:: python + import paddle.fluid as fluid + + main_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(main_program=main_program, startup_program=startup_program): + x = fluid.layers.data(name="x", shape=[-1, 784], dtype='float32') + y = fluid.layers.data(name="y", shape=[-1, 1], dtype='int32') + z = fluid.layers.fc(name="fc", input=x, size=10, act="relu") + + print("main program is: {}".format(fluid.default_main_program())) + print("start up program is: {}".format(fluid.default_startup_program())) @@ -652,63 +991,99 @@ DistributeTranspiler **代码示例** -.. code-block:: python - - #pserver模式下 - pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" - trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174" - current_endpoint = "192.168.0.1:6174" - trainer_id = 0 - trainers = 4 - role = os.getenv("PADDLE_TRAINING_ROLE") - - t = fluid.DistributeTranspiler() - t.transpile( - trainer_id, pservers=pserver_endpoints, trainers=trainers) - if role == "PSERVER": - pserver_program = t.get_pserver_program(current_endpoint) - pserver_startup_program = t.get_startup_program(current_endpoint, - pserver_program) - elif role == "TRAINER": - trainer_program = t.get_trainer_program() - - # nccl2模式下 - config = fluid.DistributeTranspilerConfig() - config.mode = "nccl2" - t = fluid.DistributeTranspiler(config=config) - t.transpile(trainer_id, workers=workers, current_endpoint=curr_ep) - exe = fluid.ParallelExecutor( - use_cuda, - loss_name=loss_var.name, - num_trainers=len(trainers.split(",)), - trainer_id=trainer_id - ) +.. code-block:: python + + x = fluid.layers.data(name='x', shape=[13], dtype='float32') + y = fluid.layers.data(name='y', shape=[1], dtype='float32') + y_predict = fluid.layers.fc(input=x, size=1, act=None) + + cost = fluid.layers.square_error_cost(input=y_predict, label=y) + avg_loss = fluid.layers.mean(cost) + + sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001) + sgd_optimizer.minimize(avg_loss) + + #pserver模式下 + pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + current_endpoint = "192.168.0.1:6174" + trainer_id = 0 + trainers = 4 + role = "PSERVER" + + t = fluid.DistributeTranspiler() + t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers) + if role == "PSERVER": + pserver_program = t.get_pserver_program(current_endpoint) + pserver_startup_program = t.get_startup_program(current_endpoint, pserver_program) + elif role == "TRAINER": + trainer_program = t.get_trainer_program() + + # nccl2模式下 + trainer_num = 2 + trainer_id = 0 + config = fluid.DistributeTranspilerConfig() + config.mode = "nccl2" + trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + t = fluid.DistributeTranspiler(config=config) + t.transpile(trainer_id=trainer_id, trainers=trainer_endpoints, current_endpoint="192.168.0.1:6174") + exe = fluid.ParallelExecutor( + loss_name=avg_loss.name, + num_trainers=len(trainer_num, + trainer_id=trainer_id + ) .. py:method:: transpile(trainer_id, program=None, pservers='127.0.0.1:6174', trainers=1, sync_mode=True, startup_program=None, current_endpoint='127.0.0.1:6174') -该方法可以运行该transpiler(转译器)。 +该方法可以运行该transpiler(转译器)。转译输入程序。 参数: - - **trainer_id** (int) – 当前Trainer worker的id, 如果有n个Trainer worker, id 取值范围为0 ~ n-1 - - **program** (Program|None) – 待transpile(转译)的program, 缺省为 ``fluid.default_main_program()`` - - **startup_program** (Program|None) - 要转译的 ``startup_program`` ,默认为 ``fluid.default_startup_program()`` - - **pservers** (str) – 内容为Pserver列表的字符串,格式为:按逗号区分不同的Pserver,每个Pserver的格式为 *ip地址:端口号* - - **trainers** (int|str) – 在Pserver模式下,该参数指Trainer机的个数;在nccl2模式下,它是一个内容为Trainer终端列表的字符串 - - **sync_mode** (bool) – 是否做同步训练(synchronous training), 默认为True - - **startup_program** (Program|None) – 待transpile(转译)的startup_program,默认为 ``fluid.default_main_program()`` - - **current_endpoint** (str) – 当需要把program转译(transpile)至NCCL2模式下时,需要将当前endpoint(终端)传入该参数。Pserver模式不使用该参数 + - **trainer_id** (int) – 当前Trainer worker的id, 如果有n个Trainer worker, id 取值范围为0 ~ n-1 + - **program** (Program|None) – 待transpile(转译)的program, 缺省为 ``fluid.default_main_program()`` + - **startup_program** (Program|None) - 要转译的 ``startup_program`` ,默认为 ``fluid.default_startup_program()`` + - **pservers** (str) – 内容为Pserver列表的字符串,格式为:按逗号区分不同的Pserver,每个Pserver的格式为 *ip地址:端口号* + - **trainers** (int|str) – 在Pserver模式下,该参数指Trainer机的个数;在nccl2模式下,它是一个内容为Trainer终端列表的字符串 + - **sync_mode** (bool) – 是否做同步训练(synchronous training), 默认为True + - **startup_program** (Program|None) – 待transpile(转译)的startup_program,默认为 ``fluid.default_main_program()`` + - **current_endpoint** (str) – 当需要把program转译(transpile)至NCCL2模式下时,需要将当前endpoint(终端)传入该参数。Pserver模式不使用该参数 + +**代码示例** + +.. code-block:: python + + transpiler = fluid.DistributeTranspiler() + t.transpile( + trainer_id=0, + pservers="127.0.0.1:7000,127.0.0.1:7001", + trainers=2, + sync_mode=False, + current_endpoint="127.0.0.1:7000") + + .. py:method:: get_trainer_program(wait_port=True) 该方法可以得到Trainer侧的program。 -返回: Trainer侧的program +返回: Trainer侧的program + +返回类型: Program -返回类型: Program +**代码示例** + +.. code-block:: python + import paddle.fluid as fluid + #this is an example, find available endpoints in your case + pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + trainer_id = 0 + trainers = 4 + t = fluid.DistributeTranspiler() + t.transpile(trainer_id, trainers=trainers, pservers=pserver_endpoints) + trainer_program = t.get_trainer_program() .. py:method:: get_pserver_program(endpoint) @@ -717,11 +1092,26 @@ DistributeTranspiler 该方法可以得到Pserver(参数服务器)侧的程序 参数: - - **endpoint** (str) – 当前Pserver终端 + - **endpoint** (str) – 当前Pserver终端 -返回: 当前Pserver需要执行的program +返回: 当前Pserver需要执行的program -返回类型: Program +返回类型: Program + +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + #this is an example, find available endpoints in your case + pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + current_endpoint = "192.168.0.1:6174" + trainer_id = 0 + trainers = 4 + t = fluid.DistributeTranspiler() + t.transpile( + trainer_id, pservers=pserver_endpoints, trainers=trainers) + pserver_program = t.get_pserver_program(current_endpoint) .. py:method:: get_pserver_programs(endpoint) @@ -730,11 +1120,27 @@ DistributeTranspiler 该方法可以得到Pserver侧用于分布式训练的 ``main_program`` 和 ``startup_program`` 。 参数: - - **endpoint** (str) – 当前Pserver终端 + - **endpoint** (str) – 当前Pserver终端 + +返回: (main_program, startup_program), “Program”类型的元组 -返回: (main_program, startup_program), “Program”类型的元组 +返回类型: tuple + +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + #this is an example, find available endpoints in your case + pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + current_endpoint = "192.168.0.1:6174" + trainer_id = 0 + trainers = 4 + t = fluid.DistributeTranspiler() + t.transpile( + trainer_id, pservers=pserver_endpoints, trainers=trainers) + pserver_program, pserver_startup_program = t.get_pserver_programs(current_endpoint) -返回类型: tuple .. py:method:: get_startup_program(endpoint, pserver_program=None, startup_program=None) @@ -744,17 +1150,30 @@ DistributeTranspiler 获取当前Pserver的startup_program,如果有多个被分散到不同blocks的变量,则修改operator的输入变量。 参数: - - **endpoint** (str) – 当前Pserver终端 - - **pserver_program** (Program) – 已停止使用。 先调用get_pserver_program - - **startup_program** (Program) – 已停止使用。应在初始化时传入startup_program - -返回: Pserver侧的startup_program + - **endpoint** (str) – 当前Pserver终端 + - **pserver_program** (Program) – 已停止使用。 先调用get_pserver_program + - **startup_program** (Program) – 已停止使用。应在初始化时传入startup_program -返回类型: Program +返回: Pserver侧的startup_program +返回类型: Program +**代码示例** +.. code-block:: python + pserver_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + trainer_endpoints = "192.168.0.1:6174,192.168.0.2:6174" + current_endpoint = "192.168.0.1:6174" + trainer_id = 0 + trainers = 4 + + t = fluid.DistributeTranspiler() + t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers) + pserver_program = t.get_pserver_program(current_endpoint) + pserver_startup_program = t.get_startup_program(current_endpoint, + pserver_program) + @@ -784,8 +1203,12 @@ block中分割(split)出的元素个数的最小值。 注意: 根据:`issuecomment-369912156 `_ , 当数据块大小超过2MB时,我们可以有效地使用带宽。如果你想更改它,请详细查看 ``slice_variable`` 函数。 +**代码示例** - +.. code-block:: python + + config = fluid.DistributeTranspilerConfig() + config.slice_var_up = True @@ -801,17 +1224,25 @@ ExecutionStrategy **代码示例** -.. code-block:: python - - exec_strategy = fluid.ExecutionStrategy() - exec_strategy.num_threads = 4 +.. code-block:: python - train_exe = fluid.ParallelExecutor(use_cuda=True, - loss_name=loss.name, + x = fluid.layers.data(name='x', shape=[13], dtype='float32') + y = fluid.layers.data(name='y', shape=[1], dtype='float32') + y_predict = fluid.layers.fc(input=x, size=1, act=None) + + cost = fluid.layers.square_error_cost(input=y_predict, label=y) + avg_loss = fluid.layers.mean(cost) + + sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001) + sgd_optimizer.minimize(avg_loss) + + exec_strategy = fluid.ExecutionStrategy() + exec_strategy.num_threads = 4 + + train_exe = fluid.ParallelExecutor(use_cuda=False, + loss_name=avg_loss.name, exec_strategy=exec_strategy) - train_loss, = train_exe.run([loss.name], feed=feed_dict) - .. py:attribute:: allow_op_delay @@ -822,14 +1253,15 @@ ExecutionStrategy .. py:attribute:: num_iteration_per_drop_scope -int型成员。它表明了清空执行时产生的临时变量需要的程序执行重复次数。因为临时变量的形状可能在两次重复过程中保持一致,所以它会使整体执行过程更快。默认值为100。 +int型成员。它表明了清空执行时产生的临时变量需要的程序执行迭代次数。因为临时变量的形状可能在两次重复过程中保持一致,所以它会使整体执行过程更快。默认值为1。 .. note:: 1. 如果在调用 ``run`` 方法时获取结果数据,``ParallelExecutor`` 会在当前程序重复执行尾部清空临时变量 2. 在一些NLP模型里,该成员会致使GPU内存不足。此时,你应减少 ``num_iteration_per_drop_scope`` 的值 - +.. py:attribute:: num_iteration_per_run +它配置了当用户在python脚本中调用pe.run()时执行器会执行的迭代次数。 .. py:attribute:: num_threads @@ -872,31 +1304,54 @@ Executor将全局变量存储到全局作用域中,并为临时变量创建局 **示例代码** .. code-block:: python + + import paddle.fluid as fluid + import paddle.fluid.compiler as compiler + import numpy + import os - # 新建一个执行引擎Executor名为exe。 + use_cuda = True place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() exe = fluid.Executor(place) - # 仅运行一次startup program. - # 不需要优化/编译这个startup program. - exe.run(fluid.default_startup_program()) + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + # 仅运行一次startup program + # 不需要优化/编译这个startup program + startup_program.random_seed=1 + exe.run(startup_program) # 无需编译,直接运行main program - loss, = exe.run(fluid.default_main_program(), - feed=feed_dict, - fetch_list=[loss.name]) + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = exe.run(train_program, + feed={"X": x}, + fetch_list=[loss.name]) + + # 另一种方法是,编译这个main program然后运行。 + # 参考CompiledProgram以获取更多信息。 + # 注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + # 否则fluid会把逻辑核的所有数目设为CPU_NUM, + # 在这种情况下,输入的batch size应大于CPU_NUM, + # 否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) - # 另一种方法是,编译这个main program然后运行. 参考CompiledProgram compiled_prog = compiler.CompiledProgram( - fluid.default_main_program()).with_data_parallel( - loss_name=loss.name) - loss, = exe.run(compiled_prog, - feed=feed_dict, - fetch_list=[loss.name]) + train_program).with_data_parallel( + loss_name=loss.name) + loss_data, = exe.run(compiled_prog, + feed={"X": x}, + fetch_list=[loss.name]) 参数: - - **place** (core.CPUPlace|core.CUDAPlace(n)) – 指明了 ``Executor`` 的执行场所 + - **place** (fluid.CPUPlace|fluid.CUDAPlace(n)) – 指明了 ``Executor`` 的执行场所 @@ -909,11 +1364,13 @@ Executor将全局变量存储到全局作用域中,并为临时变量创建局 **示例代码** -.. code-block:: python +.. code-block:: python + + import paddle.fluid as fluid - cpu = core.CPUPlace() - exe = Executor(cpu) - ... + cpu = fluid.CPUPlace() + exe = fluid.Executor(cpu) + # 执行训练或测试过程 exe.close() @@ -927,75 +1384,180 @@ feed map为该program提供输入数据。fetch_list提供program训练结束后 应注意,执行器会执行program中的所有算子而不仅仅是依赖于fetch_list的那部分。 -参数: - - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) - - **feed** (dict) – 前向输入的变量,数据,词典dict类型, 例如 {“image”: ImageData, “label”: LabelData} - - **fetch_list** (list) – 用户想得到的变量或者命名的列表, 该方法会根据这个列表给出结果 - - **feed_var_name** (str) – 前向算子(feed operator)变量的名称 - - **fetch_var_name** (str) – 结果获取算子(fetch operator)的输出变量名称 - - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。缺省为全局域 - - **return_numpy** (bool) – 如果为True,则将结果张量(fetched tensor)转化为numpy - - **use_program_cache** (bool) – 是否跨批使用缓存程序设置。设置为True时,只有当(1)程序没有用数据并行编译,并且(2)program、 feed变量名和fetch_list变量名与上一步相比没有更改时,运行速度才会更快。 +**示例代码** -返回: 根据fetch_list来获取结果 +.. code-block:: python -返回类型: list(numpy.array) + import paddle.fluid as fluid + import numpy + + #首先创建执行引擎 + place = fluid.CPUPlace() # fluid.CUDAPlace(0) + exe = fluid.Executor(place) + + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + adam = fluid.optimizer.Adam() + adam.minimize(loss) + + #仅运行startup程序一次 + exe.run(fluid.default_startup_program()) + + x = numpy.random.random(size=(10, 1)).astype('float32') + outs = exe.run(feed={'X': x}, + fetch_list=[loss.name]) + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **feed** (dict) – 前向输入的变量,数据,词典dict类型, 例如 {“image”: ImageData, “label”: LabelData} + - **fetch_list** (list) – 用户想得到的变量或者命名的列表, 该方法会根据这个列表给出结果 + - **feed_var_name** (str) – 前向算子(feed operator)变量的名称 + - **fetch_var_name** (str) – 结果获取算子(fetch operator)的输出变量名称 + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。缺省为全局域 + - **return_numpy** (bool) – 如果为True,则将结果张量(fetched tensor)转化为numpy + - **use_program_cache** (bool) – 是否跨批使用缓存程序设置。设置为True时,只有当(1)程序没有用数据并行编译,并且(2)program、 feed变量名和fetch_list变量名与上一步相比没有更改时,运行速度才会更快。 + +返回: 根据fetch_list来获取结果 + +返回类型: list(numpy.array) + + +.. py:method:: infer_from_dataset(program=None, dataset=None, scope=None, thread=0, debug=False, fetch_list=None, fetch_info=None, print_period=100) + +infer_from_dataset的文档与train_from_dataset几乎完全相同,只是在分布式训练中,推进梯度将在infer_from_dataset中禁用。 infer_from_dataset()可以非常容易地用于多线程中的评估。 + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **dataset** (paddle.fluid.Dataset) – 在此函数外创建的数据集,用户应当在调用函数前提供完整定义的数据集。必要时请检查Dataset文件。默认为None + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。默认为全局域 + - **thread** (int) – 用户想要在这个函数中运行的线程数量。线程的实际数量为min(Dataset.thread_num, thread),如果thread > 0,默认为0 + - **debug** (bool) – 是否开启debug模式,默认为False + - **fetch_list** (Variable List) – 返回变量列表,每个变量都会在训练过程中被打印出来,默认为None + - **fetch_info** (String List) – 每个变量的打印信息,默认为None + - **print_period** (int) – 每两次打印之间间隔的mini-batches的数量,默认为100 +返回: None **示例代码** -.. code-block:: python +.. code-block:: python + import paddle.fluid as fluid + place = fluid.CPUPlace() # 使用GPU时可设置place = fluid.CUDAPlace(0) + exe = fluid.Executor(place) + x = fluid.layers.data(name="x", shape=[10, 10], dtype="int64") + y = fluid.layers.data(name="y", shape=[1], dtype="int64", lod_level=1) + dataset = fluid.DatasetFactory().create_dataset() + dataset.set_use_var([x, y]) + dataset.set_thread(1) + filelist = [] # 您可以设置您自己的filelist,如filelist = ["dataA.txt"] + dataset.set_filelist(filelist) + exe.run(fluid.default_startup_program()) + exe.infer_from_dataset(program=fluid.default_main_program(),dataset=dataset) + + +.. py:method:: train_from_dataset(program=None, dataset=None, scope=None, thread=0, debug=False, fetch_list=None, fetch_info=None, print_period=100) + +从预定义的数据集中训练。 数据集在paddle.fluid.dataset中定义。 给定程序(或编译程序),train_from_dataset将使用数据集中的所有数据样本。 输入范围可由用户给出。 默认情况下,范围是global_scope()。训练中的线程总数是thread。 训练中使用的线程数将是数据集中threadnum的最小值,同时也是此接口中线程的值。 可以设置debug,以便执行器显示所有算子的运行时间和当前训练任务的吞吐量。 + +注意:train_from_dataset将销毁每次运行在executor中创建的所有资源。 + +参数: + - **program** (Program|CompiledProgram) – 需要执行的program,如果没有给定那么默认使用default_main_program (未编译的) + - **dataset** (paddle.fluid.Dataset) – 在此函数外创建的数据集,用户应当在调用函数前提供完整定义的数据集。必要时请检查Dataset文件。默认为None + - **scope** (Scope) – 执行这个program的域,用户可以指定不同的域。默认为全局域 + - **thread** (int) – 用户想要在这个函数中运行的线程数量。线程的实际数量为min(Dataset.thread_num, thread),如果thread > 0,默认为0 + - **debug** (bool) – 是否开启debug模式,默认为False + - **fetch_list** (Variable List) – 返回变量列表,每个变量都会在训练过程中被打印出来,默认为None + - **fetch_info** (String List) – 每个变量的打印信息,默认为None + - **print_period** (int) – 每两次打印之间间隔的mini-batches的数量,默认为100 - data = fluid.layers.data(name='X', shape=[1], dtype='float32') - hidden = fluid.layers.fc(input=data, size=10) - layers.assign(hidden, out) - loss = fluid.layers.mean(out) - adam = fluid.optimizer.Adam() - adam.minimize(loss) +返回: None +**示例代码** -.. code-block:: python +.. code-block:: python + import paddle.fluid as fluid - cpu = core.CPUPlace() - exe = Executor(cpu) - exe.run(default_startup_program()) + place = fluid.CPUPlace() # 通过设置place = fluid.CUDAPlace(0)使用GPU + exe = fluid.Executor(place) + x = fluid.layers.data(name="x", shape=[10, 10], dtype="int64") + y = fluid.layers.data(name="y", shape=[1], dtype="int64", lod_level=1) + dataset = fluid.DatasetFactory().create_dataset() + dataset.set_use_var([x, y]) + dataset.set_thread(1) + filelist = [] # 您可以设置您自己的filelist,如filelist = ["dataA.txt"] + dataset.set_filelist(filelist) + exe.run(fluid.default_startup_program()) + exe.infer_from_dataset(program=fluid.default_main_program(), + dataset=dataset) -.. code-block:: python - x = numpy.random.random(size=(10, 1)).astype('float32') - outs = exe.run( - feed={'X': x}, - fetch_list=[loss.name]) +.. _cn_api_fluid_global_scope: +global_scope +------------------------------- +.. py:function:: paddle.fluid.global_scope() + + +获取全局/默认作用域实例。很多api使用默认 ``global_scope`` ,例如 ``Executor.run`` 。 + +**示例代码** +.. code-block:: python + import paddle.fluid as fluid + import numpy + fluid.global_scope().var("data").get_tensor().set(numpy.ones((2, 2)), fluid.CPUPlace()) + numpy.array(fluid.global_scope().find_var("data").get_tensor()) +返回:全局/默认作用域实例 +返回类型:Scope -.. _cn_api_fluid_global_scope: +.. _cn_api_fluid_gradients: -global_scope +gradients ------------------------------- -.. py:function:: paddle.fluid.global_scope() +.. py:function:: paddle.fluid.gradients(targets, inputs, target_gradients=None, no_grad_set=None) +将目标梯度反向传播到输入。 -获取全局/默认作用域实例。很多api使用默认 ``global_scope`` ,例如 ``Executor.run`` 。 +参数: + - **targets** (Variable|list[Variable]) – 目标变量 + - **inputs** (Variable|list[Variable]) – 输入变量 + - **target_gradients** (Variable|list[Variable]|None) – 目标的梯度变量,应与目标变量形状相同;如果设置为None,则以1初始化所有梯度变量 + - **no_grad_sethread** (set[string]) – 在Block 0中不具有梯度的变量,所有block中被设置 ``stop_gradient=True`` 的变量将被自动加入该set -返回:全局/默认作用域实例 -返回类型:Scope +返回:数组,包含与输入对应的梯度。如果一个输入不影响目标函数,则对应的梯度变量为None +返回类型:(list[Variable]) +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + + x = fluid.layers.data(name='x', shape=[2,8,8], dtype='float32') + x.stop_gradient=False + y = fluid.layers.conv2d(x, 4, 1, bias_attr=False) + y = fluid.layers.relu(y) + y = fluid.layers.conv2d(y, 4, 1, bias_attr=False) + y = fluid.layers.relu(y) + z = fluid.gradients([y], x) + print(z) @@ -1006,11 +1568,18 @@ in_dygraph_mode .. py:function:: paddle.fluid.in_dygraph_mode() -返回:bool,如果Program是在动态图模式下运行的则为True。 +检查程序状态(tracer) - 是否在dygraph模式中运行 +返回:如果Program是在动态图模式下运行的则为True。 +返回类型:out(boolean) +**示例代码** + +.. code-block:: python + if fluid.in_dygraph_mode(): + pass .. _cn_api_fluid_LoDTensor: @@ -1037,32 +1606,40 @@ X 为 LoDTensor,它包含两个序列。第一个长度是2,第二个长度 :: - x.lod = [[2, 3]] - x.data = [[1, 2], [3, 4], // seq 1 + x.lod = [[2, 3]] + + x.data = [[1, 2], [3, 4], [5, 6], [7, 8], [9, 10]] - [5, 6], [7, 8], [9, 10]] // seq 2 - - x.shape = [5, 2] + x.shape = [5, 2] LoD可以有多个level(例如,一个段落可以有多个句子,一个句子可以有多个单词)。下面的例子中,Y为LoDTensor ,lod_level为2。表示有2个序列,第一个序列的长度是2(有2个子序列),第二个序列的长度是1。第一序列的两个子序列长度分别为2和2。第二个序列的子序列的长度是3。 :: + + y.lod = [[2 1], [2 2 3]] + + y.shape = [2+2+3, ...] + +**示例代码** - y.lod = [[2 1], [2 2 3]] y.shape = [2+2+3, ...] +.. code-block:: python + import paddle.fluid as fluid + + t = fluid.LoDTensor() .. note:: - 在上面的描述中,LoD是基于长度的。在paddle内部实现中,lod是基于偏移的。因此,在内部,y.lod表示为[[0,2,3],[0,2,4,7]](基于长度的Lod表示为为[[2-0,3-2],[2-0,4-2,7-4]])。 + 在上面的描述中,LoD是基于长度的。在paddle内部实现中,lod是基于偏移的。因此,在内部,y.lod表示为[[0,2,3],[0,2,4,7]](基于长度的Lod表示为为[[2-0,3-2],[2-0,4-2,7-4]])。 - 可以将LoD理解为recursive_sequence_length(递归序列长度)。此时,LoD必须是基于长度的。由于历史原因。当LoD在API中被称为lod时,它可能是基于偏移的。用户应该注意。 + 可以将LoD理解为recursive_sequence_length(递归序列长度)。此时,LoD必须是基于长度的。由于历史原因。当LoD在API中被称为lod时,它可能是基于偏移的。用户应该注意。 -.. py:method:: has_valid_recursive_sequence_lengths(self: paddle.fluid.core.LoDTensor) → bool +.. py:method:: has_valid_recursive_sequence_lengths(self: paddle.fluid.core.LoDTensor) → bool 检查LoDTensor的lod值的正确性。 @@ -1070,7 +1647,19 @@ LoD可以有多个level(例如,一个段落可以有多个句子,一个句 返回类型: out (bool) -.. py:method:: lod(self: paddle.fluid.core.LoDTensor) → List[List[int]] +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + t.set_recursive_sequence_lengths([[2, 3]]) + print(t.has_valid_recursive_sequence_lengths()) # True + +.. py:method:: lod(self: paddle.fluid.core_avx.LoDTensor) → List[List[int]] 得到LoD Tensor的LoD。 @@ -1078,8 +1667,19 @@ LoD可以有多个level(例如,一个段落可以有多个句子,一个句 返回类型:out(List [List [int]]) +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + t.set_lod([[0, 2, 5]]) + print(t.lod()) # [[0, 2, 5]] -.. py:method:: recursive_sequence_lengths(self: paddle.fluid.core.LoDTensor) → List[List[int]] +.. py:method:: recursive_sequence_lengths(self: paddle.fluid.core_avx.LoDTensor) → List[List[int]] 得到与LoD对应的LoDTensor的序列长度。 @@ -1087,29 +1687,78 @@ LoD可以有多个level(例如,一个段落可以有多个句子,一个句 返回类型:out(List [List [int]) +**示例代码** + +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + t.set_recursive_sequence_lengths([[2, 3]]) + print(t.recursive_sequence_lengths()) # [[2, 3]] + + +.. py:method:: set(*args, **kwargs) + +重载函数 + +1. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[float32], arg1: paddle::platform::CPUPlace) -> None + +2. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[int32], arg1: paddle::platform::CPUPlace) -> None + +3. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[float64], arg1: paddle::platform::CPUPlace) -> None + +4. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[int64], arg1: paddle::platform::CPUPlace) -> None + +5. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[bool], arg1: paddle::platform::CPUPlace) -> None + +6. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[uint16], arg1: paddle::platform::CPUPlace) -> None +7. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[uint8], arg1: paddle::platform::CPUPlace) -> None -.. py:method:: set_lod(self: paddle.fluid.core.LoDTensor, lod: List[List[int]]) → None +8. set(self: paddle.fluid.core_avx.Tensor, arg0: numpy.ndarray[int8], arg1: paddle::platform::CPUPlace) -> None + +.. py:method:: set_lod(self: paddle.fluid.core_avx.LoDTensor, lod: List[List[int]]) → None 设置LoDTensor的LoD。 参数: - **lod** (List [List [int]]) - 要设置的lod。 -.. py:method:: set_recursive_sequence_lengths(self: paddle.fluid.core.LoDTensor, recursive_sequence_lengths: List[List[int]]) → None +**示例代码** -根据递归序列长度recursive_sequence_lengths设置LoDTensor的LoD。 +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + t.set_lod([[0, 2, 5]]) -:: +.. py:method:: set_recursive_sequence_lengths(self: paddle.fluid.core.LoDTensor, recursive_sequence_lengths: List[List[int]]) → None + +根据递归序列长度recursive_sequence_lengths设置LoDTensor的LoD。 - 例如,如果recursive_sequence_lengths = [[2,3]], - 意味着有两个长度分别为2和3的序列,相应的lod将是[[0,2,2 + 3]],即[[0, 2,5]]。 +例如,如果recursive_sequence_lengths = [[2,3]],意味着有两个长度分别为2和3的序列,相应的lod将是[[0,2,2 + 3]],即[[0, 2,5]]。 参数: - **recursive_sequence_lengths** (List [List [int]]) - 序列长度。 +**示例代码** +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + t.set_recursive_sequence_lengths([[2, 3]]) +.. py:method:: shape(self: paddle.fluid.core_avx.Tensor) → List[int] @@ -1125,13 +1774,31 @@ LoDTensorArray .. py:class:: paddle.fluid.LoDTensorArray -.. py:method:: append(self: paddle.fluid.core.LoDTensorArray, tensor: paddle.fluid.core.LoDTensor) → None +LoDTensor的数组。 -将LoDTensor追加到LoDTensorArray后。 +**示例代码** +.. code-block:: python + + import paddle.fluid as fluid + + arr = fluid.LoDTensorArray() +.. py:method:: append(self: paddle.fluid.core_avx.LoDTensorArray, tensor: paddle.fluid.core.LoDTensor) → None +将LoDTensor追加到LoDTensorArray后。 + +**示例代码** +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + + arr = fluid.LoDTensorArray() + t = fluid.LoDTensor() + t.set(np.ndarray([5, 30]), fluid.CPUPlace()) + arr.append(t) @@ -1144,23 +1811,47 @@ memory_optimize .. py:function:: paddle.fluid.memory_optimize(input_program, skip_opt_set=None, print_log=False, level=0, skip_grads=False) +历史遗留的内存优化策略,通过在不同operators间重用var内存来减少总内存消耗。 +用一个简单的示例来解释该算法: + +c = a + b # 假设这里是最后一次使用a +d = b * c -通过重用var内存来优化内存。 +鉴于在“c = a + b”之后不再使用a,且a和d的大小相同,我们可以用变量a来代替变量d,即实际上,上面的代码可以优化成: +c = a + b +a = b * c + +请注意,在此历史遗存设计中,我们将直接用变量a代替变量d,这意味着在你调用该API后,某些变量将会消失,还有一些会取非预期值。正如上面的例子中,执行程序后,实际上a取d的值。 + +因此,为避免重要变量在优化过程中被重用或移除,我们支持用skip_opt_set指定一个变量白名单。skip_opt_set中的变量不会受memory_optimize API的影响。 + + .. note:: - 它不支持block中嵌套子block。 + + 此API已被弃用,请不要在你新写的代码中使用它。它不支持block中嵌套子block,如While、IfElse等。 参数: - - **input_program** (str) – 输入Program。 - - **skip_opt_set** (set) – set中的vars将不被内存优化。 - - **print_log** (bool) – 是否打印debug日志。 - - **level** (int) 如果 level=0 并且shape是完全相等,则重用。 + - **input_program** (str) – 输入Program。 + - **skip_opt_set** (set) – set中的vars将不被内存优化。 + - **print_log** (bool) – 是否打印debug日志。 + - **level** (int) - 值为0或1。如果level=0,则仅当a.size == b.size时我们才用b代替a;如果level=1,只要a.size <= b.size时我们就可以用b代替a。 返回: None +**示例代码** +.. code-block:: python - + import paddle.fluid as fluid + main_prog = fluid.Program() + startup_prog = fluid.Program() + + place = fluid.CPUPlace() + exe = fluid.Executor(place) + + exe.run(startup_prog) + fluid.memory_optimize(main_prog) @@ -1178,22 +1869,23 @@ name_scope 注意: 这个函数只能用于调试和可视化。不要将其用于分析,比如graph/program转换。 参数: - - **prefix** (str) - 前缀 + - **prefix** (str) - 前缀 **示例代码** .. code-block:: python - - with name_scope("encoder"): - ... - with name_scope("decoder"): - ... - with name_scope("attention"): - ... - - - - + + with fluid.name_scope("s1"): + a = fluid.layers.data(name='data', shape=[1], dtype='int32') + b = a + 1 + with fluid.name_scope("s2"): + c = b * 1 + with fluid.name_scope("s3"): + d = c / 1 + with fluid.name_scope("s1"): + f = fluid.layers.pow(d, 2.0) + with fluid.name_scope("s4"): + g = f - 1 @@ -1209,8 +1901,51 @@ ParallelExecutor ``ParallelExecutor`` 专门设计用来实现数据并行计算,着力于向不同结点(node)分配数据,并行地在不同结点中对数据进行操作。如果在GPU上使用该类运行程序,node则用来指代GPU, ``ParallelExecutor`` 也将自动获取在当前机器上可用的GPU资源。如果在CPU上进行操作,node则指代CPU,同时你也可以通过添加环境变量 ``CPU_NUM`` 来设置CPU设备的个数。例如,``CPU_NUM=4``。但是如果没有设置该环境变量,该类会调用 ``multiprocessing.cpu_count`` 来获取当前系统中CPU的个数。 +**示例代码** +.. code-block:: python + import paddle.fluid as fluid + import numpy + import os + + use_cuda = True + place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() + + # 注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + # 否则fluid会把逻辑核的所有数目设为CPU_NUM, + # 在这种情况下,输入的batch size应大于CPU_NUM, + # 否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) + + exe = fluid.Executor(place) + + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + test_program = fluid.default_main_program().clone(for_test=True) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + startup_program.random_seed=1 + exe.run(startup_program) + + train_exe = fluid.ParallelExecutor(use_cuda=use_cuda, + main_program=train_program, + loss_name=loss.name) + test_exe = fluid.ParallelExecutor(use_cuda=use_cuda, + main_program=test_program, + share_vars_from=train_exe) + + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = train_exe.run(feed={"X": x}, + fetch_list=[loss.name]) + + loss_data, = test_exe.run(feed={"X": x}, + fetch_list=[loss.name]) 参数: - **use_cuda** (bool) – 是否使用CUDA @@ -1225,24 +1960,10 @@ ParallelExecutor 返回:初始化后的 ``ParallelExecutor`` 对象 -返回类型: ParallelExecutor +返回类型: ParallelExecutor 抛出异常:``TypeError`` - 如果提供的参数 ``share_vars_from`` 不是 ``ParallelExecutor`` 类型的,将会弹出此异常 -**代码示例** - -.. code-block:: python - - train_exe = fluid.ParallelExecutor(use_cuda=True, loss_name=loss.name) - test_exe = fluid.ParallelExecutor(use_cuda=True, - main_program=test_program, - share_vars_from=train_exe) - - train_loss, = train_exe.run([loss.name], feed=feed_dict) - test_loss, = test_exe.run([loss.name], feed=feed_dict) - - - .. py:method:: run(fetch_list, feed=None, feed_dict=None, return_numpy=True) 使用 ``fetch_list`` 执行一个 ``ParallelExecutor`` 对象。 @@ -1250,27 +1971,55 @@ ParallelExecutor 参数 ``feed`` 可以是 ``dict`` 或者 ``list`` 类型变量。如果该参数是 ``dict`` 类型,feed中的数据将会被分割(split)并分送给多个设备(CPU/GPU)。 反之,如果它是 ``list`` ,则列表中的各个元素都会直接分别被拷贝到各设备中。 -例如,如果 ``feed`` 是个 ``dict`` 类型变量,则有 - -.. code-block:: python - - exe = ParallelExecutor() - # 图像会被split到设备中。假设有两个设备,那么每个设备将会处理形为 (24, 1, 28, 28)的图像 - exe.run(feed={'image': numpy.random.random(size=(48, 1, 28, 28))}) +**示例代码** -如果 ``feed`` 是个 ``list`` 类型变量,则有 +.. code-block:: python + + import paddle.fluid as fluid + import numpy + import os -.. code-block:: python + use_cuda = True + place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() + + # 注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + # 否则fluid会把逻辑核的所有数目设为CPU_NUM, + # 在这种情况下,输入的batch size应大于CPU_NUM, + # 否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) + exe = fluid.Executor(place) - exe = ParallelExecutor() + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + fluid.optimizer.SGD(learning_rate=0.01).minimize(loss) + + startup_program.random_seed=1 + exe.run(startup_program) + + train_exe = fluid.ParallelExecutor(use_cuda=use_cuda, + main_program=train_program, + loss_name=loss.name) + # 如果feed参数是dict类型: + # 图像会被split到设备中。假设有两个设备,那么每个设备将会处理形为 (5, 1)的图像 + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = train_exe.run(feed={"X": x}, + + fetch_list=[loss.name]) + + # 如果feed参数是list类型: # 各设备挨个处理列表中的每个元素 - # 第一个设备处理形为 (48, 1, 28, 28) 的图像 - # 第二个设备处理形为 (32, 1, 28, 28) 的图像 + # 第一个设备处理形为 (10, 1) 的图像 + # 第二个设备处理形为 (9, 1) 的图像 # # 使用 exe.device_count 得到设备数目 - exe.run(feed=[{"image": numpy.random.random(size=(48, 1, 28, 28))}, - {"image": numpy.random.random(size=(32, 1, 28, 28))}, - ]) + x2 = numpy.random.random(size=(9, 1)).astype('float32') + loss_data, = train_exe.run(feed=[{"X": x}, {"X": x2}], + fetch_list=[loss.name]) 参数: - **fetch_list** (list) – 获取的变量名列表 @@ -1292,7 +2041,7 @@ ParallelExecutor **代码示例** -.. code-block:: python +.. code-block:: python pe = fluid.ParallelExecutor(use_cuda=use_cuda, loss_name=avg_cost.name, @@ -1300,10 +2049,48 @@ ParallelExecutor loss = pe.run(feed=feeder.feed(cur_batch), fetch_list=[avg_cost.name])) +.. py:method:: drop_local_exe_scopes() +立即删除本地执行作用域。 +  +在程序执行期间,生成中间结果被放置在本地执行作用域内,在某些模型中,这些中间结果的创建和删除较为费时。为了解决这个问题,ParallelExecutor在ExecutionStrategy中提供了可选项,如num_iteration_per_drop_scope,此选项指示在删除本地执行作用域之前要运行的迭代次数。 但在某些情况下,每次迭代都会产生不同的中间结果,这将导致本地执行作用域所需的内存逐渐增加。 如果你想在这个时候运行另一个程序,可能没有足够的存储空间,此时你应该删除其他程序的本地执行作用域。 + +**代码示例** +.. code-block:: python + import paddle.fluid as fluid + import numpy + import os + + use_cuda = True + # 注意:如果你使用CPU运行程序,需要具体设置CPU_NUM, + # 否则fluid会把逻辑核的所有数目设为CPU_NUM, + # 在这种情况下,输入的batch size应大于CPU_NUM, + # 否则程序会异常中断。 + if not use_cuda: + os.environ['CPU_NUM'] = str(2) + + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + data = fluid.layers.data(name='X', shape=[1], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10) + loss = fluid.layers.mean(hidden) + + place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace() + exe.run(startup_program) + + parallel_exe = fluid.ParallelExecutor(use_cuda=use_cuda, + main_program=train_program, + loss_name=loss.name) + + x = numpy.random.random(size=(10, 1)).astype('float32') + loss_data, = parallel_exe.run(feed={"X": x}, + fetch_list=[loss.name]) + + parallel_exe.drop_local_exe_scopes() @@ -1330,8 +2117,10 @@ ParamAttr **代码示例** -.. code-block:: python +.. code-block:: python + import paddle.fluid as fluid + w_param_attrs = fluid.ParamAttr(name="fc_weight", learning_rate=0.5, regularizer=fluid.L2Decay(1.0), @@ -1366,55 +2155,20 @@ Program **代码示例** -.. code-block:: python - - main_program = fluid.Program() - startup_program = fluid.Program() - with fluid.program_guard(main_program=main_program, startup_program=startup_program): - fluid.layers.data(name="x", shape=[-1, 784], dtype='float32') - fluid.layers.data(name="y", shape=[-1, 1], dtype='int32') - fluid.layers.fc(name="fc", shape=[10], dtype='float32', act="relu") - - - -.. py:attribute:: op_role - -operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 - -注意:这是一个底层API。它仅用于 ``ParallelExecutor`` 复制或调度operator到设备。 - -例如,Forward operator应该在每个设备上执行。Backward operator在每个设备上执行,并将后向传播的参数梯度(使用 ``op_role_var`` 获得该变量)合并到一个设备上。Optimize operator只在一个设备上执行,并向其他设备广播新的参数, - - - -.. py:attribute:: set_op_role - -operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 - -注意:这是一个底层API。它仅用于 ``ParallelExecutor`` 复制或调度operator到设备上执行。 - -例如,Forward operator应该在每个设备上执行。Backward operato应该在每个设备上执行,并将后向传播的参数梯度(使用op_role_var获得该变量)合并到一个设备上。Optimize operator只在一个设备上执行,并向其他设备广播新的参数 - - - -.. py:attribute:: op_role_var - -``op_role`` 的辅助变量。 - -参考: ``Program.op_role`` 文档。 - -注意:这是一个底层API,用户不应该直接使用它。 - - - -.. py:attribute:: set_op_role_var - -``op_role`` 的辅助变量。 - -参考: ``Program.op_role`` 文档。 +.. code-block:: python + + import paddle.fluid as fluid -注意:这是一个底层API。用户不应该直接使用它。 + main_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(main_program=main_program, startup_program=startup_program): + x = fluid.layers.data(name="x", shape=[-1, 784], dtype='float32') + y = fluid.layers.data(name="y", shape=[-1, 1], dtype='int32') + z = fluid.layers.fc(name="fc", input=x, size=10, act="relu") + print("main program is: {}".format(main_program)) + + print("start up program is: {}".format(startup_program)) .. py:method:: to_string(throw_on_error, with_details=False) @@ -1422,8 +2176,8 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 用于debug 参数: - - **throw_on_error** (bool): 没有设置任何必需的字段时,抛出值错误。 - - **with_details** (bool): 值为true时,打印更多关于变量和参数的信息,如trainable, optimize_attr等 + - **throw_on_error** (bool): 没有设置任何必需的字段时,抛出值错误。 + - **with_details** (bool): 值为true时,打印更多关于变量和参数的信息,如trainable, optimize_attr等 返回:(str): debug 字符串 @@ -1432,85 +2186,141 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 抛出异常: - ``ValueError`` - 当 ``throw_on_error == true`` ,但没有设置任何必需的字段时,抛出 ``ValueError`` 。 +**代码示例** +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + prog_string = prog.to_string(throw_on_error=True, with_details=False) + print(prog_string) .. py:method:: clone(for_test=False) 创建一个新的、相同的Program。 -有些operator,在训练和测试之间的行为是不同的,比如batch_norm。它们有一个属性is_test来控制行为。当for_test=True时,此方法将把它们的is_test属性更改为True。 +有些operator,在训练和测试之间的行为是不同的,比如 ``batch_norm`` 。它们有一个属性 ``is_test`` 来控制行为。当 ``for_test=True`` 时,此方法将把它们的 ``is_test`` 属性更改为True。 -- 克隆Program,该Program用于训练时,将 ``for_test`` 设置为False。 -- 克隆Program,该Program用于测试时,将 ``for_test`` 设置为True。 +- 克隆Program用于训练时,将 ``for_test`` 设置为False。 +- 克隆Program用于测试时,将 ``for_test`` 设置为True。我们不会在此处对程序进行任何裁剪,因此,如果您只是想要一个用于测试的前向计算程序,请在使用 ``Opimizer.minimize`` 之前使用 ``clone`` -注意:此API不会删除任何操作符。请在backward和optimization之前使用clone(for_test=True)。 +注意: + 1. ``Program.clone()`` 方法不会克隆 ``py_reader`` + 2. 此API不会裁剪任何算子。请在backward和optimization之前使用 ``clone(for_test=True)`` 。例如: -**代码示例** + .. code-block:: python -.. code-block:: python - - test_program = fluid.default_main_program().clone(for_test=True) - optimizer = fluid.optimizer.Momentum(learning_rate=0.01, momentum=0.9) - optimizer.minimize() + test_program = fluid.default_main_program().clone(for_test=True) + optimizer = fluid.optimizer.Momentum(learning_rate=0.01, momentum=0.9) + optimizer.minimize() 参数: - - **for_test** (bool) – 取值为True时,clone方法内部会把operator的属性 ``is_test`` 设置为 True + - **for_test** (bool) – 取值为True时,clone方法内部会把operator的属性 ``is_test`` 设置为 True 返回:一个新的、相同的Program -返回类型:Program +返回类型:Program **代码示例** -1.克隆一个Program,示例代码如下: +注意,Program Desc在clone后的顺序可能不同,这不会影响您的训练或测试进程。在下面的示例中,我们为您提供了一个简单的方法print_prog(program)来打印程序描述,以确保clone后您仍能得到同样的打印结果: -.. code-block:: python +.. code-block:: python + + import paddle.fluid as fluid + import six - train_program = fluid.Program() - startup_program = fluid.Program() - with fluid.program_guard(train_program, startup_program): - img = fluid.layers.data(name='image', shape=[784]) - hidden = fluid.layers.fc(input=img, size=200, act='relu') - hidden = fluid.layers.dropout(hidden, dropout_prob=0.5) - loss = fluid.layers.cross_entropy( - input=fluid.layers.fc(hidden, size=10, act='softmax'), - label=fluid.layers.data(name='label', shape=[1], dtype='int64')) - test_program = train_program.clone(for_test=True) - sgd = fluid.optimizer.SGD(learning_rate=1e-3) - with fluid.program_guard(train_program, startup_program): - sgd.minimize(loss) - -2.如果分别运行 train Program 和 test Program,则可以不使用clone。 -.. code-block:: python + def print_prog(prog): + for name, value in sorted(six.iteritems(prog.block(0).vars)): + print(value) + for op in prog.block(0).ops: + print("op type is {}".format(op.type)) + print("op inputs are {}".format(op.input_arg_names)) + print("op outputs are {}".format(op.output_arg_names)) + for key, value in sorted(six.iteritems(op.all_attrs())): + if key not in ['op_callstack', 'op_role_var']: + print(" [ attrs: {}: {} ]".format(key, value)) - import paddle.fluid as fluid +1.克隆一个Program,示例代码如下。 - def network(is_test): - img = fluid.layers.data(name='image', shape=[784]) - hidden = fluid.layers.fc(input=img, size=200, act='relu') - hidden = fluid.layers.dropout(hidden, dropout_prob=0.5, is_test=is_test) - loss = fluid.layers.cross_entropy( - input=fluid.layers.fc(hidden, size=10, act='softmax'), - label=fluid.layers.data(name='label', shape=[1], dtype='int64')) - return loss - - train_program = fluid.Program() - startup_program = fluid.Program() - test_program = fluid.Program() +.. code-block:: python - with fluid.program_guard(train_program, startup_program): - with fluid.unique_name.guard(): - loss = network(is_test=False) - sgd = fluid.optimizer.SGD(learning_rate=1e-3) - sgd.minimize(loss) + import paddle.fluid as fluid + import six + + def print_prog(prog): + for name, value in sorted(six.iteritems(prog.block(0).vars)): + print(value) + for op in prog.block(0).ops: + print("op type is {}".format(op.type)) + print("op inputs are {}".format(op.input_arg_names)) + print("op outputs are {}".format(op.output_arg_names)) + for key, value in sorted(six.iteritems(op.all_attrs())): + if key not in ['op_callstack', 'op_role_var']: + print(" [ attrs: {}: {} ]".format(key, value)) + + train_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(train_program, startup_program): + with fluid.unique_name.guard(): + img = fluid.layers.data(name='image', shape=[784]) + hidden = fluid.layers.fc(input=img, size=200, act='relu') + hidden = fluid.layers.dropout(hidden, dropout_prob=0.5) + loss = fluid.layers.cross_entropy( + input=fluid.layers.fc(hidden, size=10, act='softmax'), + label=fluid.layers.data(name='label', shape=[1], dtype='int64')) + avg_loss = fluid.layers.mean(loss) + test_program = train_program.clone(for_test=False) + print_prog(test_program) + with fluid.program_guard(train_program, startup_program): + with fluid.unique_name.guard(): + sgd = fluid.optimizer.SGD(learning_rate=1e-3) + sgd.minimize(avg_loss) + +2.如果分别运行 train Program 和 test Program,则可以不使用clone。 - # 不使用测试阶段的startup program - with fluid.program_guard(test_program, fluid.Program()): - with fluid.unique_name.guard(): - loss = network(is_test=True) +.. code-block:: python -上边两个代码片段生成的Program是一样的。 + import paddle.fluid as fluid + import six + + def print_prog(prog): + for name, value in sorted(six.iteritems(prog.block(0).vars)): + print(value) + for op in prog.block(0).ops: + print("op type is {}".format(op.type)) + print("op inputs are {}".format(op.input_arg_names)) + print("op outputs are {}".format(op.output_arg_names)) + for key, value in sorted(six.iteritems(op.all_attrs())): + if key not in ['op_callstack', 'op_role_var']: + print(" [ attrs: {}: {} ]".format(key, value)) + def network(is_test): + img = fluid.layers.data(name='image', shape=[784]) + hidden = fluid.layers.fc(input=img, size=200, act='relu') + hidden = fluid.layers.dropout(hidden, dropout_prob=0.5) + loss = fluid.layers.cross_entropy( + input=fluid.layers.fc(hidden, size=10, act='softmax'), + label=fluid.layers.data(name='label', shape=[1], dtype='int64')) + avg_loss = fluid.layers.mean(loss) + return avg_loss + + + train_program_2 = fluid.Program() + startup_program_2 = fluid.Program() + test_program_2 = fluid.Program() + with fluid.program_guard(train_program_2, startup_program_2): + with fluid.unique_name.guard(): + sgd = fluid.optimizer.SGD(learning_rate=1e-3) + sgd.minimize(avg_loss) + # 不使用测试阶段的启动程序 + with fluid.program_guard(test_program_2, fluid.Program()): + with fluid.unique_name.guard(): + loss = network(is_test=True) + print(test_program_2) + +上边两个代码片段生成和打印的Program是一样的。 .. py:staticmethod:: parse_from_string(binary_str) @@ -1521,7 +2331,7 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 参数: - **binary_str_type** (str) – prootbuf二进制字符串 -返回: 反序列化后的ProgramDesc +返回: 反序列化后的ProgramDesc 返回类型:Program @@ -1529,6 +2339,16 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 该program中的block的个数 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + num_blocks = prog.num_blocks + print(num_blocks) + .. py:attribute:: random_seed @@ -1536,10 +2356,32 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 注意:必须在operator被添加之前设置。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + random_seed = prog.random_seed + print(random_seed) + prog.random_seed = 1 + print(prog.random_seed) + .. py:method:: global_block() 获取该program的第一个block。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + gb_block = prog.global_block() + print(gb_block) + .. py:method:: block(index) 返回该program中 , ``index`` 指定的block。 ``index`` 类型为int @@ -1548,10 +2390,30 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 返回类型:Block +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + block_0 = prog.block(0) + print(block_0) + .. py:method:: current_block() 获取当前block。当前block是用来添加operators。 +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + prog = fluid.default_main_program() + current_blk = prog.current_block() + print(current_blk) + .. py:method:: list_vars() 获取当前program中所有变量。返回值是一个可迭代对象(iterable object)。 @@ -1559,10 +2421,18 @@ operator的角色,值只能是枚举变量{Forward, Backward, Optimize}。 返回:generator 会yield每个Program中的变量 返回类型:iterable + +**代码示例** +.. code-block:: python - - + import paddle.fluid as fluid + + prog = fluid.default_main_program() + img = fluid.layers.data(name='img', shape=[1,28,28], dtype='float32') + label = fluid.layers.data(name='label', shape=[128,1], dtype='int64') + for var in prog.list_vars(): + print(var) @@ -1582,31 +2452,31 @@ program_guard **代码示例** -.. code-block:: python +.. code-block:: python - import paddle.fluid as fluid - main_program = fluid.Program() - startup_program = fluid.Program() - with fluid.program_guard(main_program, startup_program): - data = fluid.layers.data(...) - hidden = fluid.layers.fc(...) + import paddle.fluid as fluid + main_program = fluid.Program() + startup_program = fluid.Program() + with fluid.program_guard(main_program, startup_program): + data = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + hidden = fluid.layers.fc(input=data, size=10, act='relu') 需要注意的是,如果用户不需要构建自己的启动程序或者主程序,一个临时的program将会发挥作用。 **代码示例** -.. code-block:: python +.. code-block:: python - import paddle.fluid as fluid - main_program = fluid.Program() - # 如果您不需要关心startup program,传入一个临时值即可 - with fluid.program_guard(main_program, fluid.Program()): - data = ... + import paddle.fluid as fluid + main_program = fluid.Program() + # 如果您不需要关心startup program,传入一个临时值即可 + with fluid.program_guard(main_program, fluid.Program()): + data = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') 参数: - - **main_program** (Program) – “with”语句中将使用的新的main program。 - - **startup_program** (Program) – “with”语句中将使用的新的startup program。若传入 ``None`` 则不改变当前的启动程序。 + - **main_program** (Program) – “with”语句中将使用的新的main program。 + - **startup_program** (Program) – “with”语句中将使用的新的startup program。若传入 ``None`` 则不改变当前的启动程序。 @@ -1636,6 +2506,19 @@ release_memory 返回: None +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + # 搭建网络 + # ... + + # 已弃用的API + fluid.release_memory(fluid.default_main_program()) + + .. _cn_api_fluid_scope_guard: @@ -1649,21 +2532,19 @@ scope_guard 修改全局/默认作用域(scope), 运行时中的所有变量都将分配给新的scope。 参数: - - **scope** - 新的全局/默认 scope。 + - **scope** - 新的全局/默认 scope。 **代码示例** -.. code-block:: python - - import paddle.fluid as fluid - - new_scope = fluid.Scope() - with fluid.scope_guard(new_scope): - ... - - - +.. code-block:: python + import numpy + + new_scope = fluid.Scope() + with fluid.scope_guard(new_scope): + fluid.global_scope().var("data").get_tensor().set(numpy.ones((2, 2)), fluid.CPUPlace()) + numpy.array(new_scope.find_var("data").get_tensor()) + @@ -1696,24 +2577,33 @@ WeightNormParamAttr 权重归一化。权重归一化是将权重向量的长度与其方向解耦。`Weight Normalization: A Simple Reparameterization to Accelerate Training of Deep Neural Networks `_ 这篇paper中讨论了权重归一化的实现 参数: - - **dim** (list) - 参数的名称。默认None。 - - **name** (str) - 参数的名称。默认None。 - - **initializer** (initializer) - 初始化参数的方法。默认None。 - - **learning_rate** (float) - 学习率。优化时学习速率 :math:`global\_lr∗parameter\_lr∗scheduler\_factor` 。默认1.0。 - - **regularizer** (WeightDecayRegularizer) - 正则化因子。默认None。 - - **trainable** (bool) - 参数是否可训练。默认True。 - - **gradient_clip** (BaseGradientClipAttr) - 梯度下降裁剪(Gradient Clipping)的方法。默认None。 - - **do_model_average** (bool) - 参数是否应该model average。默认False。 + - **dim** (list) - 参数的名称。默认None。 + - **name** (str) - 参数的名称。默认None。 + - **initializer** (initializer) - 初始化参数的方法。默认None。 + - **learning_rate** (float) - 学习率。优化时学习速率 :math:`global\_lr∗parameter\_lr∗scheduler\_factor` 。默认1.0。 + - **regularizer** (WeightDecayRegularizer) - 正则化因子。默认None。 + - **trainable** (bool) - 参数是否可训练。默认True。 + - **gradient_clip** (BaseGradientClipAttr) - 梯度下降裁剪(Gradient Clipping)的方法。默认None。 + - **do_model_average** (bool) - 参数是否应该model average。默认False。 返回: empty program **代码示例** -.. code-block:: python +.. code-block:: python + + import paddle.fluid as fluid + data = fluid.layers.data(name="data", shape=[3, 32, 32], dtype="float32") + fc = fluid.layers.fc(input=data, + size=1000, + param_attr=fluid.WeightNormParamAttr( + dim=None, + name='weight_norm_param')) + + + + + + + - data = fluid.layers.data(name="data", shape=[3, 32, 32], dtype="float32") - fc = fluid.layers.fc(input=data, - size=1000, - param_attr=WeightNormParamAttr( - dim=None, - name='weight_norm_param')) diff --git a/doc/fluid/api_cn/initializer_cn.rst b/doc/fluid/api_cn/initializer_cn.rst index ac47215d7..214221786 100644 --- a/doc/fluid/api_cn/initializer_cn.rst +++ b/doc/fluid/api_cn/initializer_cn.rst @@ -27,14 +27,19 @@ BilinearInitializer .. code-block:: python factor = 2 - w_attr = ParamAttr(learning_rate=0., regularizer=L2Decay(0.), - initializer=Bilinear()) + C = 2 + w_attr = fluid.initializer.ParamAttr( + learning_rate=0., + regularizer=fluid.regularizer.L2Decay(0.), + initializer=fluid.initializer.Bilinear()) + x = fluid.layers.data(name="data", shape=[3, 32, 32], + dtype="float32") conv_up = fluid.layers.conv2d_transpose( - input, + input=x, num_filters=C, output_size=None, filter_size=2 * factor - factor % 2, - padding=ceil((factor - 1) / 2.), + padding=int(math.ceil((factor - 1) / 2.)), stride=factor, groups=C, param_attr=w_attr, @@ -72,6 +77,7 @@ ConstantInitializer .. code-block:: python + x = fluid.layers.data(name="data", shape=[32, 32], dtype="float32") fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.Constant(value=2.0)) @@ -98,8 +104,8 @@ force_init_on_cpu .. code-block:: python - if force_init_on_cpu(): - create_op('force_cpu': force_init_on_cpu()) + if fluid.initializer.force_init_on_cpu(): + step = fluid.layers.create_global_var(shape=[2,3], value=1.0, dtype='float32') @@ -124,8 +130,8 @@ init_on_cpu .. code-block:: python - with init_on_cpu(): - step = fluid.layers.create_global_var() + with fluid.initializer.init_on_cpu(): + step = fluid.layers.create_global_var(shape=[2,3], value=1.0, dtype='float32') @@ -156,7 +162,7 @@ MSRAInitializer .. math:: - x = \sqrt{\frac{6.0}{fan\_in}} + x = \sqrt{\frac{6.0}{fan\_in}} 在正态分布中,均值为0,标准差为: @@ -177,9 +183,8 @@ MSRAInitializer .. code-block:: python - fc = fluid.layers.fc( - input=queries, size=10, - param_attr=fluid.initializer.MSRA(uniform=False)) + x = fluid.layers.data(name="data", shape=[32, 32], dtype="float32") + fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.MSRA(uniform=False)) @@ -214,6 +219,7 @@ NormalInitializer .. code-block:: python + x = fluid.layers.data(name="data", shape=[32, 32], dtype="float32") fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.Normal(loc=0.0, scale=2.0) @@ -234,6 +240,7 @@ NumpyArrayInitializer .. code-block:: python + x = fluid.layers.data(name="x", shape=[5], dtype='float32') fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.NumpyArrayInitializer(numpy.array([1,2]))) @@ -266,6 +273,8 @@ Random Truncated Normal(高斯)分布初始化器 .. code-block:: python + import paddle.fluid as fluid + x = fluid.layers.data(name='x', shape=[1], dtype='float32') fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.TruncatedNormal(loc=0.0, scale=2.0)) @@ -305,7 +314,9 @@ UniformInitializer **代码示例** .. code-block:: python - + + import paddle.fluid as fluid + x = fluid.layers.data(name='x', shape=[1], dtype='float32') fc = fluid.layers.fc(input=x, size=10, param_attr=fluid.initializer.Uniform(low=-0.5, high=0.5)) @@ -368,6 +379,8 @@ XavierInitializer .. code-block:: python + import paddle.fluid as fluid + queries = fluid.layers.data(name='x', shape=[1], dtype='float32') fc = fluid.layers.fc( input=queries, size=10, param_attr=fluid.initializer.Xavier(uniform=False)) diff --git a/doc/fluid/api_cn/io_cn.rst b/doc/fluid/api_cn/io_cn.rst index 5d162deba..6b1092aba 100644 --- a/doc/fluid/api_cn/io_cn.rst +++ b/doc/fluid/api_cn/io_cn.rst @@ -11,14 +11,14 @@ load_inference_model .. py:function:: paddle.fluid.io.load_inference_model(dirname, executor, model_filename=None, params_filename=None, pserver_endpoints=None) -从指定目录中加载预测模型(inference model)。 +从指定目录中加载预测模型(inference model)。通过这个API,您可以获得模型结构(预测程序)和模型参数。如果您只想下载预训练后的模型的参数,请使用load_params API。更多细节请参考 ``模型/变量的保存、载入与增量训练`` 。 参数: - **dirname** (str) – model的路径 - **executor** (Executor) – 运行 inference model的 ``executor`` - **model_filename** (str|None) – 存储着预测 Program 的文件名称。如果设置为None,将使用默认的文件名为: ``__model__`` - **params_filename** (str|None) – 加载所有相关参数的文件名称。如果设置为None,则参数将保存在单独的文件中。 - - **pserver_endpoints** (list|None) – 只有在分布式预测时需要用到。 当在训练时使用分布式 look up table , 需要这个参数. 该参数是 pserver endpoints 的列表 + - **pserver_endpoints** (list|None) – 只有在分布式预测时需要用到。 当在训练时使用分布式 look up table , 需要这个参数. 该参数是 pserver endpoints 的列表 返回: 这个函数的返回有三个元素的元组(Program,feed_target_names, fetch_targets)。Program 是一个 ``Program`` ,它是预测 ``Program``。 ``feed_target_names`` 是一个str列表,它包含需要在预测 ``Program`` 中提供数据的变量的名称。``fetch_targets`` 是一个 ``Variable`` 列表,从中我们可以得到推断结果。 @@ -27,19 +27,41 @@ load_inference_model 抛出异常: - ``ValueError`` – 如果 ``dirname`` 非法 -.. code-block:: python - - exe = fluid.Executor(fluid.CPUPlace()) - path = "./infer_model" - endpoints = ["127.0.0.1:2023","127.0.0.1:2024"] - [inference_program, feed_target_names, fetch_targets] = - fluid.io.load_inference_model(dirname=path, executor=exe) - results = exe.run(inference_program, +.. code-block:: python + + import paddle.fluid as fluid + import numpy as np + main_prog = fluid.Program() + startup_prog = fluid.Program() + with fluid.program_guard(main_prog, startup_prog): + data = fluid.layers.data(name="img", shape=[64, 784], append_batch_size=False) + w = fluid.layers.create_parameter(shape=[784, 200], dtype='float32') + b = fluid.layers.create_parameter(shape=[200], dtype='float32') + hidden_w = fluid.layers.matmul(x=data, y=w) + hidden_b = fluid.layers.elementwise_add(hidden_w, b) + place = fluid.CPUPlace() + exe = fluid.Executor(place) + exe.run(startup_prog) + path = "./infer_model" + fluid.io.save_inference_model(dirname=path, feeded_var_names=['img'],target_vars=[hidden_b], executor=exe, main_program=main_prog) + tensor_img = np.array(np.random.random((1, 64, 784)), dtype=np.float32) + [inference_program, feed_target_names, fetch_targets] = (fluid.io.load_inference_model(dirname=path, executor=exe)) + + results = exe.run(inference_program, feed={feed_target_names[0]: tensor_img}, fetch_list=fetch_targets) - # 在这个示例中,inference program 保存在 ./infer_model/__model__”中 - # 参数保存在./infer_mode 单独的若干文件中 - # 加载 inference program 后, executor 使用 fetch_targets 和 feed_target_names 执行Program, 得到预测结果 + + # endpoints是pserver服务器终端列表,下面仅为一个样例 + endpoints = ["127.0.0.1:2023","127.0.0.1:2024"] + # 如果需要查询表格,我们可以使用: + [dist_inference_program, dist_feed_target_names, dist_fetch_targets] = ( + fluid.io.load_inference_model(dirname=path, + executor=exe, + pserver_endpoints=endpoints)) + + # 在这个示例中,inference program 保存在“ ./infer_model/__model__”中 + # 参数保存在“./infer_mode ”单独的若干文件中 + # 加载 inference program 后, executor 使用 fetch_targets 和 feed_target_names 执行Program,得到预测结果 @@ -60,17 +82,19 @@ load_params 注意:有些变量不是参数,但它们对于训练是必要的。因此,调用 ``save_params()`` 和 ``load_params()`` 来保存和加载参数是不够的,可以使用 ``save_persistables()`` 和 ``load_persistables()`` 代替这两个函数。 +如果您想下载预训练后的模型结构和参数用于预测,请使用load_inference_model API。更多细节请参考 :ref:`api_guide_model_save_reader`。 + 参数: - - **executor** (Executor) – 加载变量的 executor - - **dirname** (str) – 目录路径 - - **main_program** (Program|None) – 需要加载变量的 Program。如果为 None,则使用 default_main_Program 。默认值: None - - **filename** (str|None) – 保存变量的文件。如果想分开保存变量,设置 filename=None. 默认值: None + - **executor** (Executor) – 加载变量的 executor + - **dirname** (str) – 目录路径 + - **main_program** (Program|None) – 需要加载变量的 Program。如果为 None,则使用 default_main_Program 。默认值: None + - **filename** (str|None) – 保存变量的文件。如果想分开保存变量,设置 filename=None. 默认值: None 返回: None **代码示例** -.. code-block:: python +.. code-block:: python exe = fluid.Executor(fluid.CPUPlace()) param_path = "./my_paddle_model" @@ -105,7 +129,7 @@ load_persistables **代码示例** -.. code-block:: python +.. code-block:: python exe = fluid.Executor(fluid.CPUPlace()) param_path = "./my_paddle_model" @@ -147,29 +171,41 @@ load_vars **代码示例** -.. code-block:: python +.. code-block:: python - exe = fluid.Executor(fluid.CPUPlace()) + import paddle.fluid as fluid + main_prog = fluid.Program() + startup_prog = fluid.Program() + with fluid.program_guard(main_prog, startup_prog): + data = fluid.layers.data(name="img", shape=[64, 784], append_batch_size=False) + w = fluid.layers.create_parameter(shape=[784, 200], dtype='float32', name='fc_w') + b = fluid.layers.create_parameter(shape=[200], dtype='float32', name='fc_b') + hidden_w = fluid.layers.matmul(x=data, y=w) + hidden_b = fluid.layers.elementwise_add(hidden_w, b) + place = fluid.CPUPlace() + exe = fluid.Executor(place) + exe.run(startup_prog) + param_path = "./my_paddle_model" # 第一种使用方式 使用 main_program 指定变量 def name_has_fc(var): res = "fc" in var.name return res - - prog = fluid.default_main_program() - fluid.io.load_vars(executor=exe, dirname=path, main_program=prog, - vars=None, predicate=name_has_fc) + fluid.io.save_vars(executor=exe, dirname=param_path, main_program=main_prog, vars=None, predicate=name_has_fc) + fluid.io.load_vars(executor=exe, dirname=param_path, main_program=main_prog, vars=None, predicate=name_has_fc) #加载所有`main_program`中变量名包含 ‘fc’ 的变量 #并且此前所有变量应该保存在不同文件中 - - #用法2:使用 `vars` 列表来指明变量 - var_list = [var_a, var_b, var_c] + #用法2:使用 `vars` 来使变量具体化 + path = "./my_paddle_vars" + var_list = [w, b] + fluid.io.save_vars(executor=exe, dirname=path, vars=var_list, + filename="vars_file") fluid.io.load_vars(executor=exe, dirname=path, vars=var_list, filename="vars_file") - # 加载 var_a , var_b , var_c .它们此前应被保存在同一文件中 - # 文件名为 'var_file' ,路径为 "./my_paddle_model". + # 加载w和b,它们此前应被保存在同一名为'var_file'的文件中 + # 该文件所在路径为 "./my_paddle_model" @@ -178,16 +214,17 @@ load_vars PyReader ------------------------------- -.. py:class:: paddle.fluid.io.PyReader(feed_list, capacity, use_double_buffer=True, iterable=False) +.. py:class:: paddle.fluid.io.PyReader(feed_list=None, capacity=None, use_double_buffer=True, iterable=True, return_list=False) 在python中为数据输入创建一个reader对象。将使用python线程预取数据,并将其异步插入队列。当调用Executor.run(…)时,将自动提取队列中的数据。 参数: - - **feed_list** (list(Variable)|tuple(Variable)) – feed变量列表,由``fluid.layers.data()``创建。 + - **feed_list** (list(Variable)|tuple(Variable)) – feed变量列表,由 ``fluid.layers.data()`` 创建。在可迭代模式下它可以被设置为None。 - **capacity** (int) – 在Pyreader对象中维护的队列的容量。 - - **use_double_buffer** (bool) – 是否使用``double_buffer_reader ``来加速数据输入。 + - **use_double_buffer** (bool) – 是否使用 ``double_buffer_reader`` 来加速数据输入。 - **iterable** (bool) – 被创建的reader对象是否可迭代。 + - **eturn_list** (bool) – 是否以list的形式将返回值 返回: 被创建的reader对象 @@ -198,73 +235,220 @@ PyReader 1.如果iterable=False,则创建的Pyreader对象几乎与 ``fluid.layers.py_reader()`` 相同。算子将被插入program中。用户应该在每个epoch之前调用start(),并在epoch结束时捕获 ``Executor.run()`` 抛出的 ``fluid.core.EOFException `` 。一旦捕获到异常,用户应该调用reset()手动重置reader。 -.. code-block:: python +.. code-block:: python + + EPOCH_NUM = 3 + ITER_NUM = 5 + BATCH_SIZE = 3 - image = fluid.layers.data( - name='image', shape=[784], dtype='float32') - label = fluid.layers.data( - name='label', shape=[1], dtype='int64') + def reader_creator_random_image_and_label(height, width): + def reader(): + for i in range(ITER_NUM): + fake_image = np.random.uniform(low=0, + high=255, + size=[height, width]) + fake_label = np.ones([1]) + yield fake_image, fake_label + return reader + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') reader = fluid.io.PyReader(feed_list=[image, label], - capacity=4, iterable=False) - reader.decorate_sample_list_generator(user_defined_reader) - ... # definition of network is omitted - executor.run(fluid.default_main_program()) - for _ in range(EPOCH_NUM): + capacity=4, + iterable=False) + + user_defined_reader = reader_creator_random_image_and_label(784, 784) + reader.decorate_sample_list_generator( + paddle.batch(user_defined_reader, batch_size=BATCH_SIZE)) + # 此处省略网络定义 + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_startup_program()) + for i in range(EPOCH_NUM): reader.start() while True: - try: - executor.run(feed=None, ...) - except fluid.core.EOFException: - reader.reset() - break + try: + executor.run(feed=None) + except fluid.core.EOFException: + reader.reset() + break -2.如果iterable=True,则创建的Pyreader对象与程序分离。程序中不会插入任何算子。在本例中,创建的reader是一个python生成器,它是可迭代的。用户应将从Pyreader对象生成的数据输入 ``Executor.run(feed=...)`` +2.如果iterable=True,则创建的Pyreader对象与程序分离。程序中不会插入任何算子。在本例中,创建的reader是一个python生成器,它是不可迭代的。用户应将从Pyreader对象生成的数据输入 ``Executor.run(feed=...)`` 。 -.. code-block:: python +.. code-block:: python - image = fluid.layers.data( - name='image', shape=[784], dtype='float32') - label = fluid.layers.data( - name='label', shape=[1], dtype='int64') + EPOCH_NUM = 3 + ITER_NUM = 5 + BATCH_SIZE = 10 - reader = fluid.io.PyReader(feed_list=[image, label], - capacity=4, iterable=True) - reader.decorate_sample_list_generator(user_defined_reader, - places=fluid.cuda_places()) - ... # definition of network is omitted - executor.run(fluid.default_main_program()) - for _ in range(EPOCH_NUM): - for data in reader(): - executor.run(feed=data, ...) + def reader_creator_random_image(height, width): + def reader(): + for i in range(ITER_NUM): + yield np.random.uniform(low=0, high=255, size=[height, width]), + return reader + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + reader = fluid.io.PyReader(feed_list=[image], capacity=4, iterable=True, return_list=False) + + user_defined_reader = reader_creator_random_image(784, 784) + reader.decorate_sample_list_generator( + paddle.batch(user_defined_reader, batch_size=BATCH_SIZE), + fluid.core.CUDAPlace(0)) + # 此处省略网络定义 + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_main_program()) + + for _ in range(EPOCH_NUM): + for data in reader(): + executor.run(feed=data) + +3. return_list=True,返回值将用list表示而非dict + +.. code-block:: python + + import paddle + import paddle.fluid as fluid + import numpy as np + + EPOCH_NUM = 3 + ITER_NUM = 5 + BATCH_SIZE = 10 -.. py:function:: start() + def reader_creator_random_image(height, width): + def reader(): + for i in range(ITER_NUM): + yield np.random.uniform(low=0, high=255, size=[height, width]), + return reader + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + reader = fluid.io.PyReader(feed_list=[image], capacity=4, iterable=True, return_list=True) + + user_defined_reader = reader_creator_random_image(784, 784) + reader.decorate_sample_list_generator( + paddle.batch(user_defined_reader, batch_size=BATCH_SIZE), + fluid.core.CPUPlace()) + # 此处省略网络定义 + executor = fluid.Executor(fluid.core.CPUPlace()) + executor.run(fluid.default_main_program()) + + for _ in range(EPOCH_NUM): + for data in reader(): + executor.run(feed={"image": data[0]}) + + + +.. py:method:: start() 启动数据输入线程。只能在reader对象不可迭代时调用。 -.. py:function:: reset() +**代码示例** -当 ``fluid.core.EOFException`` 提升时重置reader对象。只能在reader对象不可迭代时调用。 +.. code-block:: python + + BATCH_SIZE = 10 + + def generator(): + for i in range(5): + yield np.random.uniform(low=0, high=255, size=[784, 784]), + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + reader = fluid.io.PyReader(feed_list=[image], capacity=4, iterable=False) + reader.decorate_sample_list_generator( + paddle.batch(generator, batch_size=BATCH_SIZE)) + + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_startup_program()) + for i in range(3): + reader.start() + while True: + try: + executor.run(feed=None) + except fluid.core.EOFException: + reader.reset() + break + +.. py:method:: reset() + +当 ``fluid.core.EOFException`` 抛出时重置reader对象。只能在reader对象不可迭代时调用。 -.. py:function:: decorate_sample_generator(sample_generator, batch_size, drop_last=True, places=None) +**代码示例** + +.. code-block:: python + + BATCH_SIZE = 10 + + def generator(): + for i in range(5): + yield np.random.uniform(low=0, high=255, size=[784, 784]), + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + reader = fluid.io.PyReader(feed_list=[image], capacity=4, iterable=False) + reader.decorate_sample_list_generator( + paddle.batch(generator, batch_size=BATCH_SIZE)) + + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_startup_program()) + for i in range(3): + reader.start() + while True: + try: + executor.run(feed=None) + except fluid.core.EOFException: + reader.reset() + break + +.. py:method:: decorate_sample_generator(sample_generator, batch_size, drop_last=True, places=None) 设置Pyreader对象的数据源。 -提供的 ``sample_generator `` 应该是一个python生成器,它生成每个示例的numpy.ndarray类型的数据。 +提供的 ``sample_generator`` 应该是一个python生成器,它生成的数据类型应为list(numpy.ndarray)。 当Pyreader对象不可迭代时,必须设置 ``places`` 。 如果所有的输入都没有LOD,这个方法比 ``decorate_sample_list_generator(paddle.batch(sample_generator, ...))`` 更快。 参数: - - **sample_generator** (generator) – 返回numpy.ndarray类型样本数据的Python生成器 + - **sample_generator** (generator) – Python生成器,yield 类型为list(numpy.ndarray) - **batch_size** (int) – batch size,必须大于0 - **drop_last** (bool) – 当样本数小于batch数量时,是否删除最后一个batch - **places** (None|list(CUDAPlace)|list(CPUPlace)) – 位置列表。当PyReader可迭代时必须被提供 +**代码示例** -.. py:function:: decorate_sample_list_generator(reader, places=None) +.. code-block:: python + + EPOCH_NUM = 3 + ITER_NUM = 15 + BATCH_SIZE = 3 + + def random_image_and_label_generator(height, width): + def generator(): + for i in range(ITER_NUM): + fake_image = np.random.uniform(low=0, + high=255, + size=[height, width]) + fake_label = np.array([1]) + yield fake_image, fake_label + return generator + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int32') + reader = fluid.io.PyReader(feed_list=[image, label], capacity=4, iterable=True) + + user_defined_generator = random_image_and_label_generator(784, 784) + reader.decorate_sample_generator(user_defined_generator, + batch_size=BATCH_SIZE, + places=[fluid.CUDAPlace(0)]) + # 省略了网络的定义 + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_main_program()) + + for _ in range(EPOCH_NUM): + for data in reader(): + executor.run(feed=data) + +.. py:method:: decorate_sample_list_generator(reader, places=None) 设置Pyreader对象的数据源。 @@ -276,8 +460,41 @@ PyReader - **reader** (generator) – 返回列表(numpy.ndarray)类型的批处理数据的Python生成器 - **places** (None|list(CUDAPlace)|list(CPUPlace)) – 位置列表。当PyReader可迭代时必须被提供 +**代码示例** -.. py:function:: decorate_batch_generator(reader, places=None) +.. code-block:: python + + EPOCH_NUM = 3 + ITER_NUM = 15 + BATCH_SIZE = 3 + + def random_image_and_label_generator(height, width): + def generator(): + for i in range(ITER_NUM): + fake_image = np.random.uniform(low=0, + high=255, + size=[height, width]) + fake_label = np.ones([1]) + yield fake_image, fake_label + return generator + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int32') + reader = fluid.io.PyReader(feed_list=[image, label], capacity=4, iterable=True) + + user_defined_generator = random_image_and_label_generator(784, 784) + reader.decorate_sample_list_generator( + paddle.batch(user_defined_generator, batch_size=BATCH_SIZE), + fluid.core.CUDAPlace(0)) + # 省略了网络的定义 + executor = fluid.Executor(fluid.core.CUDAPlace(0)) + executor.run(fluid.default_main_program()) + + for _ in range(EPOCH_NUM): + for data in reader(): + executor.run(feed=data) + +.. py:method:: decorate_batch_generator(reader, places=None) 设置Pyreader对象的数据源。 @@ -289,18 +506,54 @@ PyReader - **reader** (generator) – 返回LoDTensor类型的批处理数据的Python生成器 - **places** (None|list(CUDAPlace)|list(CPUPlace)) – 位置列表。当PyReader可迭代时必须被提供 +**代码示例** + +.. code-block:: python + + EPOCH_NUM = 3 + ITER_NUM = 15 + BATCH_SIZE = 3 + + def random_image_and_label_generator(height, width): + def generator(): + for i in range(ITER_NUM): + batch_image = np.random.uniform(low=0, + high=255, + size=[BATCH_SIZE, height, width]) + batch_label = np.ones([BATCH_SIZE, 1]) + yield batch_image, batch_label + return generator + + image = fluid.layers.data(name='image', shape=[784, 784], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int32') + reader = fluid.io.PyReader(feed_list=[image, label], capacity=4, iterable=True) + + user_defined_generator = random_image_and_label_generator(784, 784) + reader.decorate_batch_generator(user_defined_generator, fluid.CUDAPlace(0)) + # 省略了网络的定义 + executor = fluid.Executor(fluid.CUDAPlace(0)) + executor.run(fluid.default_main_program()) + + for _ in range(EPOCH_NUM): + for data in reader(): + executor.run(feed=data) + + .. _cn_api_fluid_io_save_inference_model: save_inference_model ------------------------------- -.. py:function:: paddle.fluid.io.save_inference_model(dirname, feeded_var_names, target_vars, executor, main_program=None, model_filename=None, params_filename=None, export_for_deployment=True) +.. py:function:: paddle.fluid.io.save_inference_model(dirname, feeded_var_names, target_vars, executor, main_program=None, model_filename=None, params_filename=None, export_for_deployment=True, program_only=False) 修改指定的 ``main_program`` ,构建一个专门用于预测的 ``Program``,然后 ``executor`` 把它和所有相关参数保存到 ``dirname`` 中。 ``dirname`` 用于指定保存变量的目录。如果变量保存在指定目录的若干文件中,设置文件名 None; 如果所有变量保存在一个文件中,请使用filename来指定它。 +如果您仅想保存您训练好的模型的参数,请使用save_params API。更多细节请参考 :ref:`api_guide_model_save_reader` 。 + + 参数: - **dirname** (str) – 保存预测model的路径 - **feeded_var_names** (list[str]) – 预测(inference)需要 feed 的数据 @@ -310,6 +563,7 @@ save_inference_model - **model_filename** (str|None) – 保存预测Program 的文件名称。如果设置为None,将使用默认的文件名为: ``__model__`` - **params_filename** (str|None) – 保存所有相关参数的文件名称。如果设置为None,则参数将保存在单独的文件中。 - **export_for_deployment** (bool) – 如果为真,Program将被修改为只支持直接预测部署的Program。否则,将存储更多的信息,方便优化和再训练。目前只支持True。 + - **program_only** (bool) – 如果为真,将只保存预测程序,而不保存程序的参数。 返回: 获取的变量名列表 @@ -321,16 +575,32 @@ save_inference_model **代码示例** -.. code-block:: python +.. code-block:: python + + import paddle.fluid as fluid - exe = fluid.Executor(fluid.CPUPlace()) path = "./infer_model" - fluid.io.save_inference_model(dirname=path, feeded_var_names=['img'], - target_vars=[predict_var], executor=exe) - # 在这个示例中,函数将修改默认的主程序让它适合于推断‘predict_var’。修改的 - # 预测Program 将被保存在 ./infer_model/__model__”中。 - # 和参数将保存在文件夹下的单独文件中 ./infer_mode + # 用户定义网络,此处以softmax回归为例 + image = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') + feeder = fluid.DataFeeder(feed_list=[image, label], place=fluid.CPUPlace()) + predict = fluid.layers.fc(input=image, size=10, act='softmax') + + loss = fluid.layers.cross_entropy(input=predict, label=label) + avg_loss = fluid.layers.mean(loss) + + exe = fluid.Executor(fluid.CPUPlace()) + exe.run(fluid.default_startup_program()) + + # 数据输入及训练过程 + + # 保存预测模型。注意我们不在这个示例中保存标签和损失。 + fluid.io.save_inference_model(dirname=path, feeded_var_names=['img'], target_vars=[predict], executor=exe) + + # 在这个示例中,函数将修改默认的主程序让它适合于预测‘predict_var’ + # 修改的预测Program 将被保存在 ./infer_model/__model__”中。 + # 参数将保存在文件夹下的单独文件中 ./infer_mode @@ -350,7 +620,7 @@ save_params ``dirname`` 用于指定保存变量的目标目录。如果想将变量保存到多个独立文件中,设置 ``filename`` 为 None; 如果想将所有变量保存在单个文件中,请使用 ``filename`` 来指定该文件的命名。 -注意:有些变量不是参数,但它们对于训练是必要的。因此,调用 ``save_params()`` 和 ``load_params()`` 来保存和加载参数是不够的,可以使用 ``save_persistables()`` 和 ``load_persistables()`` 代替这两个函数。 +注意:有些变量不是参数,但它们对于训练是必要的。因此,调用 ``save_params()`` 和 ``load_params()`` 来保存和加载参数是不够的,可以使用 ``save_persistables()`` 和 ``load_persistables()`` 代替这两个函数。如果您想要储存您的模型用于预测,请使用save_inference_model API。更多细节请参考 :ref:`api_guide_model_save_reader`。 参数: @@ -364,7 +634,7 @@ save_params **代码示例** -.. code-block:: python +.. code-block:: python exe = fluid.Executor(fluid.CPUPlace()) param_path = "./my_paddle_model" @@ -401,8 +671,10 @@ save_persistables **代码示例** -.. code-block:: python +.. code-block:: python + import paddle.fluid as fluid + exe = fluid.Executor(fluid.CPUPlace()) param_path = "./my_paddle_model" prog = fluid.default_main_program() @@ -445,9 +717,21 @@ save_vars **代码示例** -.. code-block:: python - - exe = fluid.Executor(fluid.CPUPlace()) +.. code-block:: python + + import paddle.fluid as fluid + main_prog = fluid.Program() + startup_prog = fluid.Program() + with fluid.program_guard(main_prog, startup_prog): + data = fluid.layers.data(name="img", shape=[64, 784], append_batch_size=False) + w = fluid.layers.create_parameter(shape=[784, 200], dtype='float32', name='fc_w') + b = fluid.layers.create_parameter(shape=[200], dtype='float32', name='fc_b') + hidden_w = fluid.layers.matmul(x=data, y=w) + hidden_b = fluid.layers.elementwise_add(hidden_w, b) + place = fluid.CPUPlace() + exe = fluid.Executor(place) + exe.run(startup_prog) + param_path = "./my_paddle_model" # 第一种用法:用main_program来指定变量。 @@ -455,19 +739,18 @@ save_vars res = "fc" in var.name return res - prog = fluid.default_main_program() - fluid.io.save_vars(executor=exe, dirname=path, main_program=prog, - vars=None, predicate = name_has_fc) + fluid.io.save_vars(executor=exe, dirname=param_path, main_program=main_prog, vars=None, predicate = name_has_fc) # 将main_program中名中包含“fc”的的所有变量保存。 # 变量将分开保存。 # 第二种用法: 用vars来指定变量。 - var_list = [var_a, var_b, var_c] + var_list = [w, b] + path = "./my_paddle_vars" fluid.io.save_vars(executor=exe, dirname=path, vars=var_list, filename="vars_file") - # var_a,var_b和var_c将被保存。 他们将使用同一文件,名为“var_file”,保存在路径“./my_paddle_model”下。 - + # var_a,var_b和var_c将被保存。 + #他们将使用同一文件,名为“var_file”,保存在路径“./my_paddle_vars”下。 diff --git a/doc/fluid/api_cn/layers_cn.rst b/doc/fluid/api_cn/layers_cn.rst index e0424e677..645a24ba7 100644 --- a/doc/fluid/api_cn/layers_cn.rst +++ b/doc/fluid/api_cn/layers_cn.rst @@ -35,6 +35,7 @@ array_length .. code-block:: python + import paddle.fluid as fluid tmp = fluid.layers.zeros(shape=[10], dtype='int32') i = fluid.layers.fill_constant(shape=[1], dtype='int64', value=10) arr = fluid.layers.array_write(tmp, i=i) @@ -79,6 +80,7 @@ array_read .. code-block:: python + import paddle.fluid as fluid array = fluid.layers.create_array(dtype='float32') i = fluid.layers.fill_constant(shape=[1],dtype='int64',value=10) item = fluid.layers.array_read(array, i) @@ -107,14 +109,15 @@ array_write - **i** (Variable|list) – 输出结果 ``LOD_TENSOR_ARRAY`` 的下标, 该下标指向输入张量 ``x`` 写入输出数组的位置 - **array** (Variable|list) – 会被输入张量 ``x`` 写入的输出结果 ``LOD_TENSOR_ARRAY`` 。如果该项值为None, 一个新的 ``LOD_TENSOR_ARRAY`` 将会被创建并作为结果返回 -返回: 输入张量 ``x`` 所写入的输出结果 ``LOD_TENSOR_ARRAY`` +返回: 输入张量 ``x`` 所写入的输出结果 ``LOD_TENSOR_ARRAY`` -返回类型: 变量(Variable) +返回类型: 变量(Variable) **代码示例** .. code-block:: python + import paddle.fluid as fluid tmp = fluid.layers.zeros(shape=[10], dtype='int32') i = fluid.layers.fill_constant(shape=[1], dtype='int64', value=10) arr = fluid.layers.array_write(tmp, i=i) @@ -175,27 +178,6 @@ DynamicRNN 必须设置输入lod,请参考 ``lod_tensor`` -**代码示例** - -.. code-block:: python - - import paddle.fluid as fluid - data = fluid.layers.data(name='sentence', dtype='int64', lod_level=1) - embedding = fluid.layers.embedding(input=data, size=[65535, 32], - is_sparse=True) - - drnn = fluid.layers.DynamicRNN() - with drnn.block(): - word = drnn.step_input(embedding) - prev = drnn.memory(shape=[200]) - hidden = fluid.layers.fc(input=[word, prev], size=200, act='relu') - drnn.update_memory(prev, hidden) # set prev to hidden - drnn.output(hidden) - - # last是的最后一时间步,也是编码(encoding)得出的最终结果 - last = fluid.layers.sequence_last_step(drnn()) - - 动态RNN将按照timesteps展开开序列。用户需要在with block中定义如何处理处理每个timestep。 memory用于缓存分段数据。memory的初始值可以是零,也可以是其他变量。 @@ -205,24 +187,72 @@ memory用于缓存分段数据。memory的初始值可以是零,也可以是 .. note:: 目前不支持在DynamicRNN中任何层上配置 is_sparse = True +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + sentence = fluid.layers.data(name='sentence', shape=[1], dtype='int64', lod_level=1) + embedding = fluid.layers.embedding(input=sentence, size=[65536, 32], is_sparse=True) + + drnn = fluid.layers.DynamicRNN() + with drnn.block(): + word = drnn.step_input(embedding) + prev = drnn.memory(shape=[200]) + hidden = fluid.layers.fc(input=[word, prev], size=200, act='relu') + drnn.update_memory(prev, hidden) # set prev to hidden + drnn.output(hidden) + + # 获得上一个timestep的rnn,该值是一个编码后的结果 + rnn_output = drnn() + last = fluid.layers.sequence_last_step(rnn_output) + + .. py:method:: step_input(x, level=0) 将序列标记为动态RNN输入。 参数: - - **x** (Variable) - 输入序列 + - **x** (Variable) - 含lod信息的输入序列 - **level** (int) - 用于拆分步骤的LOD层级,默认值0 返回:当前的输入序列中的timestep。 .. py:method:: static_input(x) -将变量标记为RNN输入。输入不会分散到timestep中。 +将变量标记为RNN输入。输入不会分散到timestep中。为可选项。 参数: - - **x** (Variable) - 输入序列 + - **x** (Variable) - 输入序列 + +返回:可以访问的RNN的输入变量。 + +**代码示例** + +.. code-block:: python + + import paddle.fluid as fluid + + sentence = fluid.layers.data(name='sentence', dtype='float32', shape=[32], lod_level=1) + encoder_proj = fluid.layers.data(name='encoder_proj', dtype='float32', shape=[32], lod_level=1) + decoder_boot = fluid.layers.data(name='boot', dtype='float32', shape=[10], lod_level=1) + + drnn = fluid.layers.DynamicRNN() + with drnn.block(): + current_word = drnn.step_input(sentence) + encoder_word = drnn.static_input(encoder_proj) + hidden_mem = drnn.memory(init=decoder_boot, need_reorder=True) + fc_1 = fluid.layers.fc(input=encoder_word, size=30, bias_attr=False) + fc_2 = fluid.layers.fc(input=current_word, size=30, bias_attr=False) + decoder_inputs = fc_1 + fc_2 + h, _, _ = fluid.layers.gru_unit(input=decoder_inputs, hidden=hidden_mem, size=30) + drnn.update_memory(hidden_mem, h) + out = fluid.layers.fc(input=h, size=10, bias_attr=True, act='softmax') + drnn.output(out) + + rnn_output = drnn() -返回:可以访问的RNN的输入变量,。 .. py:method:: block() @@ -232,54 +262,53 @@ memory用于缓存分段数据。memory的初始值可以是零,也可以是 为动态rnn创建一个memory 变量。 -如果 ``init`` 不是None, ``memory`` 将由这个变量初始化。参数 ``need_reorder`` 用于将memory重新排序作为输入变量。当memory初始化依赖于输入样本时,应该将其设置为true。 +如果 ``init`` 不是None, ``memory`` 将由这个变量初始化。参数 ``need_reorder`` 用于将memory重新排序作为输入变量。当memory初始化依赖于输入样本时,应该将其设置为True。 -**例如** +**代码示例** .. code-block:: python - import paddle.fluid as fluid - sentence = fluid.layers.data( - name='sentence', dtype='float32', shape=[32]) - boot_memory = fluid.layers.data( - name='boot', dtype='float32', shape=[10]) - - drnn = fluid.layers.DynamicRNN() - with drnn.block(): - word = drnn.step_input(sentence) - memory = drnn.memory(init=boot_memory, need_reorder=True) - hidden = fluid.layers.fc( - input=[word, memory], size=10, act='tanh') - drnn.update_memory(ex_mem=memory, new_mem=hidden) - drnn.output(hidden) + import paddle.fluid as fluid + + sentence = fluid.layers.data(name='sentence', shape=[32], dtype='float32', lod_level=1) + boot_memory = fluid.layers.data(name='boot', shape=[10], dtype='float32', lod_level=1) + + drnn = fluid.layers.DynamicRNN() + with drnn.block(): + word = drnn.step_input(sentence) + memory = drnn.memory(init=boot_memory, need_reorder=True) + hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh') + drnn.update_memory(ex_mem=memory, new_mem=hidden) + drnn.output(hidden) - rnn_output = drnn() + rnn_output = drnn() 否则,如果已经设置 ``shape`` 、 ``value`` 、 ``dtype`` ,memory将被 ``value`` 初始化 +**代码示例** + .. code-block:: python - import paddle.fluid as fluid + import paddle.fluid as fluid - sentence = fluid.layers.data( - name='sentence', dtype='float32', shape=[32]) + sentence = fluid.layers.data(name='sentence', dtype='float32', shape=[32], lod_level=1) - drnn = fluid.layers.DynamicRNN() - with drnn.block(): - word = drnn.step_input(sentence) - memory = drnn.memory(shape=[10], dtype='float32', value=0) - hidden = fluid.layers.fc( - input=[word, memory], size=10, act='tanh') - drnn.update_memory(ex_mem=memory, new_mem=hidden) - drnn.output(hidden) - rnn_output = drnn() + drnn = fluid.layers.DynamicRNN() + with drnn.block(): + word = drnn.step_input(sentence) + memory = drnn.memory(shape=[10], dtype='float32', value=0) + hidden = fluid.layers.fc(input=[word, memory], size=10, act='tanh') + drnn.update_memory(ex_mem=memory, new_mem=hidden) + drnn.output(hidden) + + rnn_output = drnn() 参数: - **init** (Variable|None) – 初始化的Variable - - **shape** (list|tuple) – memory shape. 注意形状不包含batch_size + - **shape** (list|tuple) – memory shape,形状不包含batch_size - **value** (float) – 初始化的值 - **need_reorder** (bool) – memory初始化依赖于输入样本时设置为True - **dtype** (str|numpy.dtype) – 初始化memory的数据类型 @@ -292,8 +321,8 @@ memory用于缓存分段数据。memory的初始值可以是零,也可以是 将内存从 ``ex_mem`` 更新到 ``new_mem`` 。注意, ``ex_mem`` 和 ``new_mem`` 的 ``shape`` 和数据类型必须相同。 参数: - - **ex_mem** (memory Variable)- memory 变量(Variable) - - **new_mem** (memory Variable)- RNN块中生成的平坦变量(plain variable) + - **ex_mem** (memory Variable)- memory 变量(Variable) + - **new_mem** (memory Variable)- RNN块中生成的平坦变量(plain variable) 返回:None @@ -307,11 +336,9 @@ memory用于缓存分段数据。memory的初始值可以是零,也可以是 返回:None + - - - - + @@ -339,12 +366,63 @@ equal .. code-block:: python + import paddle.fluid as fluid + label = fluid.layers.data(name="label", shape=[3,10,32,32], dtype="float32") + limit = fluid.layers.data(name="limit", shape=[3,10,32,32], dtype="float32") less = fluid.layers.equal(x=label,y=limit) +.. _cn_api_fluid_layers_greater_equal: + +greater_equal +------------------------------- + +.. py:function:: paddle.fluid.layers.greater_equal(x, y, cond=None) + +该层逐元素地返回 :math:`x >= y` 的逻辑值,和重载算子 `>=` 相同。 + +参数: + - **x** (Variable) - *greater_equal* 的第一个操作数 + - **y** (Variable) - *greater_equal* 的第二个操作数 + - **cond** (Variable|None) - 可选的输出变量,存储 *greater_equal* 的结果 + +返回:存储 *greater_equal* 的输出的张量变量。 + +返回类型:变量(Variable) + +**代码示例**: + +.. code-block:: python + + out = fluid.layers.greater_equal(x=label, y=limit) + + + +.. _cn_api_fluid_layers_greater_than: + +greater_than +------------------------------- + +.. py:function:: paddle.fluid.layers.greater_than(x, y, cond=None) + +该层逐元素地返回 :math:`x > y` 的逻辑值,和重载算子 `>` 相同。 + +参数: + - **x** (Variable) - *greater_than* 的第一个操作数 + - **y** (Variable) - *greater_than* 的第二个操作数 + - **cond** (Variable|None) - 可选的输出变量,存储 *greater_than* 的结果 + +返回:存储 *greater_than* 的输出的张量变量。 + +返回类型:变量(Variable) + +**代码示例**: + +.. code-block:: python + out = fluid.layers.greater_than(x=label, y=limit) @@ -366,8 +444,12 @@ if-else控制流。 .. code-block:: python + import paddle.fluid as fluid + + image = fluid.layers.data(name="X", shape=[2, 5, 5], dtype='float32') + label = fluid.layers.data(name='label', shape=[1], dtype='int64') limit = fluid.layers.fill_constant_batch_size_like( - input=label, dtype='int64', shape=[1], value=5.0) + input=label, dtype='int64', shape=[1], value=5.0) cond = fluid.layers.less_than(x=label, y=limit) ie = fluid.layers.IfElse(cond) with ie.true_block(): @@ -418,6 +500,7 @@ increment .. code-block:: python + import paddle.fluid as fluid data = fluid.layers.data(name='data', shape=[1], dtype='float32', append_batch_size=False) data = fluid.layers.increment(x=data, value=3.0, in_place=True) @@ -455,14 +538,38 @@ is_empty .. code-block:: python + import paddle.fluid as fluid + input = fluid.layers.data(name="input", shape=[4, 32, 32], dtype="float32") res = fluid.layers.is_empty(x=input) # or: - fluid.layers.is_empty(x=input, cond=res) + # fluid.layers.is_empty(x=input, cond=res) + + + + +.. _cn_api_fluid_layers_less_equal: + +less_equal +------------------------------- + +.. py:function:: paddle.fluid.layers.less_equal(x, y, cond=None) + +该层逐元素地返回 :math:`x <= y` 的逻辑值,和重载算子 `<=` 相同。 + +参数: + - **x** (Variable) - *less_equal* 的第一个操作数 + - **y** (Variable) - *less_equal* 的第二个操作数 + - **cond** (Variable|None) - 可选的输出变量,存储 *less_equal* 的结果 +返回:存储 *less_equal* 的输出的张量变量。 +返回类型:变量(Variable) +**代码示例**: +.. code-block:: python + out = fluid.layers.less_equal(x=label, y=limit) @@ -478,12 +585,6 @@ less_than 该函数按元素出现顺序依次在X,Y上操作,并返回 ``Out`` ,它们三个都是n维tensor(张量)。 其中,X、Y可以是任何类型的tensor,Out张量的各个元素可以通过 :math:`Out=X