未验证 提交 c6fa65e1 编写于 作者: C Cheerego 提交者: GitHub

Merge branch 'develop' into release/1.3

...@@ -220,10 +220,8 @@ with fluid.layers.control_flow.Switch() as switch: ...@@ -220,10 +220,8 @@ with fluid.layers.control_flow.Switch() as switch:
关于 Fluid 中 Program 的详细设计思想,可以参考阅读[Fluid设计思想](../../advanced_usage/design_idea/fluid_design_idea.html) 关于 Fluid 中 Program 的详细设计思想,可以参考阅读[Fluid设计思想](../../advanced_usage/design_idea/fluid_design_idea.html)
更多 Fluid 中的控制流,可以参考阅读[API文档](../../api_cn/layers_cn.html#control-flow) 更多 Fluid 中的控制流,可以参考阅读[API文档](../../api_cn/layers_cn.html#control-flow)
## 使用Executor执行Program ## 使用Executor执行Program
Fluid的设计思想类似于高级编程语言C++和JAVA等。程序的执行过程被分为编译和执行两个阶段。 Fluid的设计思想类似于高级编程语言C++和JAVA等。程序的执行过程被分为编译和执行两个阶段。
......
...@@ -4,33 +4,33 @@ ...@@ -4,33 +4,33 @@
使用PyReader读取训练和测试数据 使用PyReader读取训练和测试数据
############################ ############################
Paddle Fluid支持PyReader,实现Python端往C++端导入数据的功能。与 :ref:`user_guide_use_numpy_array_as_train_data` 不同,在使用PyReader时,Python端导入数据的过程和C++端 :code:`Executor::Run()` 读取数据的过程是异步进行的,且能与 :code:`double_buffer_reader` 配合以进一步提高数据读取性能 除Python Reader方法外,我们提供了PyReader。PyReader的性能比 :ref:`user_guide_use_numpy_array_as_train_data` 更好,因为PyReader的数据读取和模型训练过程是异步进行的,且能与 :code:`double_buffer_reader` 配合以进一步提高数据读取性能。此外, :code:`double_buffer_reader` 负责异步完成CPU Tensor到GPU Tensor的转换,一定程度上提升了数据读取效率
创建PyReader对象 创建PyReader对象
################################ ################################
用户创建PyReader对象的方式为: 创建PyReader对象的方式为:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
py_reader = fluid.layers.py_reader(capacity=64, py_reader = fluid.layers.py_reader(capacity=64,
shapes=[(-1,3,224,224), (-1,1)], shapes=[(-1,784), (-1,1)],
dtypes=['float32', 'int64'], dtypes=['float32', 'int64'],
name='py_reader', name='py_reader',
use_double_buffer=True) use_double_buffer=True)
其中,capacity为PyReader对象的缓存区大小;shapes为batch各参量(如图像分类任务中的image和label)的尺寸;dtypes为batch各参量的数据类型;name为PyReader对象的名称;use_double_buffer默认为True,表示使用 :code:`double_buffer_reader` 其中,capacity为PyReader对象的缓存区大小;shapes为batch各参量(如图像分类任务中的image和label)的尺寸;dtypes为batch各参量的数据类型;name为PyReader对象的名称;use_double_buffer默认为True,表示使用 :code:`double_buffer_reader` ,建议开启,可提升数据读取速度
若要创建多个不同的PyReader对象(如训练阶段和测试阶段往往需创建两个不同的PyReader对象),必须给不同的PyReader对象指定不同的name。比如,在同一任务中创建训练阶段和测试阶段的PyReader对象的方式为: 需要注意的是:如果您要创建多个不同PyReader对象(例如训练和预测阶段需创建两个不同的PyReader),则需要必须给不同的PyReader对象指定不同的name。这是因为PaddlePaddle采用不同的变量名区分不同的变量,而且 `Program.clone()` (参见 :ref:`cn_api_fluid_Program_clone` )不能实现PyReader对象的复制。
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
train_py_reader = fluid.layers.py_reader(capacity=64, train_py_reader = fluid.layers.py_reader(capacity=64,
shapes=[(-1,3,224,224), (-1,1)], shapes=[(-1,784), (-1,1)],
dtypes=['float32', 'int64'], dtypes=['float32', 'int64'],
name='train', name='train',
use_double_buffer=True) use_double_buffer=True)
...@@ -41,11 +41,10 @@ Paddle Fluid支持PyReader,实现Python端往C++端导入数据的功能。与 ...@@ -41,11 +41,10 @@ Paddle Fluid支持PyReader,实现Python端往C++端导入数据的功能。与
name='test', name='test',
use_double_buffer=True) use_double_buffer=True)
注意, :code:`Program.clone()` 方法不能实现PyReader对象的复制,因此必须用以上方式创建训练阶段和测试阶段的不同 在使用PyReader时,如果需要共享训练阶段和测试阶段的模型参数,您可以通过 :code:`fluid.unique_name.guard()` 的方式来实现。
PyReader对象 注:Paddle采用变量名区分不同变量,且变量名是根据 :code:`unique_name` 模块中的计数器自动生成的,每生成一个变量名计数值加1。 :code:`fluid.unique_name.guard()` 的作用是重置 :code:`unique_name` 模块中的计数器,保证多次调用 :code:`fluid.unique_name.guard()` 配置网络时对应变量的变量名相同,从而实现参数共享
由于 :code:`Program.clone()` 无法实现PyReader对象的复制,因此用户需通过 :code:`fluid.unique_name.guard()` 下面是一个使用PyReader配置训练阶段和测试阶段网络的例子:
的方式实现训练阶段和测试阶段模型参数的共享,具体方式为:
.. code-block:: python .. code-block:: python
...@@ -53,72 +52,169 @@ PyReader对象。 ...@@ -53,72 +52,169 @@ PyReader对象。
import paddle.fluid as fluid import paddle.fluid as fluid
import paddle.dataset.mnist as mnist import paddle.dataset.mnist as mnist
import numpy
def network(is_train): def network(is_train):
# Create py_reader object and give different names
# when is_train = True and is_train = False
reader = fluid.layers.py_reader( reader = fluid.layers.py_reader(
capacity=10, capacity=10,
shapes=((-1, 784), (-1, 1)), shapes=((-1, 784), (-1, 1)),
dtypes=('float32', 'int64'), dtypes=('float32', 'int64'),
name="train_reader" if is_train else "test_reader", name="train_reader" if is_train else "test_reader",
use_double_buffer=True) use_double_buffer=True)
# Use read_file() method to read out the data from py_reader
img, label = fluid.layers.read_file(reader) img, label = fluid.layers.read_file(reader)
... ...
# Here, we omitted the definition of loss of the model # Here, we omitted the definition of loss of the model
return loss , reader return loss , reader
# Create main program and startup program for training
train_prog = fluid.Program() train_prog = fluid.Program()
train_startup = fluid.Program() train_startup = fluid.Program()
with fluid.program_guard(train_prog, train_startup): with fluid.program_guard(train_prog, train_startup):
# Use fluid.unique_name.guard() to share parameters with test network
with fluid.unique_name.guard(): with fluid.unique_name.guard():
train_loss, train_reader = network(True) train_loss, train_reader = network(True)
adam = fluid.optimizer.Adam(learning_rate=0.01) adam = fluid.optimizer.Adam(learning_rate=0.01)
adam.minimize(train_loss) adam.minimize(train_loss)
# Create main program and startup program for testing
test_prog = fluid.Program() test_prog = fluid.Program()
test_startup = fluid.Program() test_startup = fluid.Program()
with fluid.program_guard(test_prog, test_startup): with fluid.program_guard(test_prog, test_startup):
# Use fluid.unique_name.guard() to share parameters with train network
with fluid.unique_name.guard(): with fluid.unique_name.guard():
test_loss, test_reader = network(False) test_loss, test_reader = network(False)
设置PyReader对象的数据源 设置PyReader对象的数据源
################################ ################################
PyReader对象提供 :code:`decorate_tensor_provider` 和 :code:`decorate_paddle_reader` 方法,它们均接收一个Python生成器 :code:`generator` 对象作为数据源,两个方法的区别在于: PyReader对象通过 :code:`decorate_paddle_reader()` 或 :code:`decorate_tensor_provider()` 方法设置其数据源。 :code:`decorate_paddle_reader()` 和 :code:`decorate_tensor_provider()` 均接收Python生成器 :code:`generator` 作为参数, :code:`generator` 内部每次通过yield的方式生成一个batch的数据。
:code:`decorate_paddle_reader()` 和 :code:`decorate_tensor_provider()` 方法的区别在于:
- :code:`decorate_paddle_reader()` 的 :code:`generator` 应返回Numpy Array类型的数据,而 :code:`decorate_tensor_provider()` 的 :code:`generator` 应返回LoDTensor类型的数据。
- :code:`decorate_tensor_provider()` 要求 :code:`generator` 返回的LoDTensor的数据类型、尺寸必须与配置py_reader时指定的dtypes、shapes参数相同,而 :code:`decorate_paddle_reader()` 不要求数据类型和尺寸的严格一致,其内部会完成数据类型和尺寸的转换。
具体方式为:
.. code-block:: python
import paddle.fluid as fluid
import numpy as np
BATCH_SIZE = 32
# Case 1: Use decorate_paddle_reader() method to set the data source of py_reader
# The generator yields Numpy-typed batched data
def fake_random_numpy_reader():
image = np.random.random(size=(BATCH_SIZE, 784))
label = np.random.random_integers(size=(BATCH_SIZE, 1), low=0, high=9)
yield image, label
py_reader1 = fluid.layers.py_reader(
capacity=10,
shapes=((-1, 784), (-1, 1)),
dtypes=('float32', 'int64'),
name='py_reader1',
use_double_buffer=True)
1. :code:`decorate_tensor_provider` 方法:要求 :code:`generator` 每次产生一个 :code:`list` 或 :code:`tuple` 对象, :code:`list` 或 :code:`tuple` 对象中的每个元素为 :code:`LoDTensor` 类型或Numpy数组类型,且 :code:`LoDTensor` 或Numpy数组的 :code:`shape` 必须与创建PyReader对象时指定的 :code:`shapes` 参数完全一致。 py_reader1.decorate_paddle_reader(fake_random_reader)
2. :code:`decorate_paddle_reader` 方法:要求 :code:`generator` 每次产生一个 :code:`list` 或 :code:`tuple` 对象, :code:`list` 或 :code:`tuple` 对象中的每个元素为Numpy数组类型,但Numpy数组的 :code:`shape` 不必与创建PyReader对象时指定的 :code:`shapes` 参数完全一致, :code:`decorate_paddle_reader` 方法内部会对其进行 :code:`reshape` 操作。 # Case 2: Use decorate_tensor_provider() method to set the data source of py_reader
# The generator yields Tensor-typed batched data
def fake_random_tensor_provider():
image = np.random.random(size=(BATCH_SIZE, 784)).astype('float32')
label = np.random.random_integers(size=(BATCH_SIZE, 1), low=0, high=9).astype('int64')
image_tensor = fluid.LoDTensor()
image_tensor.set(image, fluid.CPUPlace())
label_tensor = fluid.LoDTensor()
label_tensor.set(label, fluid.CPUPlace())
yield image_tensor, label_tensor
py_reader2 = fluid.layers.py_reader(
capacity=10,
shapes=((-1, 784), (-1, 1)),
dtypes=('float32', 'int64'),
name='py_reader2',
use_double_buffer=True)
py_reader2.decorate_tensor_provider(fake_random_tensor_provider)
使用PyReader进行模型训练和测试 使用PyReader进行模型训练和测试
################################ ################################
具体方式为(接上述代码) 使用PyReader进行模型训练和测试的例程如下
.. code-block:: python .. code-block:: python
import paddle
import paddle.fluid as fluid
import paddle.dataset.mnist as mnist
import six
def network(is_train):
# Create py_reader object and give different names
# when is_train = True and is_train = False
reader = fluid.layers.py_reader(
capacity=10,
shapes=((-1, 784), (-1, 1)),
dtypes=('float32', 'int64'),
name="train_reader" if is_train else "test_reader",
use_double_buffer=True)
img, label = fluid.layers.read_file(reader)
...
# Here, we omitted the definition of loss of the model
return loss , reader
# Create main program and startup program for training
train_prog = fluid.Program()
train_startup = fluid.Program()
# Define train network
with fluid.program_guard(train_prog, train_startup):
# Use fluid.unique_name.guard() to share parameters with test network
with fluid.unique_name.guard():
train_loss, train_reader = network(True)
adam = fluid.optimizer.Adam(learning_rate=0.01)
adam.minimize(train_loss)
# Create main program and startup program for testing
test_prog = fluid.Program()
test_startup = fluid.Program()
# Define test network
with fluid.program_guard(test_prog, test_startup):
# Use fluid.unique_name.guard() to share parameters with train network
with fluid.unique_name.guard():
test_loss, test_reader = network(False)
place = fluid.CUDAPlace(0) place = fluid.CUDAPlace(0)
startup_exe = fluid.Executor(place) exe = fluid.Executor(place)
startup_exe.run(train_startup)
startup_exe.run(test_startup)
trainer = fluid.ParallelExecutor( # Run startup program
use_cuda=True, loss_name=train_loss.name, main_program=train_prog) exe.run(train_startup)
exe.run(test_startup)
tester = fluid.ParallelExecutor( # Compile programs
use_cuda=True, share_vars_from=trainer, main_program=test_prog) train_prog = fluid.CompiledProgram(train_prog).with_data_parallel(loss_name=train_loss.name)
test_prog = fluid.CompiledProgram(test_prog).with_data_parallel(share_vars_from=train_prog)
# Set the data source of py_reader using decorate_paddle_reader() method
train_reader.decorate_paddle_reader( train_reader.decorate_paddle_reader(
paddle.reader.shuffle(paddle.batch(mnist.train(), 512), buf_size=8192)) paddle.reader.shuffle(paddle.batch(mnist.train(), 512), buf_size=8192))
test_reader.decorate_paddle_reader(paddle.batch(mnist.test(), 512)) test_reader.decorate_paddle_reader(paddle.batch(mnist.test(), 512))
for epoch_id in xrange(10): for epoch_id in six.moves.range(10):
train_reader.start() train_reader.start()
try: try:
while True: while True:
print 'train_loss', numpy.array( loss = exe.run(program=train_prog, fetch_list=[train_loss])
trainer.run(fetch_list=[train_loss.name])) print 'train_loss', loss
except fluid.core.EOFException: except fluid.core.EOFException:
print 'End of epoch', epoch_id print 'End of epoch', epoch_id
train_reader.reset() train_reader.reset()
...@@ -126,8 +222,8 @@ PyReader对象提供 :code:`decorate_tensor_provider` 和 :code:`decorate_paddle ...@@ -126,8 +222,8 @@ PyReader对象提供 :code:`decorate_tensor_provider` 和 :code:`decorate_paddle
test_reader.start() test_reader.start()
try: try:
while True: while True:
print 'test loss', numpy.array( loss = exe.run(program=test_prog, fetch_list=[test_loss])
tester.run(fetch_list=[test_loss.name])) print 'test loss', loss
except fluid.core.EOFException: except fluid.core.EOFException:
print 'End of testing' print 'End of testing'
test_reader.reset() test_reader.reset()
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册