未验证 提交 91607e08 编写于 作者: D Daniel Yang 提交者: GitHub

this is a docs-restructuing pull-request, test=develop (#1768)

上级 96c7fbb8
...@@ -177,7 +177,7 @@ pip install -r requirements.txt ...@@ -177,7 +177,7 @@ pip install -r requirements.txt
## 提交修改 ## 提交修改
如果您希望修改代码,请在`Paddle`仓库下参考[如何贡献代码](../development/contribute_to_paddle/index_cn.html)执行操作。 如果您希望修改代码,请在`Paddle`仓库下参考[如何贡献代码](../contribute_code/index_cn.html)执行操作。
如果您仅修改文档: 如果您仅修改文档:
...@@ -198,7 +198,7 @@ pip install -r requirements.txt ...@@ -198,7 +198,7 @@ pip install -r requirements.txt
3.在`FluidDoc`仓库下为您的修改提交PR 3.在`FluidDoc`仓库下为您的修改提交PR
提交修改与PR的步骤可以参考[如何贡献代码](../development/contribute_to_paddle/index_cn.html) 提交修改与PR的步骤可以参考[如何贡献代码](../contribute_code/index_cn.html)
## 帮助改进预览工具 ## 帮助改进预览工具
......
...@@ -58,7 +58,7 @@ git clone https://github.com/PaddlePaddle/PaddlePaddle.org.git ...@@ -58,7 +58,7 @@ git clone https://github.com/PaddlePaddle/PaddlePaddle.org.git
cd PaddlePaddle.org/portal cd PaddlePaddle.org/portal
``` ```
Then install requirements. Please make sure that you install with python 2.7.15 or 2.7.16. We recommend you to use Anaconda or virtualenv to create an appropriate virtual environment first. Then install requirements. Please make sure that you install with python 2.7.15 or 2.7.16. We recommend you to use Anaconda or virtualenv to create an appropriate virtual environment first.
Install requirements: Install requirements:
...@@ -85,9 +85,9 @@ If you need to work with documents that depend on the contents of the `book`, `m ...@@ -85,9 +85,9 @@ If you need to work with documents that depend on the contents of the `book`, `m
``` ```
./runserver --paddle <path_to_fluiddoc_dir> \ ./runserver --paddle <path_to_fluiddoc_dir> \
--book <path_to_fluiddoc_dir>/external/book \ --book <path_to_fluiddoc_dir>/external/book \
--models <path_to_fluiddoc_dir>/external/models \ --models <path_to_fluiddoc_dir>/external/models \
--mobile <path_to_fluiddoc_dir>/external/mobile --mobile <path_to_fluiddoc_dir>/external/mobile
``` ```
Then: open your browser and navigate to http://localhost:8000. Then: open your browser and navigate to http://localhost:8000.
...@@ -178,7 +178,7 @@ After completing the installation, you will also need to do: ...@@ -178,7 +178,7 @@ After completing the installation, you will also need to do:
## Submit changes ## Submit changes
If you wish to modify the code, please refer to [How to contribute code](../development/contribute_to_paddle/index_en.html) under the `Paddle` repository. If you wish to modify the code, please refer to [How to contribute code](../contribute_code/index_en.html) under the `Paddle` repository.
If you just modify the document: If you just modify the document:
...@@ -186,20 +186,20 @@ If you just modify the document: ...@@ -186,20 +186,20 @@ If you just modify the document:
- The modified content is in the `external` folder: - The modified content is in the `external` folder:
1. Submit the PR in the repostory you modified. This is because the `FluidDoc` repository is just a wrapper that brings together the links of other repositories (namely, the "submodules" in git context). 1. Submit the PR in the repostory you modified. This is because the `FluidDoc` repository is just a wrapper that brings together the links of other repositories (namely, the "submodules" in git context).
2. When your changes are approved, update the corresponding `submodule` in FluidDoc to the latest commit-id of the source repository. 2. When your changes are approved, update the corresponding `submodule` in FluidDoc to the latest commit-id of the source repository.
> For example, you updated the document on the develop branch in the book repository: > For example, you updated the document on the develop branch in the book repository:
> - Go to the `FluidDoc/external/book` directory > - Go to the `FluidDoc/external/book` directory
> - Update commit-id to the latest commit: `git pull origin develop` > - Update commit-id to the latest commit: `git pull origin develop`
> - Commit your changes in `FluidDoc` > - Commit your changes in `FluidDoc`
3. Pull Request for your changes in the `FluidDoc` repository 3. Pull Request for your changes in the `FluidDoc` repository
The steps to submit changes and PR can refer to [How to contribute code](../development/contribute_to_paddle/index_en.html) The steps to submit changes and PR can refer to [How to contribute code](../contribute_code/index_en.html)
## Help improve preview tool ## Help improve preview tool
......
...@@ -78,8 +78,8 @@ no changes added to commit (use "git add" and/or "git commit -a") ...@@ -78,8 +78,8 @@ no changes added to commit (use "git add" and/or "git commit -a")
## 编译和单元测试 ## 编译和单元测试
关于编译 PaddlePaddle 的源码,请参见[从源码编译](../../../beginners_guide/install/compile/fromsource.html) 选择对应的操作系统。 关于编译 PaddlePaddle 的源码,请参见[从源码编译](../../../install/compile/fromsource.html) 选择对应的操作系统。
关于单元测试,可参考[Op单元测试](../../../advanced_usage/development/new_op/new_op.html#id7) 的运行方法。 关于单元测试,可参考[Op单元测试](../new_op/new_op.html#id7) 的运行方法。
## 提交(commit) ## 提交(commit)
......
...@@ -69,17 +69,17 @@ On branch test ...@@ -69,17 +69,17 @@ On branch test
Changes not staged for commit: Changes not staged for commit:
(use "git add <file>..." to update what will be committed) (use "git add <file>..." to update what will be committed)
(use "git checkout -- <file>..." to discard changes in working directory) (use "git checkout -- <file>..." to discard changes in working directory)
modified: README.md modified: README.md
Untracked files: Untracked files:
(use "git add <file>..." to include in what will be committed) (use "git add <file>..." to include in what will be committed)
test test
no changes added to commit (use "git add" and/or "git commit -a") no changes added to commit (use "git add" and/or "git commit -a")
``` ```
## Build and test ## Build and test
Please refer to [Compile From Source Code](../../../beginners_guide/install/compile/fromsource_en.html) about more information of building PaddlePaddle source codes. Please refer to [Compile From Source Code](../../../install/compile/fromsource_en.html) about more information of building PaddlePaddle source codes.
Please refer to [Op Unit Tests](../../../advanced_usage/development/new_op/new_op_en.html#unit-tests) about more information of running unit tests. Please refer to [Op Unit Tests](../new_op/new_op_en.html#unit-tests) about more information of running unit tests.
## Commit ## Commit
...@@ -91,7 +91,7 @@ Next we cancel the modification of README.md,and submit new added test file. ...@@ -91,7 +91,7 @@ Next we cancel the modification of README.md,and submit new added test file.
On branch test On branch test
Untracked files: Untracked files:
(use "git add <file>..." to include in what will be committed) (use "git add <file>..." to include in what will be committed)
test test
nothing added to commit but untracked files present (use "git add" to track) nothing added to commit but untracked files present (use "git add" to track)
➜ git add test ➜ git add test
``` ```
...@@ -132,8 +132,8 @@ Check the name of current remote repository with `git remote`. ...@@ -132,8 +132,8 @@ Check the name of current remote repository with `git remote`.
➜ git remote ➜ git remote
origin origin
➜ git remote -v ➜ git remote -v
origin https://github.com/USERNAME/Paddle (fetch) origin https://github.com/USERNAME/Paddle (fetch)
origin https://github.com/USERNAME/Paddle (push) origin https://github.com/USERNAME/Paddle (push)
``` ```
origin is the name of remote repository that we clone,which is also the Paddle under your own account. Next we create a remote host of an original Paddle and name it upstream. origin is the name of remote repository that we clone,which is also the Paddle under your own account. Next we create a remote host of an original Paddle and name it upstream.
......
...@@ -25,7 +25,7 @@ Paddle使用一种编译器式的执行流程,分为编译时和运行时两 ...@@ -25,7 +25,7 @@ Paddle使用一种编译器式的执行流程,分为编译时和运行时两
2. 原始的 Program 在框架内部转换为中间描述语言: `ProgramDesc` 2. 原始的 Program 在框架内部转换为中间描述语言: `ProgramDesc`
3. `Transpiler` 接受一段 `ProgramDesc` ,输出一段变化后的 `ProgramDesc` ,作为后端 `Executor` 最终需要执行的 Program 。 `Transpiler` 并非必需步骤。 3. `Transpiler` 接受一段 `ProgramDesc` ,输出一段变化后的 `ProgramDesc` ,作为后端 `Executor` 最终需要执行的 Program 。 `Transpiler` 并非必需步骤。
4. 执行 `ProgramDesc` 中定义的 Operator(可以类比为程序语言中的指令),在执行过程中会为 Operator 创建所需的输入输出并进行管理。 4. 执行 `ProgramDesc` 中定义的 Operator(可以类比为程序语言中的指令),在执行过程中会为 Operator 创建所需的输入输出并进行管理。
...@@ -213,7 +213,7 @@ outs = exe.run( ...@@ -213,7 +213,7 @@ outs = exe.run(
## 代码实例 ## 代码实例
本节通过[编程指南](../../beginners_guide/programming_guide/programming_guide.html)中简单的线性回归例子,为您介绍上述内容如何在代码中实现。 本节通过[编程指南](../../../beginners_guide/basic_concept/programming_guide/programming_guide.html)中简单的线性回归例子,为您介绍上述内容如何在代码中实现。
**定义Program** **定义Program**
...@@ -360,5 +360,4 @@ Paddle使用Executor.run来运行一段Program。 ...@@ -360,5 +360,4 @@ Paddle使用Executor.run来运行一段Program。
[6.099215 ]], dtype=float32), array([1.6935859], dtype=float32)] [6.099215 ]], dtype=float32), array([1.6935859], dtype=float32)]
``` ```
至此您已经了解了Paddle内部的执行流程的核心概念,更多框架使用细节请参考[使用指南](../../user_guides/index_cn.html)相关内容,[模型库](../../user_guides/models/index_cn.html 至此您已经了解了Paddle内部的执行流程的核心概念,更多框架使用细节可以参考[典型案例](../../../user_guides/index_cn.html)
)中也为您提供了丰富的模型示例以供参考。
...@@ -37,7 +37,7 @@ After completing the network definition, there are usually 2 Programs in a Fluid ...@@ -37,7 +37,7 @@ After completing the network definition, there are usually 2 Programs in a Fluid
1. ``fluid.default_startup_program`` : defines various operations such as creating model parameters, input and output, and initialization of learnable parameters in the model. 1. ``fluid.default_startup_program`` : defines various operations such as creating model parameters, input and output, and initialization of learnable parameters in the model.
default_startup_program can be automatically generated by the framework and can be used without visible manual creation. default_startup_program can be automatically generated by the framework and can be used without visible manual creation.
If the call changes the default initialization method of the parameter, the framework will automatically add the relevant changes to the default_startup_program If the call changes the default initialization method of the parameter, the framework will automatically add the relevant changes to the default_startup_program
...@@ -75,22 +75,22 @@ Similarly, the following Program contains 3 blocks: ...@@ -75,22 +75,22 @@ Similarly, the following Program contains 3 blocks:
import paddle.fluid as fluid # block 0 import paddle.fluid as fluid # block 0
limit = fluid.layers.fill_constant_batch_size_like( 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) cond = fluid.layers.less_than(x=label, y=limit)
ie = fluid.layers.IfElse(cond) ie = fluid.layers.IfElse(cond)
with ie.true_block(): # block 1 with ie.true_block(): # block 1
true_image = ie.input(image) true_image = ie.input(image)
hidden = fluid.layers.fc(input=true_image, size=100, act='tanh') hidden = fluid.layers.fc(input=true_image, size=100, act='tanh')
prob = fluid.layers.fc(input=hidden, size=10, act='softmax') prob = fluid.layers.fc(input=hidden, size=10, act='softmax')
ie.output(prob) ie.output(prob)
with ie.false_block(): # block 2 with ie.false_block(): # block 2
false_image = ie.input(image) false_image = ie.input(image)
hidden = fluid.layers.fc( hidden = fluid.layers.fc(
input=false_image, size=200, act='tanh') input=false_image, size=200, act='tanh')
prob = fluid.layers.fc(input=hidden, size=10, act='softmax') prob = fluid.layers.fc(input=hidden, size=10, act='softmax')
ie.output(prob) ie.output(prob)
prob = ie() prob = ie()
``` ```
...@@ -136,10 +136,10 @@ message AttrDesc { ...@@ -136,10 +136,10 @@ message AttrDesc {
required string name = 1; required string name = 1;
enum AttrType { enum AttrType {
INT = 1, INT = 1,
STRING = 2, STRING = 2,
... ...
BLOCK = ... BLOCK = ...
} }
required AttrType type = 2; required AttrType type = 2;
...@@ -169,24 +169,24 @@ C++ implementation code of Executor is as follows: ...@@ -169,24 +169,24 @@ C++ implementation code of Executor is as follows:
```cpp ```cpp
class Executor{ class Executor{
public: public:
void Run(const ProgramDesc& pdesc, void Run(const ProgramDesc& pdesc,
scope* scope, scope* scope,
int block_id) { int block_id) {
auto& block = pdesc.Block(block_id); auto& block = pdesc.Block(block_id);
// Create all variables // Create all variables
for (auto& var : block.AllVars()) for (auto& var : block.AllVars())
scope->Var(Var->Name()); scope->Var(Var->Name());
} }
// Create OP and execute in order // Create OP and execute in order
for (auto& op_desc : block.AllOps()){ for (auto& op_desc : block.AllOps()){
auto op = CreateOp(*op_desc); auto op = CreateOp(*op_desc);
op->Run(*local_scope, place_); op->Run(*local_scope, place_);
} }
} }
}; };
``` ```
**Create Executor** **Create Executor**
...@@ -208,13 +208,13 @@ Fluid uses Executor.run to run the program. In the definition, the data is obtai ...@@ -208,13 +208,13 @@ Fluid uses Executor.run to run the program. In the definition, the data is obtai
... ...
x = numpy.random.random(size=(10, 1)).astype('float32') x = numpy.random.random(size=(10, 1)).astype('float32')
outs = exe.run( outs = exe.run(
feed={'X': x}, feed={'X': x},
fetch_list=[loss.name]) fetch_list=[loss.name])
``` ```
## Code Instance ## Code Instance
This section introduces how the above is implemented in your code through a simple linear regression example in the [Fluid Programming Guide](../../beginners_guide/programming_guide/programming_guide.html). This section introduces how the above is implemented in your code through a simple linear regression example in the [Fluid Programming Guide](../../../beginners_guide/basic_concept/programming_guide/programming_guide_en.html).
**Define Program** **Define Program**
...@@ -252,48 +252,48 @@ blocks { ...@@ -252,48 +252,48 @@ blocks {
idx: 0 idx: 0
parent_idx: -1 parent_idx: -1
vars { vars {
name: "mean_1.tmp_0" name: "mean_1.tmp_0"
type { type {
type: LOD_TENSOR type: LOD_TENSOR
lod_tensor { lod_tensor {
tensor { tensor {
data_type: FP32 data_type: FP32
dims: 1 dims: 1
} }
} }
} }
persistable: false persistable: false
} }
vars { vars {
name: "square_error_cost_1.tmp_1" name: "square_error_cost_1.tmp_1"
type { type {
type: LOD_TENSOR type: LOD_TENSOR
lod_tensor { lod_tensor {
tensor { tensor {
data_type: FP32 data_type: FP32
dims: -1 dims: -1
dims: 1 dims: 1
} }
lod_level: 0 lod_level: 0
} }
} }
persistable: false persistable: false
} }
vars { vars {
name: "square_error_cost_1.tmp_0" name: "square_error_cost_1.tmp_0"
type { type {
type: LOD_TENSOR type: LOD_TENSOR
lod_tensor { lod_tensor {
tensor { tensor {
data_type: FP32 data_type: FP32
dims: -1 dims: -1
dims: 1 dims: 1
} }
lod_level: 0 lod_level: 0
} }
} }
persistable: false persistable: false
... ...
``` ```
As you can see from the output, the entire definition process is transformed into a ProgramDesc inside the framework, indexed by block idx. There is only one block in this linear regression model, and ProgramDesc has only one piece of BlockDesc, namely Block 0. As you can see from the output, the entire definition process is transformed into a ProgramDesc inside the framework, indexed by block idx. There is only one block in this linear regression model, and ProgramDesc has only one piece of BlockDesc, namely Block 0.
...@@ -304,19 +304,19 @@ x = fluid.layers.data(name="x",shape=[1],dtype='float32') ...@@ -304,19 +304,19 @@ x = fluid.layers.data(name="x",shape=[1],dtype='float32')
In BlockDesc, the variable x is described as: In BlockDesc, the variable x is described as:
``` ```
vars { vars {
name: "x" name: "x"
type { type {
type: LOD_TENSOR type: LOD_TENSOR
lod_tensor { lod_tensor {
tensor { tensor {
data_type: FP32 data_type: FP32
dims: -1 dims: -1
dims: 1 dims: 1
} }
lod_level: 0 lod_level: 0
} }
} }
persistable: false persistable: false
``` ```
All data in Fluid are LoD-Tensor, and for data without sequence information (such as variable X here), lod_level=0. All data in Fluid are LoD-Tensor, and for data without sequence information (such as variable X here), lod_level=0.
...@@ -348,18 +348,17 @@ Since there are multiple columns of incoming and outgoing data, fluid defines tr ...@@ -348,18 +348,17 @@ Since there are multiple columns of incoming and outgoing data, fluid defines tr
```python ```python
# Start training # Start training
outs = exe.run( outs = exe.run(
feed={'x':train_data,'y':y_true}, feed={'x':train_data,'y':y_true},
fetch_list=[y_predict.name,avg_cost.name]) fetch_list=[y_predict.name,avg_cost.name])
``` ```
The above code defines that train_data is to be passed into the x variable, y_true is to be passed into the y variable, and output the predicted value of y and the last round value of cost. The above code defines that train_data is to be passed into the x variable, y_true is to be passed into the y variable, and output the predicted value of y and the last round value of cost.
The output is: The output is:
``` ```
[array([[1.5248038], [array([[1.5248038],
[3.0496075], [3.0496075],
[4.5744114], [4.5744114],
[6.099215 ]], dtype=float32), array([1.6935859], dtype=float32)] [6.099215 ]], dtype=float32), array([1.6935859], dtype=float32)]
``` ```
Till now you have already be notified of the core concepts of the internal execution process of Fluid. For more details on the usage of the framework, please refer to the [User Guide](../../user_guides/index_en.html) related content, [Model Library](../../user_guides/models/index_en.html Till now you have already be notified of the core concepts of the internal execution process of Fluid. For more details on the usage of the framework, please refer to the [User Guide](../../../user_guides/index_en.html).
) also provides you with a wealth of model examples for reference.
.. _addon_development:
########
二次开发
########
.. toctree::
:hidden:
design_idea/fluid_design_idea.md
new_op/index_cn.rst
contribute_code/index_cn.rst
contribute-docs/write_docs_cn.md
.. _addon_development_en:
################
Addon Development
################
.. toctree::
:hidden:
design_idea/fluid_design_idea_en.md
new_op/index_en.rst
contribute_code/index_en.rst
contribute-docs/write_docs_en.md
...@@ -270,7 +270,7 @@ g++ relu_op.cc relu_op.cu.o -o relu2_op.so -shared -fPIC -std=c++11 -O3 -DPADDLE ...@@ -270,7 +270,7 @@ g++ relu_op.cc relu_op.cu.o -o relu2_op.so -shared -fPIC -std=c++11 -O3 -DPADDLE
注意点: 注意点:
1. NVCC编译GPU OP的cu文件时,需要加 `-DPADDLE_WITH_CUDA -DEIGEN_USE_GPU -DPADDLE_USE_DSO` 1. NVCC编译GPU OP的cu文件时,需要加 `-DPADDLE_WITH_CUDA -DEIGEN_USE_GPU -DPADDLE_USE_DSO`
2. 如果安装的PaddlePaddle不包含MKLDNN,则需要去掉编译选项`-DPADDLE_WITH_MKLDNN`。默认的安装包已包含MKLDNN。 2. 如果安装的PaddlePaddle不包含MKLDNN,则需要去掉编译选项`-DPADDLE_WITH_MKLDNN`。默认的安装包已包含MKLDNN。
......
...@@ -408,7 +408,7 @@ class MulKernel : public framework::OpKernel<T> { ...@@ -408,7 +408,7 @@ class MulKernel : public framework::OpKernel<T> {
REGISTER_OPERATOR(mul, ops::MulOp, ops::MulOpMaker, REGISTER_OPERATOR(mul, ops::MulOp, ops::MulOpMaker,
ops::MulOpGradMaker) ops::MulOpGradMaker)
REGISTER_OPERATOR(mul_grad, ops::MulGradOp) REGISTER_OPERATOR(mul_grad, ops::MulGradOp)
REGISTER_OP_CPU_KERNEL(mul, REGISTER_OP_CPU_KERNEL(mul,
ops::MulKernel<paddle::platform::CPUDeviceContext, float>, ops::MulKernel<paddle::platform::CPUDeviceContext, float>,
ops::MulKernel<paddle::platform::CPUDeviceContext, double>); ops::MulKernel<paddle::platform::CPUDeviceContext, double>);
REGISTER_OP_CPU_KERNEL(mul_grad, REGISTER_OP_CPU_KERNEL(mul_grad,
...@@ -418,9 +418,9 @@ class MulKernel : public framework::OpKernel<T> { ...@@ -418,9 +418,9 @@ class MulKernel : public framework::OpKernel<T> {
在上面的代码中: 在上面的代码中:
- `REGISTER_OPERATOR` : 注册`ops::MulOp`类,类型名为`mul`,该类的`ProtoMaker`为`ops::MulOpMaker`,注册`ops::MulOpGrad`,类型名为`mul_grad`。 - `REGISTER_OPERATOR` : 注册`ops::MulOp`类,类型名为`mul`,该类的`ProtoMaker`为`ops::MulOpMaker`,注册`ops::MulOpGrad`,类型名为`mul_grad`。
- `REGISTER_OP_CPU_KERNEL` :注册`ops::MulKernel`类,并特化模板参数为`paddle::platform::CPUPlace`和`float`类型,同理,注册`ops::MulGradKernel`类。 - `REGISTER_OP_CPU_KERNEL` :注册`ops::MulKernel`类,并特化模板参数为`paddle::platform::CPUPlace`和`float`类型,同理,注册`ops::MulGradKernel`类。
-`.cu`文件中注册CUDA Kernel。 -`.cu`文件中注册CUDA Kernel。
...@@ -432,7 +432,7 @@ class MulKernel : public framework::OpKernel<T> { ...@@ -432,7 +432,7 @@ class MulKernel : public framework::OpKernel<T> {
#define EIGEN_USE_GPU #define EIGEN_USE_GPU
namespace ops = paddle::operators; namespace ops = paddle::operators;
REGISTER_OP_CUDA_KERNEL(mul, REGISTER_OP_CUDA_KERNEL(mul,
ops::MulKernel<paddle::platform::CUDADeviceContext, float>, ops::MulKernel<paddle::platform::CUDADeviceContext, float>,
ops::MulKernel<paddle::platform::CUDADeviceContext, double>); ops::MulKernel<paddle::platform::CUDADeviceContext, double>);
REGISTER_OP_CUDA_KERNEL(mul_grad, REGISTER_OP_CUDA_KERNEL(mul_grad,
...@@ -499,7 +499,7 @@ Op单元测试继承自`OpTest`。各项具体的单元测试在`TestMulOp`里 ...@@ -499,7 +499,7 @@ Op单元测试继承自`OpTest`。各项具体的单元测试在`TestMulOp`里
1.`setUp`函数定义输入、输出,以及相关的属性参数。 1.`setUp`函数定义输入、输出,以及相关的属性参数。
> 注意:输入输出请以`ndarray`的类型配置输入/输出,如果需要配置一个带`LOD`的输入/输出,请以`tuple`的形式传入,`tuple`中应该有两个类型为`ndarray`的元素,第一个是实际的数据,第二个是`LOD` > 注意:输入输出请以`ndarray`的类型配置输入/输出,如果需要配置一个带`LOD`的输入/输出,请以`tuple`的形式传入,`tuple`中应该有两个类型为`ndarray`的元素,第一个是实际的数据,第二个是`LOD`
2. 生成随机的输入数据。 2. 生成随机的输入数据。
...@@ -507,41 +507,41 @@ Op单元测试继承自`OpTest`。各项具体的单元测试在`TestMulOp`里 ...@@ -507,41 +507,41 @@ Op单元测试继承自`OpTest`。各项具体的单元测试在`TestMulOp`里
4. 反向计算已经自动集成进测试框架,直接调用相应接口即可。 4. 反向计算已经自动集成进测试框架,直接调用相应接口即可。
```python ```python
import unittest import unittest
import numpy as np import numpy as np
from op_test import OpTest from op_test import OpTest
class TestMulOp(OpTest): class TestMulOp(OpTest):
def setUp(self): def setUp(self):
self.op_type = "mul" self.op_type = "mul"
self.inputs = { self.inputs = {
'X': np.random.random((32, 84)).astype("float32"), 'X': np.random.random((32, 84)).astype("float32"),
'Y': np.random.random((84, 100)).astype("float32") 'Y': np.random.random((84, 100)).astype("float32")
} }
self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])} self.outputs = {'Out': np.dot(self.inputs['X'], self.inputs['Y'])}
def test_check_output(self): def test_check_output(self):
self.check_output() self.check_output()
def test_check_grad_normal(self): def test_check_grad_normal(self):
self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5) self.check_grad(['X', 'Y'], 'Out', max_relative_error=0.5)
def test_check_grad_ingore_x(self): def test_check_grad_ingore_x(self):
self.check_grad( self.check_grad(
['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X")) ['Y'], 'Out', max_relative_error=0.5, no_grad_set=set("X"))
def test_check_grad_ingore_y(self): def test_check_grad_ingore_y(self):
self.check_grad( self.check_grad(
['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y')) ['X'], 'Out', max_relative_error=0.5, no_grad_set=set('Y'))
``` ```
上面的代码首先导入依赖的包,下面是对`setUp`函数中操作的重要变量的详细解释: 上面的代码首先导入依赖的包,下面是对`setUp`函数中操作的重要变量的详细解释:
- `self.op_type = "mul" ` : 定义类型,与operator注册时注册的类型一致。 - `self.op_type = "mul" ` : 定义类型,与operator注册时注册的类型一致。
- `self.inputs` : 定义输入,类型为`numpy.array`,并初始化。 - `self.inputs` : 定义输入,类型为`numpy.array`,并初始化。
- `self.outputs` : 定义输出,并在Python脚本中完成与operator同样的计算逻辑,返回Python端的计算结果。 - `self.outputs` : 定义输出,并在Python脚本中完成与operator同样的计算逻辑,返回Python端的计算结果。
### 反向operator单测 ### 反向operator单测
...@@ -613,34 +613,34 @@ PADDLE_ENFORCE_EQ(比较对象A, 比较对象B, 错误提示信息) ...@@ -613,34 +613,34 @@ PADDLE_ENFORCE_EQ(比较对象A, 比较对象B, 错误提示信息)
1. 无报错信息或报错信息过于简单,不能给用户提供有效的提示! 1. 无报错信息或报错信息过于简单,不能给用户提供有效的提示!
问题示例1 :未写提示信息 问题示例1 :未写提示信息
``` ```
PADDLE_ENFORCE(ctx->HasInput("X"), ""); PADDLE_ENFORCE(ctx->HasInput("X"), "");
``` ```
问题示例2 :提示信息过于简单 问题示例2 :提示信息过于简单
``` ```
PADDLE_ENFORCE(i != nullptr, "i must be set"); // i是什么? PADDLE_ENFORCE(i != nullptr, "i must be set"); // i是什么?
``` ```
2. 在报错信息中使用开发人员定义的变量缩写,不易理解! 2. 在报错信息中使用开发人员定义的变量缩写,不易理解!
问题示例: 问题示例:
``` ```
PADDLE_ENFORCE(forward_pd != nullptr, PADDLE_ENFORCE(forward_pd != nullptr,
"Fail to find eltwise_fwd_pd in device context"); //eltwise_fwd_pd用户可能看不懂 "Fail to find eltwise_fwd_pd in device context"); //eltwise_fwd_pd用户可能看不懂
``` ```
3. OP内部调用非法接口:Op内部如果出现Output = ShareDataWith(Input) 3. OP内部调用非法接口:Op内部如果出现Output = ShareDataWith(Input)
问题示例: 问题示例:
```cpp ```cpp
auto *out = ctx.Output<framework::LoDTensor>("Out"); auto *out = ctx.Output<framework::LoDTensor>("Out");
auto *in = ctx.Input<framework::LoDTensor>("X"); auto *in = ctx.Input<framework::LoDTensor>("X");
out->ShareDataWith(*in); out->ShareDataWith(*in);
``` ```
Op内部如果出现Output = ShareDataWith(Input),相当于operator图的中有一条隐藏边,连接了Input和Output,这条边无法在图分析中表达,引发基于图优化的错误。 Op内部如果出现Output = ShareDataWith(Input),相当于operator图的中有一条隐藏边,连接了Input和Output,这条边无法在图分析中表达,引发基于图优化的错误。
4. OP实现的性能实践 4. OP实现的性能实践
调用了eigen的broadcast, chop等操作,性能会比手写cuda kernel差几倍以上。此时cpu的实现可以复用eigen,gpu实现可以实现cuda kernel. 调用了eigen的broadcast, chop等操作,性能会比手写cuda kernel差几倍以上。此时cpu的实现可以复用eigen,gpu实现可以实现cuda kernel.
#### OP InferShape检查提示信息特别说明 #### OP InferShape检查提示信息特别说明
...@@ -648,16 +648,16 @@ PADDLE_ENFORCE_EQ(比较对象A, 比较对象B, 错误提示信息) ...@@ -648,16 +648,16 @@ PADDLE_ENFORCE_EQ(比较对象A, 比较对象B, 错误提示信息)
- 检查输入输出变量,请统一遵循以下格式 - 检查输入输出变量,请统一遵循以下格式
`Input(变量名) of OP名 operator should not be null.` `Input(变量名) of OP名 operator should not be null.`
正确示例: 正确示例:
``` ```
PADDLE_ENFORCE(ctx->HasInput("Input"), PADDLE_ENFORCE(ctx->HasInput("Input"),
"Input(Input) of LSTMP operator should not be null."); "Input(Input) of LSTMP operator should not be null.");
``` ```
- 反向Op的输入输出检查,要写明反向Op的名字 - 反向Op的输入输出检查,要写明反向Op的名字
正确示例: 正确示例:
``` ```
PADDLE_ENFORCE(ctx->HasInput("X"), PADDLE_ENFORCE(ctx->HasInput("X"),
"Input(X) of LoDResetGrad opreator should not be null."); "Input(X) of LoDResetGrad opreator should not be null.");
``` ```
...@@ -59,9 +59,9 @@ def tanh(x): ...@@ -59,9 +59,9 @@ def tanh(x):
return np.tanh(x) return np.tanh(x)
# 前向函数2:将两个2-D LodTenosr相加,输入多个LodTensor以list[Variable]或tuple(Variable)形式 # 前向函数2:将两个2-D LodTenosr相加,输入多个LodTensor以list[Variable]或tuple(Variable)形式
def element_wise_add(x, y): def element_wise_add(x, y):
# 必须先手动将LodTensor转换为numpy数组,否则无法支持numpy的shape操作 # 必须先手动将LodTensor转换为numpy数组,否则无法支持numpy的shape操作
x = np.array(x) x = np.array(x)
y = np.array(y) y = np.array(y)
if x.shape != y.shape: if x.shape != y.shape:
...@@ -104,7 +104,7 @@ import paddle.fluid as fluid ...@@ -104,7 +104,7 @@ import paddle.fluid as fluid
def create_tmp_var(program, name, dtype, shape): def create_tmp_var(program, name, dtype, shape):
return program.current_block().create_var(name=name, dtype=dtype, shape=shape) return program.current_block().create_var(name=name, dtype=dtype, shape=shape)
in_var = fluid.layers.data(name='input', dtype='float32', shape=[-1, 28, 28]) in_var = fluid.layers.data(name='input', dtype='float32', shape=[-1, 28, 28])
# 手动创建前向输出变量 # 手动创建前向输出变量
...@@ -133,9 +133,8 @@ fluid.layers.py_func(func=tanh, x=in_var, out=out_var, backward_func=tanh_grad_w ...@@ -133,9 +133,8 @@ fluid.layers.py_func(func=tanh, x=in_var, out=out_var, backward_func=tanh_grad_w
- `py_func` 的前向函数和反向函数内部不应调用 `fluid.layers.xxx` ,因为前向函数和反向函数是在网络运行时调用的,且输入参数均为C++端的 `LoDTensor` - `py_func` 的前向函数和反向函数内部不应调用 `fluid.layers.xxx` ,因为前向函数和反向函数是在网络运行时调用的,且输入参数均为C++端的 `LoDTensor`
`fluid.layers.xxx` 是在组建网络的阶段调用的,且输入参数为Python端的 `Variable` `fluid.layers.xxx` 是在组建网络的阶段调用的,且输入参数为Python端的 `Variable`
- `skip_vars_in_backward_input` 只能跳过前向输入变量和前向输出变量,不能跳过前向输出的梯度。 - `skip_vars_in_backward_input` 只能跳过前向输入变量和前向输出变量,不能跳过前向输出的梯度。
- 若某个前向输出变量没有梯度,则 `backward_func` 将接收到 `None` 的输入。若某个前向输入变量没有梯度,则我们应在 `backward_func` 中主动返回 - 若某个前向输出变量没有梯度,则 `backward_func` 将接收到 `None` 的输入。若某个前向输入变量没有梯度,则我们应在 `backward_func` 中主动返回
`None` `None`
...@@ -9,7 +9,7 @@ Op的核心方法是Run,Run方法需要两方面的资源:数据资源和计 ...@@ -9,7 +9,7 @@ Op的核心方法是Run,Run方法需要两方面的资源:数据资源和计
Fluid框架的设计理念是可以在多种设备及第三方库上运行,有些Op的实现可能会因为设备或者第三方库的不同而不同。为此,Fluid引入了OpKernel的方式,即一个Op可以有多个OpKernel,这类Op继承自`OperatorWithKernel`,这类Op的代表是conv_op,conv_op的OpKernel有:`GemmConvKernel``CUDNNConvOpKernel``ConvMKLDNNOpKernel`,且每个OpKernel都有double和float两种数据类型。不需要OpKernel的代表有`WhileOp`等。 Fluid框架的设计理念是可以在多种设备及第三方库上运行,有些Op的实现可能会因为设备或者第三方库的不同而不同。为此,Fluid引入了OpKernel的方式,即一个Op可以有多个OpKernel,这类Op继承自`OperatorWithKernel`,这类Op的代表是conv_op,conv_op的OpKernel有:`GemmConvKernel``CUDNNConvOpKernel``ConvMKLDNNOpKernel`,且每个OpKernel都有double和float两种数据类型。不需要OpKernel的代表有`WhileOp`等。
Operator继承关系图: Operator继承关系图:
![op_inheritance_relation_diagram](../../pics/op_inheritance_relation_diagram.png) ![op_inheritance_relation_diagram](./op_inheritance_relation_diagram.png)
进一步了解可参考:[multi_devices](https://github.com/PaddlePaddle/FluidDoc/tree/develop/doc/fluid/design/multi_devices)[scope](https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/fluid/design/concepts/scope.md)[Developer's_Guide_to_Paddle_Fluid](https://github.com/PaddlePaddle/FluidDoc/blob/release/1.2/doc/fluid/getstarted/Developer's_Guide_to_Paddle_Fluid.md) 进一步了解可参考:[multi_devices](https://github.com/PaddlePaddle/FluidDoc/tree/develop/doc/fluid/design/multi_devices)[scope](https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/fluid/design/concepts/scope.md)[Developer's_Guide_to_Paddle_Fluid](https://github.com/PaddlePaddle/FluidDoc/blob/release/1.2/doc/fluid/getstarted/Developer's_Guide_to_Paddle_Fluid.md)
...@@ -173,13 +173,13 @@ class SliceOpGrad : public framework::OperatorWithKernel { ...@@ -173,13 +173,13 @@ class SliceOpGrad : public framework::OperatorWithKernel {
using framework::OperatorWithKernel::OperatorWithKernel; using framework::OperatorWithKernel::OperatorWithKernel;
void InferShape(framework::InferShapeContext* ctx) const override { void InferShape(framework::InferShapeContext* ctx) const override {
// ... // ...
} }
framework::OpKernelType GetExpectedKernelType( framework::OpKernelType GetExpectedKernelType(
const framework::ExecutionContext& ctx) const override { const framework::ExecutionContext& ctx) const override {
// Note: don't get data type from ctx.Input<framework::Tensor>("Input"); // Note: don't get data type from ctx.Input<framework::Tensor>("Input");
auto dtype = ctx.Input<framework::Tensor>(framework::GradVarName("Out"))->type(); auto dtype = ctx.Input<framework::Tensor>(framework::GradVarName("Out"))->type();
return framework::OpKernelType( dtype, ctx.GetPlace()); return framework::OpKernelType( dtype, ctx.GetPlace());
} }
}; };
...@@ -261,15 +261,15 @@ The following device operations are asynchronous with respect to the host: ...@@ -261,15 +261,15 @@ The following device operations are asynchronous with respect to the host:
</table> </table>
这两类 OP 的 LoD 传导需要考虑前向和反向两个过程。 这两类 OP 的 LoD 传导需要考虑前向和反向两个过程。
#### 前向传导 #### 前向传导
在前向传导过程,与输入的 LoD 相比较,Op 输出的 LoD 可能出现不变、改变和消失这三种情况: 在前向传导过程,与输入的 LoD 相比较,Op 输出的 LoD 可能出现不变、改变和消失这三种情况:
- 不变:适用于所有的 LoD-Transparent OP 与部分的 LoD-Based OP。可以在`InferShape` 中调用 `ShareLoD()` 直接将输入 Var 的 LoD 共享给输出 Var, 可参考 [lstm_op](https://github.com/PaddlePaddle/Paddle/blob/a88a1faa48a42a8c3737deb0f05da968d200a7d3/paddle/fluid/operators/lstm_op.cc#L92); 如果有多个输入且都可能存在 LoD 的情况,通常默认共享第一个输入, 例如 [elementwise_ops forward](https://github.com/PaddlePaddle/Paddle/blob/5d6a1fcf16bcb48d2e66306b27d9994d9b07433c/paddle/fluid/operators/elementwise/elementwise_op.h#L69) - 不变:适用于所有的 LoD-Transparent OP 与部分的 LoD-Based OP。可以在`InferShape` 中调用 `ShareLoD()` 直接将输入 Var 的 LoD 共享给输出 Var, 可参考 [lstm_op](https://github.com/PaddlePaddle/Paddle/blob/a88a1faa48a42a8c3737deb0f05da968d200a7d3/paddle/fluid/operators/lstm_op.cc#L92); 如果有多个输入且都可能存在 LoD 的情况,通常默认共享第一个输入, 例如 [elementwise_ops forward](https://github.com/PaddlePaddle/Paddle/blob/5d6a1fcf16bcb48d2e66306b27d9994d9b07433c/paddle/fluid/operators/elementwise/elementwise_op.h#L69)
- 改变:适用于部分 LoD-Based OP。在实现 OpKernel 时需考虑输出 LoD 的正确计算,真实的 LoD 在前向计算结束后才能确定,此时仍需要在`InferShape` 中调用 `ShareLoD()`,以确保CompileTime 时对 LoD Level 做了正确的传导,可参考 [sequence_expand_op](https://github.com/PaddlePaddle/Paddle/blob/565d30950138b9f831caa33904d9016cf53c6c2e/paddle/fluid/operators/sequence_ops/sequence_expand_op.cc) - 改变:适用于部分 LoD-Based OP。在实现 OpKernel 时需考虑输出 LoD 的正确计算,真实的 LoD 在前向计算结束后才能确定,此时仍需要在`InferShape` 中调用 `ShareLoD()`,以确保CompileTime 时对 LoD Level 做了正确的传导,可参考 [sequence_expand_op](https://github.com/PaddlePaddle/Paddle/blob/565d30950138b9f831caa33904d9016cf53c6c2e/paddle/fluid/operators/sequence_ops/sequence_expand_op.cc)
- 消失:适用于输出不再是序列数据的 LoD-Based OP。此时不用再考虑前向的 LoD 传导问题,可参考 [sequence_pool_op](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/operators/sequence_ops/sequence_pool_op.cc) - 消失:适用于输出不再是序列数据的 LoD-Based OP。此时不用再考虑前向的 LoD 传导问题,可参考 [sequence_pool_op](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/operators/sequence_ops/sequence_pool_op.cc)
其它重要的注意事项: 其它重要的注意事项:
...@@ -278,7 +278,7 @@ The following device operations are asynchronous with respect to the host: ...@@ -278,7 +278,7 @@ The following device operations are asynchronous with respect to the host:
- 对 LoD Level 有明确要求的 OP,推荐的做法是在 `InferShape` 中即完成 LoD Level的检查,例如 [sequence_pad_op](https://github.com/PaddlePaddle/Paddle/blob/4292bd8687ababc7737cffbddc0d38ead2138c00/paddle/fluid/operators/sequence_ops/sequence_pad_op.cc#L79) - 对 LoD Level 有明确要求的 OP,推荐的做法是在 `InferShape` 中即完成 LoD Level的检查,例如 [sequence_pad_op](https://github.com/PaddlePaddle/Paddle/blob/4292bd8687ababc7737cffbddc0d38ead2138c00/paddle/fluid/operators/sequence_ops/sequence_pad_op.cc#L79)
#### 反向传导 #### 反向传导
通常来讲,OP 的某个输入 Var 所对应的梯度 GradVar 的 LoD 应该与 Var 自身相同,所以应直接将 Var 的 LoD 共享给 GradVar,可以参考 [elementwise ops 的 backward](https://github.com/PaddlePaddle/Paddle/blob/a88a1faa48a42a8c3737deb0f05da968d200a7d3/paddle/fluid/operators/elementwise/elementwise_op.h#L189-L196) 通常来讲,OP 的某个输入 Var 所对应的梯度 GradVar 的 LoD 应该与 Var 自身相同,所以应直接将 Var 的 LoD 共享给 GradVar,可以参考 [elementwise ops 的 backward](https://github.com/PaddlePaddle/Paddle/blob/a88a1faa48a42a8c3737deb0f05da968d200a7d3/paddle/fluid/operators/elementwise/elementwise_op.h#L189-L196)
......
...@@ -9,20 +9,20 @@ The core method of Op is Run. The Run method requires two resources: data resour ...@@ -9,20 +9,20 @@ The core method of Op is Run. The Run method requires two resources: data resour
The Fluid framework is designed to run on a variety of devices and third-party libraries, and some Op implementations may vary on different the devices or third-party libraries. Therefore, Fluid introduced the OpKernel's approach, which means an Op can have multiple OpKernels. Such Ops are derived from `OperatorWithKernel`, and the representative of such Ops is conv, the OpKernels of conv_op are: `GemmConvKernel`, `CUDNNConvOpKernel`, `ConvMKLDNNOpKernel`, and each OpKernel has two data types, double and float. Ops that do not need OpKernel inclue `WhileOp` and so on. The Fluid framework is designed to run on a variety of devices and third-party libraries, and some Op implementations may vary on different the devices or third-party libraries. Therefore, Fluid introduced the OpKernel's approach, which means an Op can have multiple OpKernels. Such Ops are derived from `OperatorWithKernel`, and the representative of such Ops is conv, the OpKernels of conv_op are: `GemmConvKernel`, `CUDNNConvOpKernel`, `ConvMKLDNNOpKernel`, and each OpKernel has two data types, double and float. Ops that do not need OpKernel inclue `WhileOp` and so on.
Operator inheritance diagram: Operator inheritance diagram:
![op_inheritance_relation_diagram](../../pics/op_inheritance_relation_diagram.png) ![op_inheritance_relation_diagram](./op_inheritance_relation_diagram.png)
For further information, please refer to: [multi_devices](https://github.com/PaddlePaddle/FluidDoc/tree/develop/doc/fluid/design/multi_devices) , [scope](https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/fluid/design/concepts/scope.md) , [Developer's_Guide_to_Paddle_Fluid](https://github.com/PaddlePaddle/FluidDoc/blob/release/1.2/doc/fluid/getstarted/Developer's_Guide_to_Paddle_Fluid.md) For further information, please refer to: [multi_devices](https://github.com/PaddlePaddle/FluidDoc/tree/develop/doc/fluid/design/multi_devices) , [scope](https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/fluid/design/concepts/scope.md) , [Developer's_Guide_to_Paddle_Fluid](https://github.com/PaddlePaddle/FluidDoc/blob/release/1.2/doc/fluid/getstarted/Developer's_Guide_to_Paddle_Fluid.md)
### 2.Op's registration logic ### 2.Op's registration logic
The registration entries for each Operator include: The registration entries for each Operator include:
```C++ ```C++
OpCreator creator_; OpCreator creator_;
GradOpMakerFN grad_op_maker_; GradOpMakerFN grad_op_maker_;
proto::OpProto* proto_{nullptr}; proto::OpProto* proto_{nullptr};
OpAttrChecker* checker_{nullptr}; OpAttrChecker* checker_{nullptr};
InferVarTypeFN infer_var_type_; InferVarTypeFN infer_var_type_;
InferShapeFN infer_shape_; InferShapeFN infer_shape_;
``` ```
<table> <table>
<thead> <thead>
...@@ -74,14 +74,14 @@ The registration entries for each Operator include: ...@@ -74,14 +74,14 @@ The registration entries for each Operator include:
</table> </table>
Usually you need to call REGISTER_OPERATOR when you make comments on Op, which is: Usually you need to call REGISTER_OPERATOR when you make comments on Op, which is:
``` ```
REGISTER_OPERATOR(op_type, REGISTER_OPERATOR(op_type,
OperatorBase OperatorBase
Op_maker_and_checker_maker, Op_maker_and_checker_maker,
Op_grad_opmaker, Op_grad_opmaker,
Op_infer_var_shape, Op_infer_var_shape,
Op_infer_var_type) Op_infer_var_type)
``` ```
**Note:** **Note:**
...@@ -127,11 +127,11 @@ Since the GPU is executed asynchronously, the GPU side may not be actually execu ...@@ -127,11 +127,11 @@ Since the GPU is executed asynchronously, the GPU side may not be actually execu
Some of the synchronous and asynchronous operations in the GPU: Some of the synchronous and asynchronous operations in the GPU:
``` ```
The following device operations are asynchronous with respect to the host: The following device operations are asynchronous with respect to the host:
Kernel launches; Kernel launches;
Memory copies within a single device's memory; Memory copies within a single device's memory;
Memory copies from host to device of a memory block of 64 KB or less; Memory copies from host to device of a memory block of 64 KB or less;
Memory copies performed by functions that are suffixed with Async; Memory copies performed by functions that are suffixed with Async;
Memory set function calls. Memory set function calls.
``` ```
Note on cudaMemCpy and cudaMemCpyAsync: Note on cudaMemCpy and cudaMemCpyAsync:
...@@ -176,12 +176,11 @@ If Op has a mathematical formula, be sure to write the mathematical formula in t ...@@ -176,12 +176,11 @@ If Op has a mathematical formula, be sure to write the mathematical formula in t
The order of the parameters in the Python API is generally ranked by importance, taking fc as an example: The order of the parameters in the Python API is generally ranked by importance, taking fc as an example:
``` ```
def fc(input, def fc(input,
size, size,
num_flatten_dims=1, num_flatten_dims=1,
param_attr=None, param_attr=None,
bias_attr=None, bias_attr=None,
act=None, act=None,
is_test=False, is_test=False,
name=None) name=None)
``` ```
.. _user_guide_use_numpy_array_as_train_data_en: .. _user_guide_use_numpy_array_as_train_data_en:
################################# #################################
Take Numpy Array as Training Data Take Numpy Array as Training Data
################################# #################################
PaddlePaddle Fluid supports configuring data layer with :code:`fluid.layers.data()` . PaddlePaddle Fluid supports configuring data layer with :code:`fluid.layers.data()` .
Then you can use Numpy Array or directly use Python to create C++ Then you can use Numpy Array or directly use Python to create C++
:code:`fluid.LoDTensor` , and then feed it to :code:`fluid.Executor` or :code:`fluid.ParallelExecutor` :code:`fluid.LoDTensor` , and then feed it to :code:`fluid.Executor` or :code:`fluid.ParallelExecutor`
through :code:`Executor.run(feed=...)` . through :code:`Executor.run(feed=...)` .
Configure Data Layer Configure Data Layer
############################ ############################
With :code:`fluid.layers.data()` , you can configure data layer in neural network. Details are as follows: With :code:`fluid.layers.data()` , you can configure data layer in neural network. Details are as follows:
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import paddle.fluid as fluid
image = fluid.layers.data(name="image", shape=[3, 224, 224]) image = fluid.layers.data(name="image", shape=[3, 224, 224])
label = fluid.layers.data(name="label", shape=[1], dtype="int64") label = fluid.layers.data(name="label", shape=[1], dtype="int64")
# use image/label as layer input # use image/label as layer input
prediction = fluid.layers.fc(input=image, size=1000, act="softmax") prediction = fluid.layers.fc(input=image, size=1000, act="softmax")
loss = fluid.layers.cross_entropy(input=prediction, label=label) loss = fluid.layers.cross_entropy(input=prediction, label=label)
... ...
In the code above, :code:`image` and :code:`label` are two input data layers created by :code:`fluid.layers.data` . :code:`image` is float data of shape :code:`[3, 224, 224]` ; :code:`label` is the int data of shape :code:`[1]` . Note that: In the code above, :code:`image` and :code:`label` are two input data layers created by :code:`fluid.layers.data` . :code:`image` is float data of shape :code:`[3, 224, 224]` ; :code:`label` is the int data of shape :code:`[1]` . Note that:
1. :code:`-1` is represented for the dimension of batch size by default in Fluid. And :code:`-1` is added to the first dimension of :code:`shape` by default. Therefore in the code above, it would be alright to transfer numpy array of :code:`[32, 3, 224, 224]` to :code:`image` . If you want to customize the position of the batch size dimension, please set :code:`fluid.layers.data(append_batch_size=False)` .Please refer to the tutorial in the advanced user guide: :ref:`user_guide_customize_batch_size_rank_en` . 1. :code:`-1` is represented for the dimension of batch size by default in Fluid. And :code:`-1` is added to the first dimension of :code:`shape` by default. Therefore in the code above, it would be alright to transfer numpy array of :code:`[32, 3, 224, 224]` to :code:`image` . If you want to customize the position of the batch size dimension, please set :code:`fluid.layers.data(append_batch_size=False)` .Please refer to the tutorial in the advanced user guide: :ref:`user_guide_customize_batch_size_rank_en` .
2. Data type of category labels in Fluid is :code:`int64` and the label starts from 0. About the supported data types,please refer to :ref:`user_guide_paddle_support_data_types_en` . 2. Data type of category labels in Fluid is :code:`int64` and the label starts from 0. About the supported data types,please refer to :ref:`user_guide_paddle_support_data_types_en` .
.. _user_guide_feed_data_to_executor_en: .. _user_guide_feed_data_to_executor_en:
Transfer Train Data to Executor Transfer Train Data to Executor
################################ ################################
Both :code:`Executor.run` and :code:`ParallelExecutor.run` receive a parameter :code:`feed` . Both :code:`Executor.run` and :code:`ParallelExecutor.run` receive a parameter :code:`feed` .
The parameter is a dict in Python. Its key is the name of data layer,such as :code:`image` in code above. And its value is the corresponding numpy array. The parameter is a dict in Python. Its key is the name of data layer,such as :code:`image` in code above. And its value is the corresponding numpy array.
For example: For example:
.. code-block:: python .. code-block:: python
exe = fluid.Executor(fluid.CPUPlace()) exe = fluid.Executor(fluid.CPUPlace())
# init Program # init Program
exe.run(fluid.default_startup_program()) exe.run(fluid.default_startup_program())
exe.run(feed={ exe.run(feed={
"image": numpy.random.random(size=(32, 3, 224, 224)).astype('float32'), "image": numpy.random.random(size=(32, 3, 224, 224)).astype('float32'),
"label": numpy.random.random(size=(32, 1)).astype('int64') "label": numpy.random.random(size=(32, 1)).astype('int64')
}) })
Advanced Usage Advanced Usage
############### ###############
How to feed Sequence Data How to feed Sequence Data
-------------------------- --------------------------
Sequence data is a unique data type supported by PaddlePaddle Fluid. You can take :code:`LoDTensor` as input data type. Sequence data is a unique data type supported by PaddlePaddle Fluid. You can take :code:`LoDTensor` as input data type.
You need to: You need to:
1. Feed all data to be trained in a mini-batch. 1. Feed all data to be trained in a mini-batch.
2. Get the length of each sequence. 2. Get the length of each sequence.
You can use :code:`fluid.create_lod_tensor` to create :code:`LoDTensor` . You can use :code:`fluid.create_lod_tensor` to create :code:`LoDTensor` .
To feed sequence information, it is necessary to set the sequence nested depth :code:`lod_level` . To feed sequence information, it is necessary to set the sequence nested depth :code:`lod_level` .
For instance, if the training data are sentences consisting of words, :code:`lod_level=1`; if train data are paragraphs which consists of sentences that consists of words, :code:`lod_level=2` . For instance, if the training data are sentences consisting of words, :code:`lod_level=1`; if train data are paragraphs which consists of sentences that consists of words, :code:`lod_level=2` .
For example: For example:
.. code-block:: python .. code-block:: python
sentence = fluid.layers.data(name="sentence", dtype="int64", shape=[1], lod_level=1) sentence = fluid.layers.data(name="sentence", dtype="int64", shape=[1], lod_level=1)
... ...
exe.run(feed={ exe.run(feed={
"sentence": create_lod_tensor( "sentence": create_lod_tensor(
data=numpy.array([1, 3, 4, 5, 3, 6, 8], dtype='int64').reshape(-1, 1), data=numpy.array([1, 3, 4, 5, 3, 6, 8], dtype='int64').reshape(-1, 1),
recursive_seq_lens=[[4, 1, 2]], recursive_seq_lens=[[4, 1, 2]],
place=fluid.CPUPlace() place=fluid.CPUPlace()
) )
}) })
Training data :code:`sentence` contain three samples, the lengths of which are :code:`4, 1, 2` respectively. Training data :code:`sentence` contain three samples, the lengths of which are :code:`4, 1, 2` respectively.
They are :code:`data[0:4]`, :code:`data[4:5]` and :code:`data[5:7]` respectively. They are :code:`data[0:4]`, :code:`data[4:5]` and :code:`data[5:7]` respectively.
How to prepare training data for every device in ParallelExecutor How to prepare training data for every device in ParallelExecutor
------------------------------------------------------------------- -------------------------------------------------------------------
When you feed data to :code:`ParallelExecutor.run(feed=...)` , When you feed data to :code:`ParallelExecutor.run(feed=...)` ,
you can explicitly assign data for every training device (such as GPU). you can explicitly assign data for every training device (such as GPU).
You need to feed a list to :code:`feed` . Each element of the list is a dict. You need to feed a list to :code:`feed` . Each element of the list is a dict.
The key of the dict is name of data layer and the value of dict is value of data layer. The key of the dict is name of data layer and the value of dict is value of data layer.
For example: For example:
.. code-block:: python .. code-block:: python
parallel_executor = fluid.ParallelExecutor() parallel_executor = fluid.ParallelExecutor()
parallel_executor.run( parallel_executor.run(
feed=[ feed=[
{ {
"image": numpy.random.random(size=(32, 3, 224, 224)).astype('float32'), "image": numpy.random.random(size=(32, 3, 224, 224)).astype('float32'),
"label": numpy.random.random(size=(32, 1)).astype('int64') "label": numpy.random.random(size=(32, 1)).astype('int64')
}, },
{ {
"image": numpy.random.random(size=(16, 3, 224, 224)).astype('float32'), "image": numpy.random.random(size=(16, 3, 224, 224)).astype('float32'),
"label": numpy.random.random(size=(16, 1)).astype('int64') "label": numpy.random.random(size=(16, 1)).astype('int64')
}, },
] ]
) )
In the code above, GPU0 will train 32 samples and GPU1 will train 16 samples. In the code above, GPU0 will train 32 samples and GPU1 will train 16 samples.
.. _user_guide_customize_batch_size_rank_en: .. _user_guide_customize_batch_size_rank_en:
Customize the BatchSize dimension Customize the BatchSize dimension
------------------------------------ ------------------------------------
Batch size is the first dimension of data by default in PaddlePaddle Fluid, indicated by :code:`-1` .But in advanced usage, batch_size could be fixed or respresented by other dimension or multiple dimensions, which could be implemented by setting :code:`fluid.layers.data(append_batch_size=False)` . Batch size is the first dimension of data by default in PaddlePaddle Fluid, indicated by :code:`-1` .But in advanced usage, batch_size could be fixed or respresented by other dimension or multiple dimensions, which could be implemented by setting :code:`fluid.layers.data(append_batch_size=False)` .
1. fixed BatchSize dimension 1. fixed BatchSize dimension
.. code-block:: python .. code-block:: python
image = fluid.layers.data(name="image", shape=[32, 784], append_batch_size=False) image = fluid.layers.data(name="image", shape=[32, 784], append_batch_size=False)
Here :code:`image` is always a matrix with size of :code:`[32, 784]` . Here :code:`image` is always a matrix with size of :code:`[32, 784]` .
2. batch size expressed by other dimension 2. batch size expressed by other dimension
.. code-block:: python .. code-block:: python
sentence = fluid.layers.data(name="sentence", sentence = fluid.layers.data(name="sentence",
shape=[80, -1, 1], shape=[80, -1, 1],
append_batch_size=False, append_batch_size=False,
dtype="int64") dtype="int64")
Here the middle dimension of :code:`sentence` is batch size. This type of data layout is applied in fixed-length recurrent neural networks. Here the middle dimension of :code:`sentence` is batch size. This type of data layout is applied in fixed-length recurrent neural networks.
.. _user_guide_paddle_support_data_types_en: .. _user_guide_paddle_support_data_types_en:
Data types supported by Fluid Data types supported by Fluid
------------------------------- -------------------------------
Data types supported by PaddlePaddle Fluid contains: Data types supported by PaddlePaddle Fluid contains:
* float16: supported by part of operations * float16: supported by part of operations
* float32: major data type of real number * float32: major data type of real number
* float64: minor data type of real number, supported by most operations * float64: minor data type of real number, supported by most operations
* int32: minor data type of labels * int32: minor data type of labels
* int64: major data type of labels * int64: major data type of labels
* uint64: minor data type of labels * uint64: minor data type of labels
* bool: type of control flow data * bool: type of control flow data
* int16: minor type of labels * int16: minor type of labels
* uint8: input data type, used for pixel of picture * uint8: input data type, used for pixel of picture
.. _user_guide_distribute:
##########
分布式训练
##########
.. toctree::
:maxdepth: 1
cluster_quick_start.rst
cluster_howto.rst
fleet_api_howto_cn.rst
.. _user_guide_distribute_en:
######################
Distributed Training
######################
.. toctree::
:maxdepth: 1
cluster_quick_start_en.rst
cluster_howto_en.rst
train_on_baidu_cloud_en.rst
######## ########
多机训练 多机训练
######## ########
...@@ -8,5 +8,3 @@ ...@@ -8,5 +8,3 @@
cluster_quick_start.rst cluster_quick_start.rst
cluster_howto.rst cluster_howto.rst
fleet_api_howto_cn.rst fleet_api_howto_cn.rst
train_on_baidu_cloud_cn.rst
deploy_ctr_on_baidu_cloud_cn.rst
...@@ -27,6 +27,7 @@ import paddle.fluid as fluid ...@@ -27,6 +27,7 @@ import paddle.fluid as fluid
BATCH_SIZE = 64 BATCH_SIZE = 64
PASS_NUM = 1 PASS_NUM = 1
def loss_net(hidden, label): def loss_net(hidden, label):
prediction = fluid.layers.fc(input=hidden, size=10, act='softmax') prediction = fluid.layers.fc(input=hidden, size=10, act='softmax')
loss = fluid.layers.cross_entropy(input=prediction, label=label) loss = fluid.layers.cross_entropy(input=prediction, label=label)
...@@ -34,6 +35,7 @@ def loss_net(hidden, label): ...@@ -34,6 +35,7 @@ def loss_net(hidden, label):
acc = fluid.layers.accuracy(input=prediction, label=label) acc = fluid.layers.accuracy(input=prediction, label=label)
return prediction, avg_loss, acc return prediction, avg_loss, acc
def conv_net(img, label): def conv_net(img, label):
conv_pool_1 = fluid.nets.simple_img_conv_pool( conv_pool_1 = fluid.nets.simple_img_conv_pool(
input=img, input=img,
...@@ -79,8 +81,7 @@ def train(use_cuda, role, endpoints, current_endpoint, trainer_id, trainers): ...@@ -79,8 +81,7 @@ def train(use_cuda, role, endpoints, current_endpoint, trainer_id, trainers):
exe = fluid.Executor(place) exe = fluid.Executor(place)
train_reader = paddle.batch( train_reader = paddle.batch(
paddle.reader.shuffle( paddle.reader.shuffle(paddle.dataset.mnist.train(), buf_size=500),
paddle.dataset.mnist.train(), buf_size=500),
batch_size=BATCH_SIZE) batch_size=BATCH_SIZE)
test_reader = paddle.batch( test_reader = paddle.batch(
paddle.dataset.mnist.test(), batch_size=BATCH_SIZE) paddle.dataset.mnist.test(), batch_size=BATCH_SIZE)
...@@ -88,20 +89,23 @@ def train(use_cuda, role, endpoints, current_endpoint, trainer_id, trainers): ...@@ -88,20 +89,23 @@ def train(use_cuda, role, endpoints, current_endpoint, trainer_id, trainers):
exe.run(fluid.default_startup_program()) exe.run(fluid.default_startup_program())
for pass_id in range(PASS_NUM): for pass_id in range(PASS_NUM):
for batch_id, data in enumerate(train_reader()): for batch_id, data in enumerate(train_reader()):
acc_np, avg_loss_np = exe.run(prog, acc_np, avg_loss_np = exe.run(
feed=feeder.feed(data), prog, feed=feeder.feed(data), fetch_list=[acc, avg_loss])
fetch_list=[acc, avg_loss])
if (batch_id + 1) % 10 == 0: if (batch_id + 1) % 10 == 0:
print( print(
'PassID {0:1}, BatchID {1:04}, Loss {2:2.2}, Acc {3:2.2}'. 'PassID {0:1}, BatchID {1:04}, Loss {2:2.2}, Acc {3:2.2}'.
format(pass_id, batch_id + 1, format(pass_id, batch_id + 1,
float(avg_loss_np.mean()), float(acc_np.mean()))) float(avg_loss_np.mean()), float(
acc_np.mean())))
if __name__ == '__main__': if __name__ == '__main__':
if len(sys.argv) != 6: if len(sys.argv) != 6:
print("Usage: python %s role endpoints current_endpoint trainer_id trainers" % sys.argv[0]) print(
"Usage: python %s role endpoints current_endpoint trainer_id trainers"
% sys.argv[0])
exit(0) exit(0)
role, endpoints, current_endpoint, trainer_id, trainers = \ role, endpoints, current_endpoint, trainer_id, trainers = \
sys.argv[1:] sys.argv[1:]
train(True, role, endpoints, current_endpoint, int(trainer_id), int(trainers)) train(True, role, endpoints, current_endpoint,
int(trainer_id), int(trainers))
...@@ -246,4 +246,3 @@ VisualDL 是由 [PaddlePaddle](http://www.paddlepaddle.org/) 和 ...@@ -246,4 +246,3 @@ VisualDL 是由 [PaddlePaddle](http://www.paddlepaddle.org/) 和
## 更多细节 ## 更多细节
想了解更多关于VisualDL的使用介绍,请查看[文档](https://github.com/PaddlePaddle/VisualDL/tree/develop/demo) 想了解更多关于VisualDL的使用介绍,请查看[文档](https://github.com/PaddlePaddle/VisualDL/tree/develop/demo)
...@@ -262,4 +262,3 @@ We welcome everyone to use, comment and contribute to VisualDL :) ...@@ -262,4 +262,3 @@ We welcome everyone to use, comment and contribute to VisualDL :)
## More details ## More details
For more details about how to use VisualDL, please take a look at [documents](https://github.com/PaddlePaddle/VisualDL/tree/develop/demo) For more details about how to use VisualDL, please take a look at [documents](https://github.com/PaddlePaddle/VisualDL/tree/develop/demo)
...@@ -29,9 +29,9 @@ LogWriter 的定义为: ...@@ -29,9 +29,9 @@ LogWriter 的定义为:
class LogWriter(dir, sync_cycle) class LogWriter(dir, sync_cycle)
``` ```
> :param dir : 指定日志文件的保存路径。 > :param dir : 指定日志文件的保存路径。
> :param sync_cycle : 同步周期。经过 sync_cycle 次添加数据的操作,就执行一次将数据从内存写入磁盘的操作。 > :param sync_cycle : 同步周期。经过 sync_cycle 次添加数据的操作,就执行一次将数据从内存写入磁盘的操作。
> :return: 函数返回一个 LogWriter 对象。 > :return: 函数返回一个 LogWriter 对象。
例1 创建一个 LogWriter 对象 例1 创建一个 LogWriter 对象
...@@ -40,7 +40,7 @@ class LogWriter(dir, sync_cycle) ...@@ -40,7 +40,7 @@ class LogWriter(dir, sync_cycle)
log_writer = LogWriter("./log", sync_cycle=10) log_writer = LogWriter("./log", sync_cycle=10)
``` ```
LogWriter类的成员函数包括: LogWriter类的成员函数包括:
* `mode()` * `mode()`
* `scalar()`, `histogram()`, `image()`, `text()`, `audio()`, `embedding()` * `scalar()`, `histogram()`, `image()`, `text()`, `audio()`, `embedding()`
...@@ -69,12 +69,12 @@ with log_writer.mode("test") as shower: ...@@ -69,12 +69,12 @@ with log_writer.mode("test") as shower:
* LogWriter 对象的成员函数 `scalar()` * LogWriter 对象的成员函数 `scalar()`
```python ```python
def scalar(tag, type) def scalar(tag, type)
``` ```
> :param tag : 标签,tag 相同的折线在同一子框,否则不同,tag 的名称中不能有 % 这个字符。 > :param tag : 标签,tag 相同的折线在同一子框,否则不同,tag 的名称中不能有 % 这个字符。
> :param type : 数据类型,可选“float”, "double", "int",默认值为 "float"。 > :param type : 数据类型,可选“float”, "double", "int",默认值为 "float"。
> :return: 函数返回一个 ScalarWriter 对象。 > :return: 函数返回一个 ScalarWriter 对象。
* scalar 组件的成员函数 `add_record()` * scalar 组件的成员函数 `add_record()`
...@@ -82,8 +82,8 @@ def scalar(tag, type) ...@@ -82,8 +82,8 @@ def scalar(tag, type)
def add_record(step, value) def add_record(step, value)
``` ```
> :param step : 步进数,标记这是第几个添加的数据。 > :param step : 步进数,标记这是第几个添加的数据。
> :param value : 输入数据。 > :param value : 输入数据。
例3 scalar 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/scalar-demo.py) 例3 scalar 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/scalar-demo.py)
...@@ -110,7 +110,7 @@ for step in range(1000): ...@@ -110,7 +110,7 @@ for step in range(1000):
# 向名称为 loss 的图中添加模式为train的数据 # 向名称为 loss 的图中添加模式为train的数据
train_loss.add_record(step, 1 / (value[step] + 1)) train_loss.add_record(step, 1 / (value[step] + 1))
# 向名称为 acc 的图中添加模式为test的数据 # 向名称为 acc 的图中添加模式为test的数据
test_acc.add_record(step, 1 - value[step]) test_acc.add_record(step, 1 - value[step])
``` ```
...@@ -130,9 +130,9 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 ...@@ -130,9 +130,9 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080
VisualDL 页面的右边侧栏有各个组件的调节选项,以 scalar 组件为例: VisualDL 页面的右边侧栏有各个组件的调节选项,以 scalar 组件为例:
* Smoothing : 用于调节曲线的平滑度。 * Smoothing : 用于调节曲线的平滑度。
* X-axis : 折线图的横坐标参数,可选 `Step`, `Relative`, `Wall Time`,分别表示横轴设为步进数、相对值、数据采集的时间。 * X-axis : 折线图的横坐标参数,可选 `Step`, `Relative`, `Wall Time`,分别表示横轴设为步进数、相对值、数据采集的时间。
* Tooltip sorting : 标签排序方法,可选 `default`, `descending`, `ascending`, `nearest`,分别表示默认排序、按名称降序、按名称升序、按最新更新时间排序。 * Tooltip sorting : 标签排序方法,可选 `default`, `descending`, `ascending`, `nearest`,分别表示默认排序、按名称降序、按名称升序、按最新更新时间排序。
VisualDL 页面的右边侧栏的最下方还有一个 `RUNNING` 按钮,此时前端定期从后端同步数据,刷新页面。点击可切换为红色的 `STOPPED`,暂停前端的数据更新。 VisualDL 页面的右边侧栏的最下方还有一个 `RUNNING` 按钮,此时前端定期从后端同步数据,刷新页面。点击可切换为红色的 `STOPPED`,暂停前端的数据更新。
...@@ -145,22 +145,22 @@ VisualDL 页面的右边侧栏的最下方还有一个 `RUNNING` 按钮,此时 ...@@ -145,22 +145,22 @@ VisualDL 页面的右边侧栏的最下方还有一个 `RUNNING` 按钮,此时
* LogWriter 对象的成员函数 `histogram()` * LogWriter 对象的成员函数 `histogram()`
```python ```python
def histogram(tag, num_buckets, type) def histogram(tag, num_buckets, type)
``` ```
> :param tag : 标签,结合 LogWriter 指定的模式,决定输入参数显示的子框。 > :param tag : 标签,结合 LogWriter 指定的模式,决定输入参数显示的子框。
> :param num_buckets : 直方图的柱子数量。 > :param num_buckets : 直方图的柱子数量。
> :param type : 数据类型,可选“float”, "double", "int",默认值为 "float"。 > :param type : 数据类型,可选“float”, "double", "int",默认值为 "float"。
> :return: 函数返回一个 HistogramWriter 对象。 > :return: 函数返回一个 HistogramWriter 对象。
* histogram 组件的成员函数 `add_record()` * histogram 组件的成员函数 `add_record()`
```python ```python
def add_record(step, data) def add_record(step, data)
``` ```
> :param step : 步进数,标记这是第几组添加的数据。 > :param step : 步进数,标记这是第几组添加的数据。
> :param data : 输入参数, 数据类型为 list[]。 > :param data : 输入参数, 数据类型为 list[]。
例4 histogram 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/histogram-demo.py) 例4 histogram 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/histogram-demo.py)
...@@ -206,15 +206,15 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 ...@@ -206,15 +206,15 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080
使用 image 组件添加数据,需要先设定 LogWriter 对象的成员函数 `image()`,即可结合 `start_sampling()`, `is_sample_taken()`, `set_sample()``finish_sample()` 这四个 image 组件的成员函数来完成。这几个函数的定义及用法如下: 使用 image 组件添加数据,需要先设定 LogWriter 对象的成员函数 `image()`,即可结合 `start_sampling()`, `is_sample_taken()`, `set_sample()``finish_sample()` 这四个 image 组件的成员函数来完成。这几个函数的定义及用法如下:
* LogWriter 对象的成员函数 `image()` * LogWriter 对象的成员函数 `image()`
```python ```python
def image(tag, num_samples, step_cycle) def image(tag, num_samples, step_cycle)
``` ```
> :param tag : 标签,结合 set_sample() 的参数 index,决定图片显示的子框。 > :param tag : 标签,结合 set_sample() 的参数 index,决定图片显示的子框。
> :param num_samples : 设置单个 step 的采样数,页面上的图片数目也等于 num_samples。 > :param num_samples : 设置单个 step 的采样数,页面上的图片数目也等于 num_samples。
> :param step_cycle : 将 step_cycle 个 step 的数据存储到日志中,默认值为 1。 > :param step_cycle : 将 step_cycle 个 step 的数据存储到日志中,默认值为 1。
> :return: 函数返回一个 ImageWriter 对象。 > :return: 函数返回一个 ImageWriter 对象。
* 开始新的采样周期 - 开辟一块内存空间,用于存放采样的数据: * 开始新的采样周期 - 开辟一块内存空间,用于存放采样的数据:
...@@ -225,18 +225,18 @@ def start_sampling() ...@@ -225,18 +225,18 @@ def start_sampling()
* 判断该图片是否应被采样,当返回值为 `-1`,表示不用采样,否则,应被采样: * 判断该图片是否应被采样,当返回值为 `-1`,表示不用采样,否则,应被采样:
```python ```python
def is_sample_taken() def is_sample_taken()
``` ```
* 使用函数 `set_sample()` 添加图片数据: * 使用函数 `set_sample()` 添加图片数据:
```python ```python
def set_sample(index, image_shape, image_data) def set_sample(index, image_shape, image_data)
``` ```
> :param index : 索引号,与 tag 组合使用,决定图片显示的子框。 > :param index : 索引号,与 tag 组合使用,决定图片显示的子框。
> :param image_shape : 图片的形状,[weight, height, 通道数(RGB 为 3,灰度图为 1)]。 > :param image_shape : 图片的形状,[weight, height, 通道数(RGB 为 3,灰度图为 1)]。
> :param image_data : 图片的数据格式为矩阵,通常为 numpy.ndarray,经 flatten() 后变为行向量。 > :param image_data : 图片的数据格式为矩阵,通常为 numpy.ndarray,经 flatten() 后变为行向量。
* 结束当前的采样周期,将已采样的数据存到磁盘,并释放这一块内存空间: * 结束当前的采样周期,将已采样的数据存到磁盘,并释放这一块内存空间:
...@@ -320,8 +320,8 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 ...@@ -320,8 +320,8 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080
def text(tag) def text(tag)
``` ```
> :param tag : 标签,结合 LogWriter 设定的模式,决定文本显示的子框。 > :param tag : 标签,结合 LogWriter 设定的模式,决定文本显示的子框。
> :return: 函数返回一个 TextWriter 对象。 > :return: 函数返回一个 TextWriter 对象。
* text 组件的成员函数 `add_record()` * text 组件的成员函数 `add_record()`
...@@ -329,7 +329,7 @@ def text(tag) ...@@ -329,7 +329,7 @@ def text(tag)
def add_record(step, str) def add_record(step, str)
``` ```
> :param step : 步进数,标记这是第几组添加的数据。 > :param step : 步进数,标记这是第几组添加的数据。
> :param str : 输入文本,数据类型为 string。 > :param str : 输入文本,数据类型为 string。
例6 text 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/text-demo.py) 例6 text 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/text-demo.py)
...@@ -372,13 +372,13 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 ...@@ -372,13 +372,13 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080
* LogWriter 对象的成员函数 `audio()` * LogWriter 对象的成员函数 `audio()`
```python ```python
def audio(tag, num_samples, step_cycle) def audio(tag, num_samples, step_cycle)
``` ```
> :param tag : 标签,结合 set_sample() 的参数 index,决定音频播放的子框。 > :param tag : 标签,结合 set_sample() 的参数 index,决定音频播放的子框。
> :param num_samples : 设置单个 step 的采样数,页面上的音频数目也等于 num_samples。 > :param num_samples : 设置单个 step 的采样数,页面上的音频数目也等于 num_samples。
> :param step_cycle : 将 step_cycle 个 step 的数据存储到日志中,默认值为 1。 > :param step_cycle : 将 step_cycle 个 step 的数据存储到日志中,默认值为 1。
> :return: 函数返回一个 AudioWriter 对象。 > :return: 函数返回一个 AudioWriter 对象。
* 开始新的采样周期 - 开辟一块内存空间,用于存放采样的数据: * 开始新的采样周期 - 开辟一块内存空间,用于存放采样的数据:
...@@ -389,18 +389,18 @@ def start_sampling() ...@@ -389,18 +389,18 @@ def start_sampling()
* 判断该音频是否应被采样,当返回值为 `-1`,表示不用采样,否则,应被采样: * 判断该音频是否应被采样,当返回值为 `-1`,表示不用采样,否则,应被采样:
```python ```python
def is_sample_taken() def is_sample_taken()
``` ```
* 使用函数 `set_sample()` 添加音频数据: * 使用函数 `set_sample()` 添加音频数据:
```python ```python
def set_sample(index, audio_params, audio_data) def set_sample(index, audio_params, audio_data)
``` ```
> :param index : 索引号,结合 tag,决定音频播放的子框。 > :param index : 索引号,结合 tag,决定音频播放的子框。
> :param audio_params : 音频的参数 [sample rate, sample width, channel],其中 sample rate 为采样率, sample width 为每一帧采样的字节数, channel 为通道数(单声道设为1,双声道设为2,四声道设为4,以此类推)。 > :param audio_params : 音频的参数 [sample rate, sample width, channel],其中 sample rate 为采样率, sample width 为每一帧采样的字节数, channel 为通道数(单声道设为1,双声道设为2,四声道设为4,以此类推)。
> :param audio_data :音频数据,音频数据的格式一般为 numpy.ndarray,经 flatten() 后变为行向量。 > :param audio_data :音频数据,音频数据的格式一般为 numpy.ndarray,经 flatten() 后变为行向量。
* 结束当前的采样周期,将已采样的数据存到磁盘,并释放这一块内存空间: * 结束当前的采样周期,将已采样的数据存到磁盘,并释放这一块内存空间:
...@@ -486,8 +486,8 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 ...@@ -486,8 +486,8 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080
<a name="6">high dimensional</a> 组件的作用就是将数据映射到 2D/3D 空间来做可视化嵌入,这有利于了解不同数据的相关性。high dimensional 组件支持以下两种降维算法: <a name="6">high dimensional</a> 组件的作用就是将数据映射到 2D/3D 空间来做可视化嵌入,这有利于了解不同数据的相关性。high dimensional 组件支持以下两种降维算法:
* PCA : Principle Component Analysis 主成分分析 * PCA : Principle Component Analysis 主成分分析
* [t-SNE](https://lvdmaaten.github.io/tsne/) : t-distributed stochastic neighbor embedding t-分布式随机领域嵌入 * [t-SNE](https://lvdmaaten.github.io/tsne/) : t-distributed stochastic neighbor embedding t-分布式随机领域嵌入
想使用 high dimensional 组件,只需先设定 LogWriter 对象的成员函数 `embedding()`,即可使用 `add_embeddings_with_word_dict()` 函数添加数据。这两个函数的定义及用法如下: 想使用 high dimensional 组件,只需先设定 LogWriter 对象的成员函数 `embedding()`,即可使用 `add_embeddings_with_word_dict()` 函数添加数据。这两个函数的定义及用法如下:
...@@ -503,8 +503,8 @@ def embedding() ...@@ -503,8 +503,8 @@ def embedding()
def add_embeddings_with_word_dict(data, Dict) def add_embeddings_with_word_dict(data, Dict)
``` ```
> :param data : 输入数据,数据类型为 List[List(float)]。 > :param data : 输入数据,数据类型为 List[List(float)]。
> :param Dict : 字典, 数据类型为 Dict[str, int]。 > :param Dict : 字典, 数据类型为 Dict[str, int]。
例8 high dimensional 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/embedding-demo.py) 例8 high dimensional 组件示例程序 [Github](https://github.com/PaddlePaddle/VisualDL/blob/develop/demo/component/embedding-demo.py)
...@@ -619,4 +619,4 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 --model_pb paddle_lenet_5_mod ...@@ -619,4 +619,4 @@ visualdl --logdir ./log --host 0.0.0.0 --port 8080 --model_pb paddle_lenet_5_mod
<p align="center"> <p align="center">
<img src="https://raw.githubusercontent.com/PaddlePaddle/VisualDL/develop/demo/component/usage-interface/graph.png" width=800><br/> <img src="https://raw.githubusercontent.com/PaddlePaddle/VisualDL/develop/demo/component/usage-interface/graph.png" width=800><br/>
图8. graph 组件展示 Lenet-5 的模型结构 <br/> 图8. graph 组件展示 Lenet-5 的模型结构 <br/>
</p> </p>
\ No newline at end of file
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册