提交 b5b700f4 编写于 作者: J JZ-LIANG

Merge remote-tracking branch 'upstream/develop' into fleet20_api_cn

...@@ -7,3 +7,13 @@ paddle/optimizer/Dpsgd_cn.rst ...@@ -7,3 +7,13 @@ paddle/optimizer/Dpsgd_cn.rst
paddle/reader/ComposeNotAligned_cn.rst paddle/reader/ComposeNotAligned_cn.rst
paddle/fluid/layers/scatter_cn.rst paddle/fluid/layers/scatter_cn.rst
paddle/tensor/manipulation/scatter_cn.rst paddle/tensor/manipulation/scatter_cn.rst
paddle/distributed/fleet/Fleet_cn.rst
paddle/distributed/fleet/utils/fs/ExecuteError_cn.rst
paddle/distributed/fleet/utils/fs/FSFileExistsError_cn.rst
paddle/distributed/fleet/utils/fs/FSFileNotExistsError_cn.rst
paddle/distributed/fleet/utils/fs/FSShellCmdAborted_cn.rst
paddle/distributed/fleet/utils/fs/FSTimeOut_cn.rst
paddle/distributed/fleet/utils/fs/FS_cn.rst
paddle/distributed/fleet/utils/fs/HDFSClient_cn.rst
paddle/distributed/fleet/utils/fs/LocalFS_cn.rst
upgrade_guide_cn.md
#!/bin/bash #!/bin/bash
set -x
git_files=`git diff --numstat upstream/$BRANCH | awk '{print $NF}'` function build_paddle() {
git clone https://github.com/PaddlePaddle/Paddle.git
mkdir Paddle/build
cd Paddle/build
for file in `echo $git_files`;do cmake .. -DWITH_GPU=ON -DWITH_COVERAGE=OFF -DWITH_TESTING=OFF -DCMAKE_BUILD_TYPE=Release
grep "code-block" ../$file make -j`nproc`
if [ $? -eq 0 ] ;then pip install -U python/dist/paddlepaddle_gpu-0.0.0-cp27-cp27mu-linux_x86_64.whl
echo $file | grep "doc/paddle/api/paddle/.*_cn.rst"
if [ $? -eq 0 ];then cd -
api_file=`echo $file | sed 's#doc/paddle/api/##g'` }
grep -w "${api_file}" ${DIR_PATH}/api_white_list.txt
if [ $? -ne 0 ];then need_check_files=""
function find_need_check_files() {
git_files=`git diff --numstat upstream/$BRANCH | awk '{print $NF}'`
for file in `echo $git_files`;do
grep "code-block" ../$file
if [ $? -eq 0 ] ;then
echo $file | grep "doc/paddle/api/paddle/.*_cn.rst"
if [ $? -eq 0 ];then
api_file=`echo $file | sed 's#doc/paddle/api/##g'`
grep -w "${api_file}" ${DIR_PATH}/api_white_list.txt
if [ $? -ne 0 ];then
need_check_files="${need_check_files} $file"
fi
fi
fi
done
}
need_check_cn_doc_files=`git diff --numstat upstream/$BRANCH | awk '{print $NF}' | grep "doc/paddle/api/paddle/.*_cn.rst" | sed 's#doc/##g'`
echo $need_check_cn_doc_files
find_need_check_files
if [ "$need_check_files" = "" -a "$need_check_cn_doc_files" = "" ]
then
echo "need check files is empty, skip chinese api check"
else
echo "need check files is not empty, begin to build and install paddle"
build_paddle
if [ $? -ne 0 ];then
echo "paddle build error"
exit 5
fi
if [ "${need_check_files}" != "" ]; then
for file in $need_check_files;do
python chinese_samplecode_processor.py ../$file python chinese_samplecode_processor.py ../$file
if [ $? -ne 0 ];then if [ $? -ne 0 ];then
echo "chinese sample code failed" echo "chinese sample code failed, the file is ${file}"
exit 5 exit 5
fi fi
fi done
fi fi
fi
done
if [ "${need_check_cn_doc_files}" != "" ];then
cd ../doc/paddle/api
python gen_doc.py
cd -
for file in $need_check_cn_doc_files; do
cat ../doc/paddle/api/en_cn_files_diff | awk '{print $1}' | grep ${file}
if [ $? -eq 0 ];then
echo "Chinese doc file exist, but the Englist doc does not exist, the Chinese file is ${file}"
fi
done
fi
fi
#!/bin/bash #!/bin/bash
set -x
API_FILES=("doc/paddle/api/paddle") API_FILES=("doc/paddle/api/paddle")
for API_FILE in ${API_FILES[*]}; do for API_FILE in ${API_FILES[*]}; do
......
...@@ -60,7 +60,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就 ...@@ -60,7 +60,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
......
...@@ -60,7 +60,7 @@ Load model and run it in static graph mode: ...@@ -60,7 +60,7 @@ Load model and run it in static graph mode:
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance: However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance:
......
...@@ -10,7 +10,6 @@ dataset ...@@ -10,7 +10,6 @@ dataset
dataset/imdb.rst dataset/imdb.rst
dataset/imikolov.rst dataset/imikolov.rst
dataset/movielens.rst dataset/movielens.rst
dataset/sentiment.rst
dataset/uci_housing.rst dataset/uci_housing.rst
dataset/wmt14.rst dataset/wmt14.rst
dataset/wmt16.rst dataset/wmt16.rst
sentiment
+++++++++
.. automodule:: paddle.dataset.sentiment
:members:
:noindex:
======== ========
paddle.io fluid.io
======== ========
.. toctree:: .. toctree::
...@@ -7,14 +7,10 @@ paddle.io ...@@ -7,14 +7,10 @@ paddle.io
io/batch.rst io/batch.rst
io/BatchSampler.rst io/BatchSampler.rst
io/buffered.rst
io/cache.rst
io/chain.rst
io/compose.rst
io/ComposeNotAligned.rst io/ComposeNotAligned.rst
io/DataLoader.rst io/DataLoader.rst
io/Dataset.rst io/Dataset.rst
io/firstn.rst io/default_collate_fn.rst
io/get_program_parameter.rst io/get_program_parameter.rst
io/get_program_persistable_vars.rst io/get_program_persistable_vars.rst
io/load.rst io/load.rst
...@@ -23,17 +19,10 @@ paddle.io ...@@ -23,17 +19,10 @@ paddle.io
io/load_persistables.rst io/load_persistables.rst
io/load_program_state.rst io/load_program_state.rst
io/load_vars.rst io/load_vars.rst
io/map_readers.rst
io/multiprocess_reader.rst
io/PyReader.rst io/PyReader.rst
io/save.rst io/save.rst
io/save_inference_model.rst io/save_inference_model.rst
io/save_inference_model.rst
io/save_params.rst io/save_params.rst
io/save_persistables.rst io/save_persistables.rst
io/save_vars.rst io/save_vars.rst
io/set_program_state.rst io/set_program_state.rst
io/set_program_state.rst
io/shuffle.rst
io/shuffle.rst
io/xmap_readers.rst
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_buffered:
buffered
--------
.. autofunction:: paddle.fluid.io.buffered
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_cache:
cache
-----
.. autofunction:: paddle.fluid.io.cache
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_chain:
chain
-----
.. autofunction:: paddle.fluid.io.chain
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}` .. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY! !DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_compose: .. _api_fluid_io_default_collate_fn:
compose default_collate_fn
------- ------------------
.. autofunction:: paddle.fluid.io.compose .. autofunction:: paddle.fluid.io.default_collate_fn
:noindex: :noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_firstn:
firstn
------
.. autofunction:: paddle.fluid.io.firstn
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_map_readers:
map_readers
-----------
.. autofunction:: paddle.fluid.io.map_readers
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_multiprocess_reader:
multiprocess_reader
-------------------
.. autofunction:: paddle.fluid.io.multiprocess_reader
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_shuffle:
shuffle
-------
.. autofunction:: paddle.fluid.io.shuffle
:noindex:
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_xmap_readers:
xmap_readers
------------
.. autofunction:: paddle.fluid.io.xmap_readers
:noindex:
...@@ -14,7 +14,6 @@ dataset ...@@ -14,7 +14,6 @@ dataset
dataset_cn/imdb_cn.rst dataset_cn/imdb_cn.rst
dataset_cn/imikolov_cn.rst dataset_cn/imikolov_cn.rst
dataset_cn/movielens_cn.rst dataset_cn/movielens_cn.rst
dataset_cn/sentiment_cn.rst
dataset_cn/uci_housing_cn.rst dataset_cn/uci_housing_cn.rst
dataset_cn/wmt14_cn.rst dataset_cn/wmt14_cn.rst
dataset_cn/wmt16_cn.rst dataset_cn/wmt16_cn.rst
.. _cn_api_paddle_dataset_sentiment:
sentiment
-------------------------------
脚本获取并预处理由NLTK提供的movie_reviews数据集。
.. py:function:: paddle.dataset.sentiment.get_word_dict()
按照样本中出现的单词的频率对单词进行排序。
返回: words_freq_sorted
.. py:function:: paddle.dataset.sentiment.train()
默认的训练集reader creator。
.. py:function:: paddle.dataset.sentiment.test()
默认的测试集reader creator。
.. py:function:: paddle.dataset.sentiment.convert(path)
将数据集转换为recordio格式。
...@@ -7,8 +7,8 @@ save ...@@ -7,8 +7,8 @@ save
.. py:function:: paddle.fluid.save(program, model_path) .. py:function:: paddle.fluid.save(program, model_path)
:api_attr: 声明式编程模式(静态图) :api_attr: 声明式编程模式(静态图)
:alias_main: paddle.save :alias_main: paddle.static.save
:alias: paddle.save,paddle.tensor.save,paddle.tensor.io.save :alias: paddle.static.save
:old_api: paddle.fluid.save :old_api: paddle.fluid.save
......
...@@ -6,8 +6,8 @@ load ...@@ -6,8 +6,8 @@ load
.. py:function:: paddle.fluid.io.load(program, model_path, executor=None, var_list=None) .. py:function:: paddle.fluid.io.load(program, model_path, executor=None, var_list=None)
:api_attr: 声明式编程模式(静态图) :api_attr: 声明式编程模式(静态图)
:alias_main: paddle.load :alias_main: paddle.static.load
:alias: paddle.load,paddle.tensor.load,paddle.tensor.io.load :alias: paddle.static.load
:old_api: paddle.fluid.io.load :old_api: paddle.fluid.io.load
......
...@@ -40,13 +40,13 @@ add_position_encoding ...@@ -40,13 +40,13 @@ add_position_encoding
.. code-block:: python .. code-block:: python
import paddle.fluid as fluid import numpy as np
import paddle
import paddle.nn.functional as F
tensor = fluid.data( tensor = np.random.randn(16, 32, 64)
name='tensor', tensor = paddle.to_tensor(tensor)
shape=[None, 64, 512], position_tensor = F.add_position_encoding(
dtype='float32')
position_tensor = fluid.layers.add_position_encoding(
input=tensor, alpha=1.0, beta=1.0) input=tensor, alpha=1.0, beta=1.0)
......
...@@ -14,7 +14,7 @@ warpctc ...@@ -14,7 +14,7 @@ warpctc
该OP用于计算 `CTC loss <https://www.cs.toronto.edu/~graves/icml_2006.pdf>`_ 。该OP的底层调用了第三方 `baidu-research::warp-ctc <https://github.com/baidu-research/warp-ctc>`_ 的实现。 该OP用于计算 `CTC loss <https://www.cs.toronto.edu/~graves/icml_2006.pdf>`_ 。该OP的底层调用了第三方 `baidu-research::warp-ctc <https://github.com/baidu-research/warp-ctc>`_ 的实现。
参数: 参数:
- **input** (Variable) - 可以是3-D Tensor或2-D LoDTensor。当输入类型是3-D Tensor时,则表示输入是经过padding的定长序列,其 shape 必须是 ``[seq_length, batch_size, num_classes + 1]`` 。当输入类型是2-D LoDTensor时,则表示输入为变长序列,其shape必须为 ``[Lp,num_classes+1]`` , ``Lp`` 是所有输入序列长度之和。以上 shape 中的 ``num_classes`` 是实际类别数,不包括空白标签。该输入不需要经过 softmax 操作,因为该OP的内部对 ``input`` 做了 softmax 操作。数据类型仅支持float32 - **input** (Variable) - 可以是3-D Tensor或2-D LoDTensor。当输入类型是3-D Tensor时,则表示输入是经过padding的定长序列,其 shape 必须是 ``[seq_length, batch_size, num_classes + 1]`` 。当输入类型是2-D LoDTensor时,则表示输入为变长序列,其shape必须为 ``[Lp,num_classes+1]`` , ``Lp`` 是所有输入序列长度之和。以上 shape 中的 ``num_classes`` 是实际类别数,不包括空白标签。该输入不需要经过 softmax 操作,因为该OP的内部对 ``input`` 做了 softmax 操作。数据类型支持 float32 和 float64
- **label** (Variable) - 可以是3-D Tensor或2-D LoDTensor,需要跟 ``input`` 保持一致。当输入类型为3-D Tensor时,表示输入是经过 padding 的定长序列,其 shape 为 ``[batch_size, label_length]`` ,其中, ``label_length`` 是最长的 label 序列的长度。当输入类型是2-D LoDTensor时,则表示输入为变长序列,其shape必须为 ``[Lp, 1]`` , 其中 ``Lp`` 是所有 label 序列的长度和。 ``label`` 中的数值为字符ID。数据类型支持int32。 - **label** (Variable) - 可以是3-D Tensor或2-D LoDTensor,需要跟 ``input`` 保持一致。当输入类型为3-D Tensor时,表示输入是经过 padding 的定长序列,其 shape 为 ``[batch_size, label_length]`` ,其中, ``label_length`` 是最长的 label 序列的长度。当输入类型是2-D LoDTensor时,则表示输入为变长序列,其shape必须为 ``[Lp, 1]`` , 其中 ``Lp`` 是所有 label 序列的长度和。 ``label`` 中的数值为字符ID。数据类型支持int32。
- **blank** (int,可选) - 空格标记的ID,其取值范围为 ``[0,num_classes+1)`` 。数据类型支持int32。缺省值为0。 - **blank** (int,可选) - 空格标记的ID,其取值范围为 ``[0,num_classes+1)`` 。数据类型支持int32。缺省值为0。
- **norm_by_times** (bool,可选) - 是否根据序列长度对梯度进行正则化。数据类型支持 bool 。缺省值为False。 - **norm_by_times** (bool,可选) - 是否根据序列长度对梯度进行正则化。数据类型支持 bool 。缺省值为False。
......
...@@ -8,7 +8,7 @@ ctc_loss ...@@ -8,7 +8,7 @@ ctc_loss
参数 参数
::::::::: :::::::::
- **log_probs** (Tensor): - 经过 padding 的概率序列,其 shape 必须是 [max_logit_length, batch_size, num_classes + 1]。其中 max_logit_length 是最长输入序列的长度。该输入不需要经过 softmax 操作,因为该 OP 的内部对 input 做了 softmax 操作。数据类型仅支持float32 - **log_probs** (Tensor): - 经过 padding 的概率序列,其 shape 必须是 [max_logit_length, batch_size, num_classes + 1]。其中 max_logit_length 是最长输入序列的长度。该输入不需要经过 softmax 操作,因为该 OP 的内部对 input 做了 softmax 操作。数据类型支持 float32 和 float64
- **labels** (Tensor): - 经过 padding 的标签序列,其 shape 为 [batch_size, max_label_length],其中 max_label_length 是最长的 label 序列的长度。数据类型支持int32。 - **labels** (Tensor): - 经过 padding 的标签序列,其 shape 为 [batch_size, max_label_length],其中 max_label_length 是最长的 label 序列的长度。数据类型支持int32。
- **input_lengths** (Tensor): - 表示输入 ``log_probs`` 数据中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。 - **input_lengths** (Tensor): - 表示输入 ``log_probs`` 数据中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。
- **label_lengths** (Tensor): - 表示 label 中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。 - **label_lengths** (Tensor): - 表示 label 中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。
......
...@@ -13,7 +13,7 @@ CTCLoss ...@@ -13,7 +13,7 @@ CTCLoss
形状 形状
::::::::: :::::::::
- **log_probs** (Tensor): - 经过 padding 的概率序列,其 shape 必须是 [max_logit_length, batch_size, num_classes + 1]。其中 max_logit_length 是最长输入序列的长度。该输入不需要经过 softmax 操作,因为该 OP 的内部对 input 做了 softmax 操作。数据类型仅支持float32 - **log_probs** (Tensor): - 经过 padding 的概率序列,其 shape 必须是 [max_logit_length, batch_size, num_classes + 1]。其中 max_logit_length 是最长输入序列的长度。该输入不需要经过 softmax 操作,因为该 OP 的内部对 input 做了 softmax 操作。数据类型支持 float32 和 float64
- **labels** (Tensor): - 经过 padding 的标签序列,其 shape 为 [batch_size, max_label_length],其中 max_label_length 是最长的 label 序列的长度。数据类型支持int32。 - **labels** (Tensor): - 经过 padding 的标签序列,其 shape 为 [batch_size, max_label_length],其中 max_label_length 是最长的 label 序列的长度。数据类型支持int32。
- **input_lengths** (Tensor): - 表示输入 ``log_probs`` 数据中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。 - **input_lengths** (Tensor): - 表示输入 ``log_probs`` 数据中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。
- **label_lengths** (Tensor): - 表示 label 中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。 - **label_lengths** (Tensor): - 表示 label 中每个序列的长度,shape为 [batch_size] 。数据类型支持int64。
......
...@@ -204,8 +204,8 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别 ...@@ -204,8 +204,8 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别
path = "./models" path = "./models"
startup_prog = fluid.default_startup_program() startup_prog = fluid.default_startup_program()
exe.run(startup_prog) exe.run(startup_prog)
fluid.io.load_persistables(exe, path, startup_prog)
main_prog = fluid.default_main_program() main_prog = fluid.default_main_program()
fluid.io.load_persistables(exe, path, main_prog)
exe.run(main_prog) exe.run(main_prog)
上面的例子中,通过调用 :code:`fluid.io.load_persistables` 函数,PaddlePaddle Fluid会从默认 上面的例子中,通过调用 :code:`fluid.io.load_persistables` 函数,PaddlePaddle Fluid会从默认
...@@ -270,12 +270,12 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别 ...@@ -270,12 +270,12 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别
pserver_endpoints = "127.0.0.1:1001,127.0.0.1:1002" pserver_endpoints = "127.0.0.1:1001,127.0.0.1:1002"
trainers = 4 trainers = 4
training_role == "PSERVER" training_role == "PSERVER"
current_endpoint = "127.0.0.1:1002"
config = fluid.DistributeTranspilerConfig() config = fluid.DistributeTranspilerConfig()
t = fluid.DistributeTranspiler(config=config) t = fluid.DistributeTranspiler(config=config)
t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers, sync_mode=True, current_endpoint=current_endpoint) t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers, sync_mode=True, current_endpoint=current_endpoint)
if training_role == "PSERVER": if training_role == "PSERVER":
current_endpoint = "127.0.0.1:1001"
pserver_prog = t.get_pserver_program(current_endpoint) pserver_prog = t.get_pserver_program(current_endpoint)
pserver_startup = t.get_startup_program(current_endpoint, pserver_prog) pserver_startup = t.get_startup_program(current_endpoint, pserver_prog)
...@@ -284,7 +284,7 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别 ...@@ -284,7 +284,7 @@ save_vars、save_params、save_persistables 以及 save_inference_model的区别
exe.run(pserver_prog) exe.run(pserver_prog)
if training_role == "TRAINER": if training_role == "TRAINER":
main_program = t.get_trainer_program() main_program = t.get_trainer_program()
exe.run(main_program) exe.run(main_program)
上面的例子中,每个PServer通过调用HDFS的命令获取到0号trainer保存的参数,通过配置获取到PServer的 :code:`fluid.Program` ,PaddlePaddle Fluid会从此 上面的例子中,每个PServer通过调用HDFS的命令获取到0号trainer保存的参数,通过配置获取到PServer的 :code:`fluid.Program` ,PaddlePaddle Fluid会从此
:code:`fluid.Program` 也就是 :code:`pserver_startup` 的所有模型变量中找出长期变量,并通过指定的 :code:`path` 目录下一一加载。 :code:`fluid.Program` 也就是 :code:`pserver_startup` 的所有模型变量中找出长期变量,并通过指定的 :code:`path` 目录下一一加载。
......
...@@ -27,23 +27,6 @@ How to save model variables ...@@ -27,23 +27,6 @@ How to save model variables
The model variables we need to save are different depending on the application. For example, if we just want to save the model for future predictions, just saving the model parameters will be enough. But if we need to save a checkpoint for future recovery of current training, then we should save all the persistable variables, and even record the current epoch and step id. It is because even though some model variables are not parameters, they are still essential for model training. The model variables we need to save are different depending on the application. For example, if we just want to save the model for future predictions, just saving the model parameters will be enough. But if we need to save a checkpoint for future recovery of current training, then we should save all the persistable variables, and even record the current epoch and step id. It is because even though some model variables are not parameters, they are still essential for model training.
Difference between save_vars、save_params、save_persistables and save_inference_model
##########################################################################
1. :code:`save_inference_model` will prune the inference model based on :code:`feeded_var_names` and :code:`target_vars` , this method will save the ``__model__`` file of the pruned program and the persistable variables in the program.
2. :code:`save_persistables` this method will not save model, it will save all the persistable variables in the program.
3. :code:`save_params` this method will not save model, it will save all the parameters in the program.
4. :code:`save_vars` this method will not save model, it will save the given parameter by user.
:code:`save_persistables` this method is useful for increment training or checkpoint training, it can save persistable variables in program comprehensively, such as parameter variables, optimizer variables, if you need increment training or checkpoint training, please choose this one.
:code:`save_inference_model` this method is useful for inference, it will save persistable variables and pruned program, if you need program and variables for follow-up high performance inference, please choose this one.
:code:`save_vars 和 save_params` there methods are only needed in particular cases, we suppose you already know the purpose of there APIs, there are not recommended for use normally.
Save the model to make prediction for new samples Save the model to make prediction for new samples
=================================================== ===================================================
...@@ -143,8 +126,8 @@ In the above example, by calling the :code:`fluid.io.save_persistables` function ...@@ -143,8 +126,8 @@ In the above example, by calling the :code:`fluid.io.save_persistables` function
path = "./models" path = "./models"
startup_prog = fluid.default_startup_program() startup_prog = fluid.default_startup_program()
exe.run(startup_prog) exe.run(startup_prog)
fluid.io.load_persistables(exe, path, startup_prog)
main_prog = fluid.default_main_program() main_prog = fluid.default_main_program()
fluid.io.load_persistables(exe, path, main_prog)
exe.run(main_prog) exe.run(main_prog)
In the above example, by calling the :code:`fluid.io.load_persistables` function, PaddlePaddle Fluid will find persistable variables from all model variables in the default :code:`fluid.Program` , e.t. :code:`prog` . and load them one by one from the specified :code:`path` directory to continue training. In the above example, by calling the :code:`fluid.io.load_persistables` function, PaddlePaddle Fluid will find persistable variables from all model variables in the default :code:`fluid.Program` , e.t. :code:`prog` . and load them one by one from the specified :code:`path` directory to continue training.
...@@ -196,23 +179,23 @@ For the PServer to be loaded with parameters during training, for example: ...@@ -196,23 +179,23 @@ For the PServer to be loaded with parameters during training, for example:
exe = fluid.Executor(fluid.CPUPlace()) exe = fluid.Executor(fluid.CPUPlace())
path = "./models" path = "./models"
pserver_endpoints = "127.0.0.1:1001,127.0.0.1:1002" pserver_endpoints = "127.0.0.1:1001,127.0.0.1:1002"
trainers = 4 trainers = 4
Training_role == "PSERVER" Training_role == "PSERVER"
config = fluid.DistributeTranspilerConfig() current_endpoint = "127.0.0.1:1002"
t = fluid.DistributeTranspiler(config=config) config = fluid.DistributeTranspilerConfig()
t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers, sync_mode=True) t = fluid.DistributeTranspiler(config=config)
t.transpile(trainer_id, pservers=pserver_endpoints, trainers=trainers, sync_mode=True, current_endpoint=current_endpoint)
if training_role == "PSERVER":
current_endpoint = "127.0.0.1:1001" if training_role == "PSERVER":
pserver_prog = t.get_pserver_program(current_endpoint) pserver_prog = t.get_pserver_program(current_endpoint)
pserver_startup = t.get_startup_program(current_endpoint, pserver_prog) pserver_startup = t.get_startup_program(current_endpoint, pserver_prog)
exe.run(pserver_startup) exe.run(pserver_startup)
fluid.io.load_persistables(exe, path, pserver_startup) fluid.io.load_persistables(exe, path, pserver_startup)
exe.run(pserver_prog) exe.run(pserver_prog)
if training_role == "TRAINER": if training_role == "TRAINER":
main_program = t.get_trainer_program() main_program = t.get_trainer_program()
exe.run(main_program) exe.run(main_program)
In the above example, each PServer obtains the parameters saved by trainer 0 by calling the HDFS command, and obtains the PServer's :code:`fluid.Program` by configuration. PaddlePaddle Fluid will find all persistable variables in all model variables from this :code:`fluid.Program` , e.t. :code:`pserver_startup` , and load them from the specified :code:`path` directory. In the above example, each PServer obtains the parameters saved by trainer 0 by calling the HDFS command, and obtains the PServer's :code:`fluid.Program` by configuration. PaddlePaddle Fluid will find all persistable variables in all model variables from this :code:`fluid.Program` , e.t. :code:`pserver_startup` , and load them from the specified :code:`path` directory.
...@@ -551,7 +551,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0]) ...@@ -551,7 +551,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0])
# 声明式编程中需要使用执行器执行之前已经定义好的网络 # 声明式编程中需要使用执行器执行之前已经定义好的网络
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
# 声明式编程中需要调用执行器的run方法执行计算过程 # 声明式编程中需要调用执行器的run方法执行计算过程
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
``` ```
......
...@@ -7,16 +7,16 @@ ...@@ -7,16 +7,16 @@
------------- -------------
.. csv-table:: .. csv-table::
:header: "版本说明", "预测库(1.8.3版本)", "预测库(develop版本)" :header: "版本说明", "预测库(1.8.4版本)", "预测库(2.0.0-beta0版本)", "预测库(develop版本)"
:widths: 3, 2, 2 :widths: 3, 2, 2, 2
"ubuntu14.04_cpu_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cpu_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-cpu-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cpu_avx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-avx-openblas/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-openblas/fluid_inference.tgz>`_" "ubuntu14.04_cpu_avx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-avx-openblas/fluid_inference.tgz>`_", ,"`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-openblas/paddle_inference.tgz>`_"
"ubuntu14.04_cpu_noavx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-noavx-openblas/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-noavx-openblas/fluid_inference.tgz>`_" "ubuntu14.04_cpu_noavx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-noavx-openblas/fluid_inference.tgz>`_", ,"`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-noavx-openblas/paddle_inference.tgz>`_"
"ubuntu14.04_cuda9.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cuda9.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda9-cudnn7-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda9-cudnn7-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cuda10.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cuda10.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda10-cudnn7-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda10-cudnn7-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cuda10.1_cudnn7.6_avx_mkl_trt6", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Ffluid_inference.tgz>`_", "ubuntu14.04_cuda10.1_cudnn7.6_avx_mkl_trt6", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Ffluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Fpaddle_inference.tgz>`_",
"nv-jetson-cuda10-cudnn7.5-trt5", "`fluid_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/1.7.1-nv-jetson-cuda10-cudnn7.5-trt5/fluid_inference.tar.gz>`_", "nv-jetson-cuda10-cudnn7.5-trt5", "`fluid_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/1.7.1-nv-jetson-cuda10-cudnn7.5-trt5/fluid_inference.tar.gz>`_", "`paddle_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-nv-jetson-cuda10-cudnn7.5-trt5/paddle_inference.tgz>`_",
从源码编译 从源码编译
...@@ -46,7 +46,7 @@ WITH_NV_JETSON OFF 在NV Jetson硬件上编译时需 ...@@ -46,7 +46,7 @@ WITH_NV_JETSON OFF 在NV Jetson硬件上编译时需
git clone https://github.com/paddlepaddle/Paddle git clone https://github.com/paddlepaddle/Paddle
cd Paddle cd Paddle
# 建议使用git checkout切换到Paddle稳定的版本,如: # 建议使用git checkout切换到Paddle稳定的版本,如:
git checkout v1.7.2 git checkout v1.8.4
**note**: 如果您是多卡机器,建议安装NCCL;如果您是单卡机器则可以在编译时显示指定WITH_NCCL=OFF来跳过这一步。注意如果WITH_NCCL=ON,且没有安装NCCL,则编译会报错。 **note**: 如果您是多卡机器,建议安装NCCL;如果您是单卡机器则可以在编译时显示指定WITH_NCCL=OFF来跳过这一步。注意如果WITH_NCCL=ON,且没有安装NCCL,则编译会报错。
...@@ -188,3 +188,4 @@ version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使 ...@@ -188,3 +188,4 @@ version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使
WITH_GPU: ON WITH_GPU: ON
CUDA version: 10.1 CUDA version: 10.1
CUDNN version: v7 CUDNN version: v7
...@@ -7,16 +7,16 @@ Direct Download and Installation ...@@ -7,16 +7,16 @@ Direct Download and Installation
--------------------------------- ---------------------------------
.. csv-table:: c++ inference library list .. csv-table:: c++ inference library list
:header: "version description", "inference library(1.8.3 version)", "inference library(develop version)" :header: "version description", "inference library(1.8.4 version)", "inference library(2.0.0-beta0 version)", "inference library(develop version)"
:widths: 3, 2, 2 :widths: 3, 2, 2, 2
"ubuntu14.04_cpu_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cpu_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-cpu-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cpu_avx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-avx-openblas/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-openblas/fluid_inference.tgz>`_" "ubuntu14.04_cpu_avx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-avx-openblas/fluid_inference.tgz>`_", ,"`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-avx-openblas/paddle_inference.tgz>`_"
"ubuntu14.04_cpu_noavx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-cpu-noavx-openblas/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-noavx-openblas/fluid_inference.tgz>`_" "ubuntu14.04_cpu_noavx_openblas", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-cpu-noavx-openblas/fluid_inference.tgz>`_", ,"`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-cpu-noavx-openblas/paddle_inference.tgz>`_"
"ubuntu14.04_cuda9.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cuda9.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda9-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda9-cudnn7-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda9-cudnn7-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cuda10.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_" "ubuntu14.04_cuda10.0_cudnn7_avx_mkl", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda10-cudnn7-avx-mkl/fluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda10-cudnn7-avx-mkl/paddle_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/latest-gpu-cuda10-cudnn7-avx-mkl/paddle_inference.tgz>`_"
"ubuntu14.04_cuda10.1_cudnn7.6_avx_mkl_trt6", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.3-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Ffluid_inference.tgz>`_", "ubuntu14.04_cuda10.1_cudnn7.6_avx_mkl_trt6", "`fluid_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/1.8.4-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Ffluid_inference.tgz>`_", "`paddle_inference.tgz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-gpu-cuda10.1-cudnn7.6-avx-mkl-trt6%2Fpaddle_inference.tgz>`_",
"nv-jetson-cuda10-cudnn7.5-trt5", "`fluid_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/1.7.1-nv-jetson-cuda10-cudnn7.5-trt5/fluid_inference.tar.gz>`_", "nv-jetson-cuda10-cudnn7.5-trt5", "`fluid_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/1.7.1-nv-jetson-cuda10-cudnn7.5-trt5/fluid_inference.tar.gz>`_", "`paddle_inference.tar.gz <https://paddle-inference-lib.bj.bcebos.com/2.0.0-beta0-nv-jetson-cuda10-cudnn7.5-trt5/paddle_inference.tgz>`_",
Build from Source Code Build from Source Code
----------------------- -----------------------
...@@ -46,8 +46,8 @@ Firstly we pull the latest code from github. ...@@ -46,8 +46,8 @@ Firstly we pull the latest code from github.
git clone https://github.com/paddlepaddle/Paddle git clone https://github.com/paddlepaddle/Paddle
cd Paddle cd Paddle
# Use git checkout to switch to stable versions such as v1.7.2 # Use git checkout to switch to stable versions such as v1.8.4
git checkout v1.7.2 git checkout v1.8.4
**note**: If your environment is a multi-card machine, it is recommended to install nccl; otherwise, you can skip this step by specifying WITH_NCCL = OFF during compilation. Note that if WITH_NCCL = ON, and NCCL is not installed, the compiler will report an error. **note**: If your environment is a multi-card machine, it is recommended to install nccl; otherwise, you can skip this step by specifying WITH_NCCL = OFF during compilation. Note that if WITH_NCCL = ON, and NCCL is not installed, the compiler will report an error.
...@@ -202,3 +202,4 @@ The version information of the inference library is recorded in version.txt, inc ...@@ -202,3 +202,4 @@ The version information of the inference library is recorded in version.txt, inc
WITH_GPU: ON WITH_GPU: ON
CUDA version: 8.0 CUDA version: 8.0
CUDNN version: v7 CUDNN version: v7
# C++ 预测 API介绍 # C++ 预测 API介绍
为了更简单方便地预测部署,PaddlePaddle 提供了一套高层 C++ API 预测接口。 为了更简单方便地预测部署,PaddlePaddle 提供了一套高层 C++ API 预测接口。下面是详细介绍。
下面是详细介绍。
如果您在使用2.0之前的Paddle,请参考[旧版API](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.8/advanced_guide/inference_deployment/inference/native_infer.html)文档,升级到新版API请参考[推理升级指南](#推理升级指南)
## 内容 ## 内容
- [使用AnalysisPredictor进行高性能预测](#使用AnalysisPredictor进行高性能预测) - [使用Predictor进行高性能预测](#使用Predictor进行高性能预测)
- [使用AnalysisConfig管理预测配置](#使用AnalysisConfig管理预测配置) - [使用Config管理预测配置](#使用Config管理预测配置)
- [使用ZeroCopyTensor管理输入/输出](#使用ZeroCopyTensor管理输入/输出) - [使用Tensor管理输入/输出](#使用Tensor管理输入/输出)
- [使用PredictorPool在多线程下进行预测](#使用PredictorPool在多线程下进行预测)
- [C++预测样例编译测试](#C++预测样例编译测试) - [C++预测样例编译测试](#C++预测样例编译测试)
- [性能调优](#性能调优) - [性能调优](#性能调优)
- [推理升级指南](#推理升级指南)
- [C++ API](#C++_API)
## <a name="使用Predictor进行高性能预测"> 使用Predictor进行高性能预测</a>
## <a name="使用AnalysisPredictor进行高性能预测"> 使用AnalysisPredictor进行高性能预测</a> Paddle Inference采用 Predictor 进行预测。Predictor 是一个高性能预测引擎,该引擎通过对计算图的分析,完成对计算图的一系列的优化(如OP的融合、内存/显存的优化、 MKLDNN,TensorRT 等底层加速库的支持等),能够大大提升预测性能。
Paddle Fluid采用 AnalysisPredictor 进行预测。AnalysisPredictor 是一个高性能预测引擎,该引擎通过对计算图的分析,完成对计算图的一系列的优化(如OP的融合、内存/显存的优化、 MKLDNN,TensorRT 等底层加速库的支持等),能够大大提升预测性能。
为了展示完整的预测流程,下面是一个使用 AnalysisPredictor 进行预测的完整示例,其中涉及到的具体概念和配置会在后续部分展开详细介绍。 为了展示完整的预测流程,下面是一个使用 Predictor 进行预测的完整示例,其中涉及到的具体概念和配置会在后续部分展开详细介绍。
#### AnalysisPredictor 预测示例 #### Predictor 预测示例
``` c++ ``` c++
#include "paddle_inference_api.h" #include "paddle_inference_api.h"
namespace paddle { namespace paddle_infer {
void CreateConfig(AnalysisConfig* config, const std::string& model_dirname) { void CreateConfig(Config* config, const std::string& model_dirname) {
// 模型从磁盘进行加载 // 模型从磁盘进行加载
config->SetModel(model_dirname + "/model", config->SetModel(model_dirname + "/model",
model_dirname + "/params"); model_dirname + "/params");
// config->SetModel(model_dirname); // config->SetModel(model_dirname);
// 如果模型从内存中加载,可以使用SetModelBuffer接口 // 如果模型从内存中加载,可以使用SetModelBuffer接口
// config->SetModelBuffer(prog_buffer, prog_size, params_buffer, params_size); // config->SetModelBuffer(prog_buffer, prog_size, params_buffer, params_size);
...@@ -41,22 +43,18 @@ void CreateConfig(AnalysisConfig* config, const std::string& model_dirname) { ...@@ -41,22 +43,18 @@ void CreateConfig(AnalysisConfig* config, const std::string& model_dirname) {
config->SetCpuMathLibraryNumThreads(10); config->SetCpuMathLibraryNumThreads(10);
*/ */
// 使用ZeroCopyTensor,此处必须设置为false config->SwitchIrDebug(true); // 可视化调试选项,若开启,则会在每个图优化过程后生成dot文件
config->SwitchUseFeedFetchOps(false); // config->SwitchIrOptim(false); // 默认为true。如果设置为false,关闭所有优化
// 若输入为多个,此处必须设置为true // config->EnableMemoryOptim(); // 开启内存/显存复用
config->SwitchSpecifyInputNames(true);
config->SwitchIrDebug(true); // 可视化调试选项,若开启,则会在每个图优化过程后生成dot文件
// config->SwitchIrOptim(false); // 默认为true。如果设置为false,关闭所有优化
// config->EnableMemoryOptim(); // 开启内存/显存复用
} }
void RunAnalysis(int batch_size, std::string model_dirname) { void RunAnalysis(int batch_size, std::string model_dirname) {
// 1. 创建AnalysisConfig // 1. 创建AnalysisConfig
AnalysisConfig config; Config config;
CreateConfig(&config, model_dirname); CreateConfig(&config, model_dirname);
// 2. 根据config 创建predictor,并准备输入数据,此处以全0数据为例 // 2. 根据config 创建predictor,并准备输入数据,此处以全0数据为例
auto predictor = CreatePaddlePredictor(config); auto predictor = CreatePredictor(config);
int channels = 3; int channels = 3;
int height = 224; int height = 224;
int width = 224; int width = 224;
...@@ -65,50 +63,45 @@ void RunAnalysis(int batch_size, std::string model_dirname) { ...@@ -65,50 +63,45 @@ void RunAnalysis(int batch_size, std::string model_dirname) {
// 3. 创建输入 // 3. 创建输入
// 使用了ZeroCopy接口,可以避免预测中多余的CPU copy,提升预测性能 // 使用了ZeroCopy接口,可以避免预测中多余的CPU copy,提升预测性能
auto input_names = predictor->GetInputNames(); auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]); auto input_t = predictor->GetInputHandle(input_names[0]);
input_t->Reshape({batch_size, channels, height, width}); input_t->Reshape({batch_size, channels, height, width});
input_t->copy_from_cpu(input); input_t->CopyFromCpu(input);
// 4. 运行预测引擎 // 4. 运行预测引擎
CHECK(predictor->ZeroCopyRun()); CHECK(predictor->Run());
// 5. 获取输出 // 5. 获取输出
std::vector<float> out_data; std::vector<float> out_data;
auto output_names = predictor->GetOutputNames(); auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]); auto output_t = predictor->GetOutputHandle(output_names[0]);
std::vector<int> output_shape = output_t->shape(); std::vector<int> output_shape = output_t->shape();
int out_num = std::accumulate(output_shape.begin(), output_shape.end(), 1, std::multiplies<int>()); int out_num = std::accumulate(output_shape.begin(), output_shape.end(), 1, std::multiplies<int>());
out_data.resize(out_num); out_data.resize(out_num);
output_t->copy_to_cpu(out_data.data()); output_t->CopyToCpu(out_data.data());
} }
} // namespace paddle } // namespace paddle_infer
int main() { int main() {
// 模型下载地址 http://paddle-inference-dist.cdn.bcebos.com/tensorrt_test/mobilenet.tar.gz // 模型下载地址 http://paddle-inference-dist.cdn.bcebos.com/tensorrt_test/mobilenet.tar.gz
paddle::RunAnalysis(1, "./mobilenet"); paddle_infer::RunAnalysis(1, "./mobilenet");
return 0; return 0;
} }
``` ```
## <a name="使用AnalysisConfig管理预测配置"> 使用AnalysisConfig管理预测配置</a> ## <a name="使用Config管理预测配置"> 使用Config管理预测配置</a>
AnalysisConfig管理AnalysisPredictor的预测配置,提供了模型路径设置、预测引擎运行设备选择以及多种优化预测流程的选项。配置方法如下: Config管理Predictor的预测配置,提供了模型路径设置、预测引擎运行设备选择以及多种优化预测流程的选项。配置方法如下:
#### 通用优化配置 #### 通用优化配置
``` c++ ``` c++
config->SwitchIrOptim(true); // 开启计算图分析优化,包括OP融合等 config->SwitchIrOptim(true); // 开启计算图分析优化,包括OP融合等
config->EnableMemoryOptim(); // 开启内存/显存复用 config->EnableMemoryOptim(); // 开启内存/显存复用
``` ```
**Note:** 使用ZeroCopyTensor必须设置:
``` c++
config->SwitchUseFeedFetchOps(false); // 关闭feed和fetch OP使用,使用ZeroCopy接口必须设置此项
```
#### 设置模型和参数路径 #### 设置模型和参数路径
从磁盘加载模型时,根据模型和参数文件存储方式不同,设置AnalysisConfig加载模型和参数的路径有两种形式: 从磁盘加载模型时,根据模型和参数文件存储方式不同,设置Config加载模型和参数的路径有两种形式:
* 非combined形式:模型文件夹`model_dir`下存在一个模型文件和多个参数文件时,传入模型文件夹路径,模型文件名默认为`__model__` * 非combined形式:模型文件夹`model_dir`下存在一个模型文件和多个参数文件时,传入模型文件夹路径,模型文件名默认为`__model__`
``` c++ ``` c++
...@@ -124,43 +117,41 @@ config->SetModel("./model_dir/model", "./model_dir/params"); ...@@ -124,43 +117,41 @@ config->SetModel("./model_dir/model", "./model_dir/params");
#### 配置CPU预测 #### 配置CPU预测
``` c++ ``` c++
config->DisableGpu(); // 禁用GPU config->DisableGpu(); // 禁用GPU
config->EnableMKLDNN(); // 开启MKLDNN,可加速CPU预测 config->EnableMKLDNN(); // 开启MKLDNN,可加速CPU预测
config->SetCpuMathLibraryNumThreads(10); // 设置CPU Math库线程数,CPU核心数支持情况下可加速预测 config->SetCpuMathLibraryNumThreads(10); // 设置CPU Math库线程数,CPU核心数支持情况下可加速预测
``` ```
#### 配置GPU预测 #### 配置GPU预测
``` c++ ``` c++
config->EnableUseGpu(100, 0); // 初始化100M显存,使用GPU ID为0 config->EnableUseGpu(100, 0); // 初始化100M显存,使用GPU ID为0
config->GpuDeviceId(); // 返回正在使用的GPU ID config->GpuDeviceId(); // 返回正在使用的GPU ID
// 开启TensorRT预测,可提升GPU预测性能,需要使用带TensorRT的预测库 // 开启TensorRT预测,可提升GPU预测性能,需要使用带TensorRT的预测库
config->EnableTensorRtEngine(1 << 20 /*workspace_size*/, config->EnableTensorRtEngine(1 << 20 /*workspace_size*/,
batch_size /*max_batch_size*/, batch_size /*max_batch_size*/,
3 /*min_subgraph_size*/, 3 /*min_subgraph_size*/,
AnalysisConfig::Precision::kFloat32 /*precision*/, AnalysisConfig::Precision::kFloat32 /*precision*/,
false /*use_static*/, false /*use_static*/,
false /*use_calib_mode*/); false /*use_calib_mode*/);
``` ```
## <a name="使用ZeroCopyTensor管理输入/输出"> 使用ZeroCopyTensor管理输入/输出</a> ## <a name="使用Tensor管理输入/输出"> 使用Tensor管理输入/输出</a>
ZeroCopyTensor是AnalysisPredictor的输入/输出数据结构。ZeroCopyTensor的使用可以避免预测时候准备输入以及获取输出时多余的数据copy,提高预测性能。 Tensor是Predictor的输入/输出数据结构。
**Note:** 使用ZeroCopyTensor,务必在创建config时设置`config->SwitchUseFeedFetchOps(false);`
``` c++ ``` c++
// 通过创建的AnalysisPredictor获取输入和输出的tensor // 通过创建的Predictor获取输入和输出的tensor
auto input_names = predictor->GetInputNames(); auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputTensor(input_names[0]); auto input_t = predictor->GetInputHandle(input_names[0]);
auto output_names = predictor->GetOutputNames(); auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputTensor(output_names[0]); auto output_t = predictor->GetOutputHandle(output_names[0]);
// 对tensor进行reshape // 对tensor进行reshape
input_t->Reshape({batch_size, channels, height, width}); input_t->Reshape({batch_size, channels, height, width});
// 通过copy_from_cpu接口,将cpu数据输入;通过copy_to_cpu接口,将输出数据copy到cpu // 通过CopyFromCpu接口,将cpu数据输入;通过CopyToCpu接口,将输出数据copy到cpu
input_t->copy_from_cpu<float>(input_data /*数据指针*/); input_t->CopyFromCpu<float>(input_data /*数据指针*/);
output_t->copy_to_cpu(out_data /*数据指针*/); output_t->CopyToCpu(out_data /*数据指针*/);
// 设置LOD // 设置LOD
std::vector<std::vector<size_t>> lod_data = {{0}, {0}}; std::vector<std::vector<size_t>> lod_data = {{0}, {0}};
...@@ -172,13 +163,29 @@ int output_size; ...@@ -172,13 +163,29 @@ int output_size;
float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size); float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size);
``` ```
## <a name="使用PredictorPool在多线程下进行预测"> 使用PredictorPool在多线程下进行预测</a>
`PredictorPool``Predictor`进行管理。`PredictorPool``Predictor`进行了简单的封装,通过传入config和thread的数目来完成初始化,在每个线程中,根据自己的线程id直接从池中取出对应的`Predictor`来完成预测过程。
```c++
# 服务初始化时,完成PredictorPool的初始化
PredictorPool pool(config, thread_num);
# 根据线程id来获取Predictor
auto predictor = pool.Retrive(thread_id);
# 使用Predictor进行预测
...
```
## <a name="C++预测样例编译测试"> C++预测样例编译测试</a> ## <a name="C++预测样例编译测试"> C++预测样例编译测试</a>
1. 下载或编译paddle预测库,参考[安装与编译C++预测库](./build_and_install_lib_cn.html) 1. 下载或编译paddle预测库,参考[安装与编译C++预测库](./build_and_install_lib_cn.html)
2. 下载[预测样例](https://paddle-inference-dist.bj.bcebos.com/tensorrt_test/paddle_inference_sample_v1.7.tar.gz)并解压,进入`sample/inference`目录下。 2. 下载[预测样例](https://paddle-inference-dist.bj.bcebos.com/tensorrt_test/paddle_inference_sample_v1.7.tar.gz)并解压,进入`sample/inference`目录下。
`inference` 文件夹目录结构如下: `inference` 文件夹目录结构如下:
``` shell ``` shell
inference inference
├── CMakeLists.txt ├── CMakeLists.txt
├── mobilenet_test.cc ├── mobilenet_test.cc
...@@ -188,12 +195,12 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size); ...@@ -188,12 +195,12 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size);
│ └── params │ └── params
├── run.sh ├── run.sh
└── run_impl.sh └── run_impl.sh
``` ```
- `mobilenet_test.cc` 为单线程预测的C++源文件 - `mobilenet_test.cc` 为单线程预测的C++源文件
- `thread_mobilenet_test.cc` 为多线程预测的C++源文件 - `thread_mobilenet_test.cc` 为多线程预测的C++源文件
- `mobilenetv1` 为模型文件夹 - `mobilenetv1` 为模型文件夹
- `run.sh` 为预测运行脚本文件 - `run.sh` 为预测运行脚本文件
3. 配置编译与运行脚本 3. 配置编译与运行脚本
...@@ -217,11 +224,12 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size); ...@@ -217,11 +224,12 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size);
4. 编译与运行样例 4. 编译与运行样例
``` shell ``` shell
sh run.sh sh run.sh
``` ```
## <a name="性能调优"> 性能调优</a> ## <a name="性能调优"> 性能调优</a>
### CPU下预测 ### CPU下预测
1. 在CPU型号允许的情况下,尽量使用带AVX和MKL的版本。 1. 在CPU型号允许的情况下,尽量使用带AVX和MKL的版本。
2. 可以尝试使用Intel的 MKLDNN 加速。 2. 可以尝试使用Intel的 MKLDNN 加速。
...@@ -231,7 +239,7 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size); ...@@ -231,7 +239,7 @@ float *output_d = output_t->data<float>(PaddlePlace::kGPU, &output_size);
1. 可以尝试打开 TensorRT 子图加速引擎, 通过计算图分析,Paddle可以自动将计算图中部分子图融合,并调用NVIDIA的 TensorRT 来进行加速,详细内容可以参考 [使用Paddle-TensorRT库预测](../../performance_improving/inference_improving/paddle_tensorrt_infer.html) 1. 可以尝试打开 TensorRT 子图加速引擎, 通过计算图分析,Paddle可以自动将计算图中部分子图融合,并调用NVIDIA的 TensorRT 来进行加速,详细内容可以参考 [使用Paddle-TensorRT库预测](../../performance_improving/inference_improving/paddle_tensorrt_infer.html)
### 多线程预测 ### 多线程预测
Paddle Fluid支持通过在不同线程运行多个AnalysisPredictor的方式来优化预测性能,支持CPU和GPU环境。 Paddle Inference支持通过在不同线程运行多个Predictor的方式来优化预测性能,支持CPU和GPU环境。
使用多线程预测的样例详见[C++预测样例编译测试](#C++预测样例编译测试)中下载的[预测样例](https://paddle-inference-dist.bj.bcebos.com/tensorrt_test/paddle_inference_sample_v1.7.tar.gz)中的 使用多线程预测的样例详见[C++预测样例编译测试](#C++预测样例编译测试)中下载的[预测样例](https://paddle-inference-dist.bj.bcebos.com/tensorrt_test/paddle_inference_sample_v1.7.tar.gz)中的
`thread_mobilenet_test.cc`文件。可以将`run.sh``mobilenet_test`替换成`thread_mobilenet_test`再执行 `thread_mobilenet_test.cc`文件。可以将`run.sh``mobilenet_test`替换成`thread_mobilenet_test`再执行
...@@ -241,3 +249,1233 @@ sh run.sh ...@@ -241,3 +249,1233 @@ sh run.sh
``` ```
即可运行多线程预测样例。 即可运行多线程预测样例。
## <a name="推理升级指南"> 推理升级指南</a>
2.0对API做了整理,简化了写法,以及去掉了历史上冗余的概念。
新的 API 为纯增,原有 API 保持不变,在后续版本会逐步删除。
重要变化:
- 命名空间从 `paddle` 变更为 `paddle_infer`
- `PaddleTensor`, `PaddleBuf` 等被废弃,`ZeroCopyTensor` 变为默认 Tensor 类型,并更名为 `Tensor`
- 新增 `PredictorPool` 工具类简化多线程 predictor 的创建,后续也会增加更多周边工具
- `CreatePredictor` (原 `CreatePaddlePredictor`) 的返回值由 `unique_ptr` 变为 `shared_ptr` 以避免 Clone 后析构顺序出错的问题
API 变更
| 原有命名 | 现有命名 | 行为变化 |
| ---------------------------- | ---------------------------- | ----------------------------- |
| 头文件 `paddle_infer.h` | 无变化 | 包含旧接口,保持向后兼容 |
| 无 | `paddle_inference_api.h` | 新API,可以与旧接口并存 |
| `CreatePaddlePredictor` | `CreatePredictor` | 返回值变为 shared_ptr |
| `ZeroCopyTensor` | `Tensor` | 无 |
| `AnalysisConfig` | `Config` | 无 |
| `TensorRTConfig` | 废弃 | |
| `PaddleTensor` + `PaddleBuf` | 废弃 | |
| `Predictor::GetInputTensor` | `Predictor::GetInputHandle` | 无 |
| `Predictor::GetOutputTensor` | `Predictor::GetOutputHandle` | 无 |
| | `PredictorPool` | 简化创建多个 predictor 的支持 |
使用新 C++ API 的流程与之前完全一致,只有命名变化
```c++
#include "paddle_infernce_api.h"
using namespace paddle_infer;
Config config;
config.SetModel("xxx_model_dir");
auto predictor = CreatePredictor(config);
// Get the handles for the inputs and outputs of the model
auto input0 = predictor->GetInputHandle("X");
auto output0 = predictor->GetOutputHandle("Out");
for (...) {
// Assign data to input0
MyServiceSetData(input0);
predictor->Run();
// get data from the output0 handle
MyServiceGetData(output0);
}
```
## <a name="C++_API"> C++ API</a>
##### CreatePredictor
```c++
std::shared_ptr<Predictor> CreatePredictor(const Config& config);
```
`CreatePredictor`用来根据`Config`构建预测引擎。
示例:
```c++
// 设置Config
Config config;
config.SetModel(FLAGS_model_dir);
// 根据Config创建Predictor
std::shared_ptr<Predictor> predictor = CreatePredictor(config);
```
参数:
- `config(Config)` - 用于构建Predictor的配置信息
返回:`Predictor`智能指针
返回类型:`std::shared_ptr<Predictor>`
##### GetVersion()
```c++
std::string GetVersion();
```
打印Paddle Inference的版本信息。
参数:
- `None`
返回:版本信息
返回类型:`std::string`
##### PlaceType
```c++
enum class PaddlePlace { kUNK };
using PlaceType = paddle::PaddlePlace;
```
PlaceType为目标设备硬件类型,用户可以根据应用场景选择硬件平台类型。
枚举变量`PlaceType`的所有可能取值包括:
`{kUNK, kCPU, kGPU}`
##### PrecisionType
```c++
enum class Precision { kFloat32 };
using PrecisionType = paddle::AnalysisConfig::Precision;
```
`PrecisionType`设置模型的运行精度,默认值为kFloat32(float32)。
枚举变量`PrecisionType`的所有可能取值包括:
`{kFloat32, kInt8, kHalf}`
##### DataType
```c++
enum class PaddleDType { FLOAT32 };
using DataType = paddle::PaddleDType;
```
`DataType`为模型中Tensor的数据精度,默认值为FLOAT32(float32)。
枚举变量`DataType`的所有可能取值包括:
`{FLOAT32, INT64, INT32, UINT8}`
##### GetNumBytesOfDataType
```c++
int GetNumBytesOfDataType(DataType dtype);
```
获取各个`DataType`对应的字节数。
参数:
- `dtype` - DataType枚举
返回:字节数
返回类型:`int`
##### Predictor
```c++
class Predictor;
```
`Predictor`是Paddle Inference的预测器,由`CreatePredictor`根据`Config`进行创建。用户可以根据Predictor提供的接口设置输入数据、执行模型预测、获取输出等.
示例:
```c++
using namespace paddle_infer;
Config config;
config.SetModel("xxx_model_dir");
auto predictor = CreatePredictor(config);
// Get the handles for the inputs and outputs of the model
auto input0 = predictor->GetInputHandle("X");
auto output0 = predictor->GetOutputHandle("Out");
for (...) {
// Assign data to input0
MyServiceSetData(input0);
predictor->Run();
// get data from the output0 handle
MyServiceGetData(output0);
}
```
###### GetInputNames()
获取所有输入Tensor的名称。
参数:
- `None`
返回:所有输入Tensor的名称
返回类型:`std::vector<std::string>`
###### GetOutputNames()
获取所有输出Tensor的名称。
参数:
- `None`
返回:所有输出Tensor的名称
返回类型:`std::vector<std::string>`
###### GetInputHandle(const std::string& name)
根据名称获取输入Tensor的句柄。
参数:
- `name` - Tensor的名称
返回:指向`Tensor`的指针
返回类型:`std::unique_ptr<Tensor>`
###### GetOutputHandle(const std::string& name)
根据名称获取输出Tensor的句柄。
参数:
- `name` - Tensor的名称
返回:指向`Tensor`的指针
返回类型:`std::unique_ptr<Tensor>`
###### Run()
执行模型预测,需要在***设置输入数据后***调用。
参数:
- `None`
返回:`None`
返回类型:`void`
###### ClearIntermediateTensor()
释放中间tensor。
参数:
- `None`
返回:`None`
返回类型:`void`
###### Clone()
根据该Predictor,克隆一个新的Predictor,两个Predictor之间共享权重。
参数:
- `None`
返回:新的Predictor
返回类型:`std::unique_ptr<Predictor>`
##### Tensor
```c++
class Tensor;
```
Tensor是Paddle Inference的数据组织形式,用于对底层数据进行封装并提供接口对数据进行操作,包括设置Shape、数据、LoD信息等。
*注意:用户应使用`Predictor`的`GetInputHandle`和`GetOuputHandle`接口获取输入/输出的`Tensor`。*
示例:
```c++
// 通过创建的Predictor获取输入和输出的tensor
auto input_names = predictor->GetInputNames();
auto input_t = predictor->GetInputHandle(input_names[0]);
auto output_names = predictor->GetOutputNames();
auto output_t = predictor->GetOutputHandle(output_names[0]);
// 对tensor进行reshape
input_t->Reshape({batch_size, channels, height, width});
// 通过CopyFromCpu接口,将cpu数据输入;通过CopyToCpu接口,将输出数据copy到cpu
input_t->CopyFromCpu<float>(input_data /*数据指针*/);
output_t->CopyToCpu(out_data /*数据指针*/);
// 设置LOD
std::vector<std::vector<size_t>> lod_data = {{0}, {0}};
input_t->SetLoD(lod_data);
// 获取Tensor数据指针
float *input_d = input_t->mutable_data<float>(PlaceType::kGPU); // CPU下使用PlaceType::kCPU
int output_size;
float *output_d = output_t->data<float>(PlaceType::kGPU, &output_size);
```
###### Reshape(shape)
设置Tensor的维度信息。
参数:
- `shape(const std::vector<int>&)` - 维度信息
返回:`None`
返回类型:`void`
###### shape()
获取Tensor的维度信息。
参数:
- `None`
返回:Tensor的维度信息
返回类型:`std::vector<int>`
###### CopyFromCpu(data)
```c++
template <typename T>
void CopyFromCpu(const T* data);
```
从cpu获取数据,设置到tensor内部。
示例:
```c++
// float* data = ...;
auto in_tensor = predictor->GetInputHandle("in_name");
in_tensor->CopyFromCpu(data);
```
参数:
- `data(const T*)` - cpu数据指针
返回:`None`
返回类型:`void`
###### CopyToCpu(data)
```c++
template <typename T>
void CopyToCpu(T* data);
```
示例:
```c++
std::vector<float> data(100);
auto out_tensor = predictor->GetOutputHandle("out_name");
out_tensor->CopyToCpu(data.data());
```
参数:
- `data(T*)` - cpu数据指针
返回:`None`
返回类型:`void`
###### data<T>(place, size)
```c++
template <typename T>
T* data(PlaceType* place, int* size) const;
```
获取Tensor的底层数据的常量指针,用于读取Tensor数据。
示例:
```c++
PlaceType place;
int size;
auto out_tensor = predictor->GetOutputHandle("out_name");
float* data = out_tensor->data<float>(&place, &size);
```
参数:
- `place(PlaceType*)` - 获取tensor的PlaceType
- `size(int*)` - 获取tensor的size
返回:数据指针
返回类型:`T*`
###### mutable_data<T>(place)
```c++
template <typename T>
T* mutable_data(PlaceType place);
```
获取Tensor的底层数据的指针,用于设置Tensor数据。
```c++
auto in_tensor = predictor->GetInputHandle("in_name");
float* data = out_tensor->mutable_data<float>(PlaceType::kCPU);
data[0] = 1.;
```
参数:
- `place(PlaceType)` - 设备信息
返回:`Tensor`底层数据指针
返回类型:`T*`
###### SetLoD(lod)
设置Tensor的LoD信息。
参数:
- `lod(const std::vector<std::vector<size_t>>)` - Tensor的LoD信息
返回:`None`
返回类型:`void`
###### lod()
获取Tensor的LoD信息
参数:
- `None`
返回:`Tensor`的LoD信息
返回类型:`std::vector<std::vector<size_t>>`
###### type()
tensor的DataType信息。
参数:
- `None`
返回:`Tensor`的DataType信息
返回类型:`DataType`
###### name()
tensor对应的name。
参数:
- `None`
返回:`Tensor`对应的name
返回类型:`std::string`
##### Config
```c++
class Config;
```
`Config`用来配置构建`Predictor`的配置信息,如模型路径、是否开启gpu等等。
示例:
```c++
Config config;
config.SetModel(FLAGS_model_dir);
config.DisableGpu();
config->SwitchIrOptim(false); // 默认为true。如果设置为false,关闭所有优化
config->EnableMemoryOptim(); // 开启内存/显存复用
```
###### SetModel(const std::string& model_dir)
设置模型文件路径,当需要从磁盘加载非combine模式时使用。
参数:
- `model_dir` - 模型文件夹路径
返回:`None`
返回类型:`void`
###### model_dir()
获取模型文件夹路径。
参数:
- `None`
返回:模型文件夹路径
返回类型:`string`
###### SetModel(const std::string& prog, const std::string& params)
设置模型文件路径,当需要从磁盘加载combine模式时使用。
参数:
- `prog` - 模型文件路径
- `params` - 模型参数文件路径
返回:`None`
返回类型:`void`
###### SetProgFile(const std::string& prog)
设置模型文件路径。
参数:
- `prog` - 模型文件路径
返回:`None`
返回类型:`void`
###### prog_file()
获取模型文件路径。
参数:
- `None`
返回:模型文件路径
返回类型:`string`
###### SetParamsFile(const std::string& params)
设置模型参数文件路径。
参数:
- `params` - 模型文件路径
返回:`None`
返回类型:`void`
###### params_file()
获取模型参数文件路径。
参数:
- `None`
返回:模型参数文件路径
返回类型:`string`
###### SetModelBuffer(const char* prog_buffer, size_t prog_buffer_size, const char* params_buffer, size_t params_buffer_size)
从内存加载模型。
参数:
- `prog_buffer` - 内存中模型结构数据
- `prog_buffer_size` - 内存中模型结构数据的大小
- `params_buffer` - 内存中模型参数数据
- `params_buffer_size` - 内存中模型参数数据的大小
返回:`None`
返回类型:`void`
###### model_from_memory()
判断是否从内存中加载模型。
参数:
- `None`
返回:是否从内存中加载模型
返回类型:`bool`
###### SetOptimCacheDir(const std::string& opt_cache_dir)
设置缓存路径。
参数:
- `opt_cache_dir` - 缓存路径
返回:`None`
返回类型:`void`
###### DisableFCPadding()
关闭fc padding。
参数:
- `None`
返回:`None`
返回类型:`void`
###### use_fc_padding()
判断是否启用fc padding。
参数:
- `None`
返回:是否启用fc padding
返回类型:`bool`
###### EnableUseGpu(uint64_t memory_pool_init_size_mb, int device_id = 0)
启用gpu。
参数:
- `memory_pool_init_size_mb` - 初始化分配的gpu显存,以MB为单位
- `device_id` - 设备id
返回:`None`
返回类型:`void`
###### DisableGpu()
禁用gpu。
参数:
- `None`
返回:`None`
返回类型:`void`
###### use_gpu()
是否启用gpu。
参数:
- `None`
返回:是否启用gpu
返回类型:`bool`
###### gpu_device_id()
获取gpu的device id。
参数:
- `None`
返回:gpu的device id
返回类型:`int`
###### memory_pool_init_size_mb()
获取gpu的初始显存大小。
参数:
- `None`
返回:初始的显存大小
返回类型:`int`
###### fraction_of_gpu_memory_for_pool()
初始化显存占总显存的百分比
参数:
- `None`
返回:初始的显存占总显存的百分比
返回类型:`float`
###### EnableCUDNN()
启用cudnn。
参数:
- `None`
返回:`None`
返回类型:`void`
###### cudnn_enabled()
是否启用cudnn。
参数:
- `None`
返回:是否启用cudnn
返回类型:`bool`
###### EnableXpu(int l3_workspace_size)
启用xpu。
参数:
- `l3_workspace_size` - l3 cache分配的显存大小
返回:`None`
返回类型:`void`
###### SwitchIrOptim(int x=true)
设置是否开启ir优化。
参数:
- `x` - 是否开启ir优化,默认打开
返回:`None`
返回类型:`void`
###### ir_optim()
是否开启ir优化。
参数:
- `None`
返回:是否开启ir优化
返回类型:`bool`
###### SwitchUseFeedFetchOps(int x = true)
设置是否使用feed,fetch op,仅内部使用。
参数:
- `x` - 是否使用feed, fetch op
返回:`None`
返回类型:`void`
###### use_feed_fetch_ops_enabled()
是否使用feed,fetch op。
参数:
- `None`
返回:是否使用feed,fetch op
返回类型:`bool`
###### SwitchSpecifyInputNames(bool x = true)
设置是否需要指定输入tensor的name。
参数:
- `x` - 是否指定输入tensor的name
返回:`None`
返回类型:`void`
###### specify_input_name()
是否需要指定输入tensor的name。
参数:
- `None`
返回:是否需要指定输入tensor的name
返回类型:`bool`
###### EnableTensorRtEngine(int workspace_size = 1 << 20, int max_batch_size = 1, int min_subgraph_size = 3, Precision precision = Precision::kFloat32, bool use_static = false, bool use_calib_mode = true)
设置是否启用TensorRT。
参数:
- `workspace_size` - 指定TensorRT使用的工作空间大小
- `max_batch_size` - 设置最大的batch大小,运行时batch大小不得超过此限定值
- `min_subgraph_size` - Paddle-TRT是以子图的形式运行,为了避免性能损失,当子图内部节点个数大于min_subgraph_size的时候,才会使用Paddle-TRT运行
- `precision` - 指定使用TRT的精度,支持FP32(kFloat32),FP16(kHalf),Int8(kInt8)
- `use_static` - 如果指定为true,在初次运行程序的时候会将TRT的优化信息进行序列化到磁盘上,下次运行时直接加载优化的序列化信息而不需要重新生成
- `use_calib_mode` - 若要运行Paddle-TRT int8离线量化校准,需要将此选项设置为true
返回:`None`
返回类型:`void`
###### tensorrt_engine_enabled()
是否启用tensorRT。
参数:
- `None`
返回:是否启用tensorRT
返回类型:`bool`
###### SetTRTDynamicShapeInfo(std::map<std::string, std::vector<int>> min_input_shape, std::map<std::string, std::vector<int>> max_input_shape, std::map<std::string, std::vector<int>> optim_input_shape, bool disable_trt_plugin_fp16 = false)
设置tensorRT的动态shape。
参数:
- `min_input_shape` - tensorRT子图支持动态shape的最小shape
- `max_input_shape` - tensorRT子图支持动态shape的最大shape
- `optim_input_shape` - tensorRT子图支持动态shape的最优shape
- `disable_trt_plugin_fp16` - 设置tensorRT的plugin不在fp16精度下运行
返回:`None`
返回类型:`void`
###### EnableLiteEngine(AnalysisConfig::Precision precision_mode = Precsion::kFloat32, bool zero_copy = false, const std::vector<std::string>& passes_filter = {}, const std::vector<std::string>& ops_filter = {})
启用lite子图。
参数:
- `precision_mode` - lite子图的运行精度
- `zero_copy` - 启用zero_copy,lite子图与paddle inference之间共享数据
- `passes_filter` - 设置lite子图的pass
- `ops_filter` - 设置不使用lite子图运行的op
返回:`None`
返回类型:`void`
###### lite_engine_enabled()
是否启用lite子图。
参数:
- `None`
返回:是否启用lite子图
返回类型:`bool`
###### SwitchIrDebug(int x = true)
设置是否在图分析阶段打印ir,启用后会在每一个pass后生成dot文件。
参数:
- `x` - 是否打印ir
返回:`None`
返回类型:`void`
###### EnableMKLDNN()
启用mkldnn。
参数:
- `None`
返回:`None`
返回类型:`void`
###### SetMkldnnCacheCapacity(int capacity)
设置mkldnn针对不同输入shape的cache容量大小,MKLDNN cache设计文档请参考[链接](https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/fluid/design/mkldnn/caching/caching.md)
参数:
- `capacity` - cache容量大小
返回:`None`
返回类型:`void`
###### mkldnn_enabled()
是否启用mkldnn。
参数:
- `None`
返回:是否启用mkldnn
返回类型:`bool`
###### SetMKLDNNOp(std::unordered_set<std::string> op_list)
指定优先使用mkldnn加速的op列表。
参数:
- `op_list` - 优先使用mkldnn的op列表
返回:`None`
返回类型:`void`
###### EnableMkldnnQuantizer()
启用mkldnn量化。
参数:
- `None`
返回:`None`
返回类型:`void`
###### mkldnn_quantizer_enabled()
是否启用mkldnn量化。
参数:
- `None`
返回:是否启用mkldnn量化
返回类型:`bool`
###### EnableMkldnnBfloat16()
启用mkldnn bf16。
参数:
- `None`
返回:`None`
返回类型:`void`
###### mkldnn_bfloat16_enabled()
是否启用mkldnn bf16。
参数:
- `None`
返回:是否启用mkldnn bf16
返回类型:`bool`
###### mkldnn_quantizer_config()
返回mkldnn量化config。
参数:
- `None`
返回:mkldnn量化config
返回类型:`MkldnnQuantizerConfig`
###### SetCpuMathLibraryNumThreads(int cpu_math_library_num_threads)
设置cpu blas库计算线程数。
参数:
- `cpu_math_library_num_threads` - blas库计算线程数
返回:`None`
返回类型:`void`
###### cpu_math_library_num_threads()
cpu blas库计算线程数。
参数:
- `None`
返回:cpu blas库计算线程数。
返回类型:`int`
###### ToNativeConfig()
转化为NativeConfig,不推荐使用。
参数:
- `None`
返回:当前Config对应的NativeConfig
返回类型:`NativeConfig`
###### EnableGpuMultiStream()
开启线程流,目前的行为是为每一个线程绑定一个流,在将来该行为可能改变。
参数:
- `None`
返回:`None`
返回类型:`void`
###### thread_local_stream_enabled()
是否启用线程流。
参数:
- `None`
返回:是否启用线程流。
返回类型:`bool`
###### EnableMemoryOptim()
开启内/显存复用,具体降低内存效果取决于模型结构。
参数:
- `None`
返回:`None`
返回类型:`void`
###### enable_memory_optim()
是否开启内/显存复用。
参数:
- `None`
返回:是否开启内/显存复用。
返回类型:`bool`
###### EnableProfile()
打开profile,运行结束后会打印所有op的耗时占比。
参数:
- `None`
返回:`None`
返回类型:`void`
###### profile_enabled()
是否开启profile。
参数:
- `None`
返回:是否开启profile
返回类型:`bool`
###### DisableGlogInfo()
去除Paddle Inference运行中的log。
参数:
- `None`
返回:`None`
返回类型:`void`
###### glog_info_disabled()
是否禁用了log。
参数:
- `None`
返回:是否禁用了log
返回类型:`bool`
###### SetInValid()
设置Config为无效状态,仅内部使用,保证每一个Config仅用来初始化一次Predictor。
参数:
- `None`
返回:`None`
返回类型:`void`
###### is_valid()
当前Config是否有效。
参数:
- `None`
返回:Config是否有效
返回类型:`bool`
###### pass_builder()
返回pass_builder,用来自定义图分析阶段选择的ir。
示例:
```c++
Config config;
auto pass_builder = config.pass_builder()
pass_builder->DeletePass("fc_fuse_pass") // 去除fc_fuse
```
参数:
- `None`
返回:pass_builder
返回类型:`PassStrategy`
##### PredictorPool
```c++
class PredictorPool;
```
`PredictorPool``Predictor`进行了简单的封装,通过传入config和thread的数目来完成初始化,在每个线程中,根据自己的线程id直接从池中取出对应的`Predictor`来完成预测过程。
示例:
```c++
Config config;
// init config
int thread_num = 4;
PredictorPool pool(config, thread_num);
auto predictor0 = pool.Retrive(0);
...
auto predictor3 = pool.Retrive(3);
```
###### Retrive(idx)
根据线程id取出该线程对应的Predictor。
参数:
- `idx(int)` - 线程id
返回:线程对应的Predictor
返回类型:`Predictor*`
# Python 预测 API介绍 # Python 预测 API介绍
Fluid提供了高度优化的[C++预测库](./native_infer.html),为了方便使用,我们也提供了C++预测库对应的Python接口,下面是详细的使用说明。 Paddle提供了高度优化的[C++预测库](./native_infer.html),为了方便使用,我们也提供了C++预测库对应的Python接口,下面是详细的使用说明。
如果您在使用2.0之前的Paddle,请参考[旧版API](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.8/advanced_guide/inference_deployment/inference/python_infer_cn.html)文档。
## Python预测相关数据结构 ## Python预测相关数据结构
使用Python预测API与C++预测API相似,主要包括`PaddleTensor`, `PaddleDType`, `AnalysisConfig``PaddlePredictor`,分别对应于C++ API中同名的类型。 使用Python预测API与C++预测API相似,主要包括`Tensor`, `DataType`, `Config``Predictor`,分别对应于C++ API中同名的类型。
### PaddleTensor ### DataType
class paddle.fluid.core.PaddleTensor class paddle.inference.DataType
`PaddleTensor`是预测库输入和输出的数据结构,包括以下字段 `DataType`定义了`Tensor`的数据类型,由传入`Tensor`的numpy数组类型确定,包括以下成员
* `name`(str): 指定输入的名称 * `INT64`: 64位整型
* `shape`(tuple|list): Tensor的shape * `INT32`: 32位整型
* `data`(numpy.ndarray): Tensor的数据,可在PaddleTensor构造的时候用`numpy.ndarray`直接传入 * `FLOAT32`: 32位浮点型
* `dtype`(PaddleDType): Tensor的类型
* `lod`(List[List[int]]): [LoD](../../../user_guides/howto/basic_concept/lod_tensor.html)信息
`PaddleTensor`包括以下方法 ### PrecisionType
* `as_ndarray`: 返回`data`对应的numpy数组 class paddle.3.inference.PrecisionType
#### 代码示例 `PrecisionType`定义了`Predictor`运行的精度模式,包括一下成员
``` python
tensor = PaddleTensor(name="tensor", data=numpy.array([1, 2, 3], dtype="int32"))
```
调用`PaddleTensor`的成员字段和方法输出如下:
``` python
>>> tensor.name
'tensor'
>>> tensor.shape
[3]
>>> tensor.dtype
PaddleDType.INT32
>>> tensor.lod
[]
>>> tensor.as_ndarray()
array([1, 2, 3], dtype=int32)
```
* `Float32`: fp32模式运行
* `Half`: fp16模式运行
* `Int8`: int8模式运行
### PaddleDType ### Tensor
class paddle.fluid.core.PaddleTensor class paddle.inference.Tensor
`PaddleDType`定义了`PaddleTensor`的数据类型,由传入`PaddleTensor`的numpy数组类型确定,包括以下成员 `Tensor``Predictor`的一种输入/输出数据结构,通过`predictor`获取输入/输出handle得到,主要提供以下方法
* `INT64`: 64位整型 * `copy_from_cpu`: 从cpu获取模型运行所需输入数据
* `INT32`: 32位整型 * `copy_to_cpu`: 获取模型运行输出结果
* `FLOAT32`: 32位浮点型 * `lod`: 获取lod信息
* `set_lod`: 设置lod信息
* `shape`: 获取shape信息
* `reshape`: 设置shape信息
* `type`: 获取DataType信息
### AnalysisConfig ``` python
# 创建predictor
predictor = create_predictor(config)
class paddle.fluid.core.AnalysisConfig # 获取输入的名称
input_names = predictor.get_input_names()
input_tensor = predictor.get_input_handle(input_names[0])
`AnalysisConfig`是创建预测引擎的配置,提供了模型路径设置、预测引擎运行设备选择以及多种优化预测流程的选项,主要包括以下方法 # 设置输入
fake_input = numpy.random.randn(1, 3, 318, 318).astype("float32")
input_tensor.copy_from_cpu(fake_input)
# 运行predictor
predictor.run()
# 获取输出
output_names = predictor.get_output_names()
output_tensor = predictor.get_output_handle(output_names[0])
output_data = output_tensor.copy_to_cpu() # numpy.ndarray类型
```
### Config
class paddle.inference.Config
`Config`是创建预测引擎的配置,提供了模型路径设置、预测引擎运行设备选择以及多种优化预测流程的选项,主要包括以下方法
* `set_model`: 设置模型的路径 * `set_model`: 设置模型的路径
* `model_dir`: 返回模型文件夹路径 * `model_dir`: 返回模型文件夹路径
...@@ -71,15 +81,16 @@ class paddle.fluid.core.AnalysisConfig ...@@ -71,15 +81,16 @@ class paddle.fluid.core.AnalysisConfig
* `enable_mkldnn`: 开启MKLDNN * `enable_mkldnn`: 开启MKLDNN
* `disable_glog_info`: 禁用预测中的glog日志 * `disable_glog_info`: 禁用预测中的glog日志
* `delete_pass`: 预测的时候删除指定的pass * `delete_pass`: 预测的时候删除指定的pass
#### 代码示例 #### 代码示例
设置模型和参数路径有两种形式: 设置模型和参数路径有两种形式:
* 当模型文件夹下存在一个模型文件和多个参数文件时,传入模型文件夹路径,模型文件名默认为`__model__` * 当模型文件夹下存在一个模型文件和多个参数文件时,传入模型文件夹路径,模型文件名默认为`__model__`
``` python ``` python
config = AnalysisConfig("./model") config = Config("./model")
``` ```
* 当模型文件夹下只有一个模型文件和一个参数文件时,传入模型文件和参数文件路径 * 当模型文件夹下只有一个模型文件和一个参数文件时,传入模型文件和参数文件路径
``` python ``` python
config = AnalysisConfig("./model/model", "./model/params") config = Config("./model/model", "./model/params")
``` ```
使用`set_model`方法设置模型和参数路径方式同上 使用`set_model`方法设置模型和参数路径方式同上
...@@ -87,147 +98,53 @@ config = AnalysisConfig("./model/model", "./model/params") ...@@ -87,147 +98,53 @@ config = AnalysisConfig("./model/model", "./model/params")
``` python ``` python
config.enable_use_gpu(100, 0) # 初始化100M显存,使用gpu id为0 config.enable_use_gpu(100, 0) # 初始化100M显存,使用gpu id为0
config.gpu_device_id() # 返回正在使用的gpu id config.gpu_device_id() # 返回正在使用的gpu id
config.disable_gpu() # 禁用gpu config.disable_gpu() # 禁用gpu
config.switch_ir_optim(True) # 开启IR优化 config.switch_ir_optim(True) # 开启IR优化
config.enable_tensorrt_engine(precision_mode=AnalysisConfig.Precision.Float32, config.enable_tensorrt_engine(precision_mode=PrecisionType.Float32,
use_calib_mode=True) # 开启TensorRT预测,精度为fp32,开启int8离线量化 use_calib_mode=True) # 开启TensorRT预测,精度为fp32,开启int8离线量化
config.enable_mkldnn() # 开启MKLDNN config.enable_mkldnn() # 开启MKLDNN
```
### PaddlePredictor
class paddle.fluid.core.PaddlePredictor
`PaddlePredictor`是运行预测的引擎,由`paddle.fluid.core.create_paddle_predictor(config)`创建,主要提供以下方法
* `run`: 输入和返回值均为`PaddleTensor`列表类型,功能为运行预测引擎,返回预测结果
#### 代码示例
``` python
# 设置完AnalysisConfig后创建预测引擎PaddlePredictor
predictor = create_paddle_predictor(config)
# 设置输入
x = numpy.array([1, 2, 3], dtype="int64")
x_t = fluid.core.PaddleTensor(x)
y = numpy.array([4], dtype = "int64")
y_t = fluid.core.PaddleTensor(y)
# 运行预测引擎得到结果,返回值是一个PaddleTensor的列表
results = predictor.run([x_t, y_t])
# 获得预测结果,并应用到自己的应用中
``` ```
### 使用ZeroCopyTensor管理输入/输出 ### Predictor
`ZeroCopyTensor``AnalysisPredictor`的一种输入/输出数据结构,与`PaddleTensor`等同。`ZeroCopyTensor`相比于`PaddleTensor`,可以避免预测时候准备输入以及获取输出时多余的数据拷贝,提高预测性能。 class paddle.inference.Predictor
注意: 需要注意的是,使用`ZeroCopyTensor`,务必在创建`config`时设置`config.switch_use_feed_fetch_ops(False)`用于显式地在模型运行的时候删去`feed``fetch`ops,不会影响模型的效果,但是能提升性能。 `Predictor`是运行预测的引擎,由`paddle.inference.create_predictor(config)`创建,主要提供以下方法
``` python
# 创建predictor
predictor = create_paddle_predictor(config)
# 获取输入的名称
input_names = predictor.get_input_names()
input_tensor = predictor.get_input_tensor(input_names[0])
# 设置输入 * `run()`: 运行预测引擎,返回预测结果
fake_input = numpy.random.randn(1, 3, 318, 318).astype("float32")
input_tensor.copy_from_cpu(fake_input)
# 运行predictor
predictor.zero_copy_run()
# 获取输出
output_names = predictor.get_output_names()
output_tensor = predictor.get_output_tensor(output_names[0])
output_data = output_tensor.copy_to_cpu() # numpy.ndarray类型
```
### AnalysisPredictor
class paddle.fluid.core.AnalysisPredictor
`AnalysisPredictor`是运行预测的引擎,继承于`PaddlePredictor`,同样是由`paddle.fluid.core.create_paddle_predictor(config)`创建,主要提供以下方法
* `zero_copy_run()`: 运行预测引擎,返回预测结果
* `get_input_names()`: 获取输入的名称 * `get_input_names()`: 获取输入的名称
* `get_input_tensor(input_name: str)`: 根据输入的名称获取对应的`ZeroCopyTensor` * `get_input_handle(input_name: str)`: 根据输入的名称获取对应的`Tensor`
* `get_output_names()`: 获取输出的名称 * `get_output_names()`: 获取输出的名称
* `get_output_tensor(output_name: str)`: 根据输出的名称获取对应的`ZeroCopyTensor` * `get_output_handle(output_name: str)`: 根据输出的名称获取对应的`Tensor`
#### 代码示例 #### 代码示例
``` python ``` python
# 设置完AnalysisConfig后创建预测引擎PaddlePredictor # 设置完AnalysisConfig后创建预测引擎PaddlePredictor
predictor = create_paddle_predictor(config) predictor = create_predictor(config)
# 获取输入的名称 # 获取输入的名称
input_names = predictor.get_input_names() input_names = predictor.get_input_names()
input_tensor = predictor.get_input_tensor(input_names[0]) input_handle = predictor.get_input_handle(input_names[0])
# 设置输入 # 设置输入
fake_input = numpy.random.randn(1, 3, 318, 318).astype("float32") fake_input = numpy.random.randn(1, 3, 318, 318).astype("float32")
input_tensor.reshape([1, 3, 318, 318]) input_handle.reshape([1, 3, 318, 318])
input_tensor.copy_from_cpu(fake_input) input_handle.copy_from_cpu(fake_input)
# 运行predictor # 运行predictor
predictor.zero_copy_run() predictor.run()
# 获取输出 # 获取输出
output_names = predictor.get_output_names() output_names = predictor.get_output_names()
output_tensor = predictor.get_output_tensor(output_names[0]) output_handle = predictor.get_output_handle(output_names[0])
``` ```
## 支持方法列表
* PaddleTensor
* `as_ndarray() -> numpy.ndarray`
* ZeroCopyTensor
* `copy_from_cpu(input: numpy.ndarray) -> None`
* `copy_to_cpu() -> numpy.ndarray`
* `reshape(input: numpy.ndarray|List[int]) -> None`
* `shape() -> List[int]`
* `set_lod(input: numpy.ndarray|List[List[int]]) -> None`
* `lod() -> List[List[int]]`
* `type() -> PaddleDType`
* AnalysisConfig
* `set_model(model_dir: str) -> None`
* `set_model(prog_file: str, params_file: str) -> None`
* `model_dir() -> str`
* `prog_file() -> str`
* `params_file() -> str`
* `enable_use_gpu(memory_pool_init_size_mb: int, device_id: int) -> None`
* `gpu_device_id() -> int`
* `switch_ir_optim(x: bool = True) -> None`
* `enable_tensorrt_engine(workspace_size: int = 1 << 20,
max_batch_size: int,
min_subgraph_size: int,
precision_mode: AnalysisConfig.precision,
use_static: bool,
use_calib_mode: bool) -> None`
* `enable_mkldnn() -> None`
* `disable_glog_info() -> None`
* `delete_pass(pass_name: str) -> None`
* PaddlePredictor
* `run(input: List[PaddleTensor]) -> List[PaddleTensor]`
* AnalysisPredictor
* `zero_copy_run() -> None`
* `get_input_names() -> List[str]`
* `get_input_tensor(input_name: str) -> ZeroCopyTensor`
* `get_output_names() -> List[str]`
* `get_output_tensor(output_name: str) -> ZeroCopyTensor`
可参考对应的[C++预测接口](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/pybind/inference_api.cc),其中定义了每个接口的参数和返回值
## 完整使用示例 ## 完整使用示例
下面是使用Fluid Python API进行预测的一个完整示例,使用resnet50模型 下面是使用Paddle Inference Python API进行预测的一个完整示例,使用resnet50模型
下载[resnet50模型](http://paddle-inference-dist.bj.bcebos.com/resnet50_model.tar.gz)并解压,运行如下命令将会调用预测引擎 下载[resnet50模型](http://paddle-inference-dist.bj.bcebos.com/resnet50_model.tar.gz)并解压,运行如下命令将会调用预测引擎
...@@ -237,70 +154,11 @@ python resnet50_infer.py --model_file ./model/model --params_file ./model/params ...@@ -237,70 +154,11 @@ python resnet50_infer.py --model_file ./model/model --params_file ./model/params
`resnet50_infer.py` 的内容是 `resnet50_infer.py` 的内容是
### PaddleTensor的完整使用示例
``` python ``` python
import argparse import argparse
import numpy as np import numpy as np
from paddle.inference import Config
from paddle.fluid.core import PaddleTensor from paddle.inference import create_predictor
from paddle.fluid.core import AnalysisConfig
from paddle.fluid.core import create_paddle_predictor
def main():
args = parse_args()
# 设置AnalysisConfig
config = AnalysisConfig(args.model_file, args.params_file)
config.disable_gpu()
# 创建PaddlePredictor
predictor = create_paddle_predictor(config)
# 设置输入,此处以随机输入为例,用户可自行输入真实数据
inputs = fake_input(args.batch_size)
# 运行预测引擎
outputs = predictor.run(inputs)
output_num = 512
# 获得输出并解析
output = outputs[0]
print(output.name)
output_data = output.as_ndarray() #return numpy.ndarray
assert list(output_data.shape) == [args.batch_size, output_num]
for i in range(args.batch_size):
print(np.argmax(output_data[i]))
def fake_input(batch_size):
shape = [batch_size, 3, 318, 318]
data = np.random.randn(*shape).astype("float32")
image = PaddleTensor(data)
return [image]
def parse_args():
parser = argparse.ArgumentParser()
parser.add_argument("--model_file", type=str, help="model filename")
parser.add_argument("--params_file", type=str, help="parameter filename")
parser.add_argument("--batch_size", type=int, default=1, help="batch size")
return parser.parse_args()
if __name__ == "__main__":
main()
```
### ZeroCopyTensor的完整使用示例
``` python
import argparse
import numpy as np
from paddle.fluid.core import AnalysisConfig
from paddle.fluid.core import create_paddle_predictor
def main(): def main():
...@@ -310,24 +168,24 @@ def main(): ...@@ -310,24 +168,24 @@ def main():
config = set_config(args) config = set_config(args)
# 创建PaddlePredictor # 创建PaddlePredictor
predictor = create_paddle_predictor(config) predictor = create_predictor(config)
# 获取输入的名称 # 获取输入的名称
input_names = predictor.get_input_names() input_names = predictor.get_input_names()
input_tensor = predictor.get_input_tensor(input_names[0]) input_handle = predictor.get_input_handle(input_names[0])
# 设置输入 # 设置输入
fake_input = np.random.randn(1, 3, 318, 318).astype("float32") fake_input = np.random.randn(1, 3, 318, 318).astype("float32")
input_tensor.reshape([1, 3, 318, 318]) input_handle.reshape([1, 3, 318, 318])
input_tensor.copy_from_cpu(fake_input) input_handle.copy_from_cpu(fake_input)
# 运行predictor # 运行predictor
predictor.zero_copy_run() predictor.run()
# 获取输出 # 获取输出
output_names = predictor.get_output_names() output_names = predictor.get_output_names()
output_tensor = predictor.get_output_tensor(output_names[0]) output_handle = predictor.get_output_handle(output_names[0])
output_data = output_tensor.copy_to_cpu() # numpy.ndarray类型 output_data = output_handle.copy_to_cpu() # numpy.ndarray类型
def parse_args(): def parse_args():
...@@ -340,7 +198,7 @@ def parse_args(): ...@@ -340,7 +198,7 @@ def parse_args():
def set_config(args): def set_config(args):
config = AnalysisConfig(args.model_file, args.params_file) config = Config(args.model_file, args.params_file)
config.disable_gpu() config.disable_gpu()
config.switch_use_feed_fetch_ops(False) config.switch_use_feed_fetch_ops(False)
config.switch_specify_input_names(True) config.switch_specify_input_names(True)
...@@ -348,5 +206,79 @@ def set_config(args): ...@@ -348,5 +206,79 @@ def set_config(args):
if __name__ == "__main__": if __name__ == "__main__":
main() main()
``` ```
## 支持方法列表
* Tensor
* `copy_from_cpu(input: numpy.ndarray) -> None`
* `copy_to_cpu() -> numpy.ndarray`
* `reshape(input: numpy.ndarray|List[int]) -> None`
* `shape() -> List[int]`
* `set_lod(input: numpy.ndarray|List[List[int]]) -> None`
* `lod() -> List[List[int]]`
* `type() -> PaddleDType`
* Config
* `set_model(model_dir: str) -> None`
* `set_model(prog_file: str, params_file: str) -> None`
* `set_model_buffer(model: str, model_size: int, param: str, param_size: int) -> None`
* `model_dir() -> str`
* `prog_file() -> str`
* `params_file() -> str`
* `model_from_memory() -> bool`
* `set_cpu_math_library_num_threads(num: int) -> None`
* `enable_use_gpu(memory_pool_init_size_mb: int, device_id: int) -> None`
* `use_gpu() -> bool`
* `gpu_device_id() -> int`
* `switch_ir_optim(x: bool = True) -> None`
* `switch_ir_debug(x: int=True) -> None`
* `ir_optim() -> bool`
* `enable_tensorrt_engine(workspace_size: int = 1 << 20,
max_batch_size: int,
min_subgraph_size: int,
precision_mode: AnalysisConfig.precision,
use_static: bool,
use_calib_mode: bool) -> None`
* `set_trt_dynamic_shape_info(min_input_shape: Dict[str, List[int]]={}, max_input_shape: Dict[str, List[int]]={}, optim_input_shape: Dict[str, List[int]]={}, disable_trt_plugin_fp16: bool=False) -> None`
* `tensorrt_engine_enabled() -> bool`
* `enable_mkldnn() -> None`
* `enable_mkldnn_bfloat16() -> None`
* `mkldnn_enabled() -> bool`
* `set_mkldnn_cache_capacity(capacity: int=0) -> None`
* `set_mkldnn_op(ops: Set[str]) -> None`
* `set_optim_cache_dir(dir: str) -> None`
* `disable_glog_info() -> None`
* `pass_builder() -> paddle::PassStrategy`
* `delete_pass(pass_name: str) -> None`
* `cpu_math_library_num_threads() -> int`
* `disable_gpu() -> None`
* `enable_lite_engine(precision: PrecisionType, zero_copy: bool, passes_filter: List[str]=[], ops_filter: List[str]=[]) -> None`
* `lite_engine_enabled() -> bool`
* `enable_memory_optim() -> None`
* `enable_profile() -> None`
* `enable_quantizer() -> None`
* `quantizer_config() -> paddle::MkldnnQuantizerConfig`
* `fraction_of_gpu_memory_for_pool() -> float`
* `memory_pool_init_size_mb() -> int`
* `glog_info_disabled() -> bool`
* `gpu_device_id() -> int`
* `specify_input_name() -> bool`
* `switch_specify_input_names(x: bool=True) -> None`
* `specify_input_name(q) -> bool`
* `switch_use_feed_fetch_ops(x: int=True) -> None`
* `use_feed_fetch_ops_enabled() -> bool`
* `to_native_config() -> paddle.fluid.core_avx.NativeConfig`
* `create_predictor(config: Config) -> Predictor`
* Predictor
* `run() -> None`
* `get_input_names() -> List[str]`
* `get_input_handle(input_name: str) -> Tensor`
* `get_output_names() -> List[str]`
* `get_output_handle(output_name: str) -> Tensor`
* `clear_intermediate_tensor() -> None`
* `clone() -> Predictor`
* PredictorPool
* `retrive(idx: int) -> Predictor`
可参考对应的[C++预测接口](https://github.com/PaddlePaddle/Paddle/blob/develop/paddle/fluid/pybind/inference_api.cc),其中定义了每个接口的参数和返回值
...@@ -2,41 +2,41 @@ ...@@ -2,41 +2,41 @@
安装与编译 Windows 预测库 安装与编译 Windows 预测库
=========================== ===========================
下载安装包与对应的测试环境 直接下载安装
------------- -------------
| 版本说明 | 预测库(1.8.3版本) | 编译器 | 构建工具 | cuDNN | CUDA | | 版本说明 | 预测库(1.8.4版本) |预测库(2.0.0-beta0版本) | 编译器 | 构建工具 | cuDNN | CUDA |
|:---------|:-------------------|:-------------------|:----------------|:--------|:-------| |:---------|:-------------------|:-------------------|:----------------|:--------|:-------|
| cpu_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 | | cpu_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/2.0.0-beta0/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 |
| cpu_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/open/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 | | cpu_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/open/cpu/fluid_inference_install_dir.zip) || MSVC 2015 update 3| CMake v3.16.0 |
| cuda9.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/post97/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 | | cuda9.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/post97/fluid_inference_install_dir.zip) || MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 |
| cuda9.0_cudnn7_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/open/post97/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 | | cuda9.0_cudnn7_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/open/post97/fluid_inference_install_dir.zip) || MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 |
| cuda10.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/post107/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.4.1 | 10.0 | | cuda10.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/post107/fluid_inference_install_dir.zip) | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.4.1 | 10.0 |
### 硬件环境 ### 硬件环境
测试环境硬件配置: 测试环境硬件配置:
| CPU | I7-8700K | | 操作系统 | win10 家庭版本 |
|:---------|:-------------------| |:---------|:-------------------|
| CPU | I7-8700K |
| 内存 | 16G | | 内存 | 16G |
| 硬盘 | 1T hdd + 256G ssd | | 硬盘 | 1T hdd + 256G ssd |
| 显卡 | GTX1080 8G | | 显卡 | GTX1080 8G |
测试环境操作系统使用 win10 家庭版本
从源码编译预测库 从源码编译
-------------- --------------
用户也可以从 PaddlePaddle 核心代码编译C++预测库,只需在编译时配制下面这些编译选项: 用户也可以从 PaddlePaddle 核心代码编译C++预测库,只需在编译时配制下面这些编译选项:
|选项 |说明 | 值 | |选项 |说明 | 值 |
|:-------------|:-------|:------------| |:-------------|:-------|:------------|
|CMAKE_BUILD_TYPE | 配置生成器上的构建类型,windows预测库目前只支持Release | Release | |CMAKE_BUILD_TYPE | 配置生成器上的构建类型,windows预测库目前只支持Release | Release |
|ON_INFER | 是否生成预测库,编译预测库时必须设置为ON | ON | |ON_INFER | 是否生成预测库,编译预测库时必须设置为ON | ON |
|WITH_GPU | 是否支持GPU | ON/OFF | |WITH_GPU | 是否支持GPU | ON/OFF |
|WITH_MKL | 是否使用Intel MKL(数学核心库) | ON/OFF | |WITH_MKL | 是否使用Intel MKL(数学核心库)或者OPENBLAS | ON/OFF |
|WITH_PYTHON | 是否内嵌PYTHON解释器 | OFF(推荐) | |WITH_PYTHON | 是否编译Python包 | OFF(推荐) |
|MSVC_STATIC_CRT|是否使用/MT 模式进行编译,Windows默认使用 /MT 模式进行编译 |ON/OFF| |MSVC_STATIC_CRT|是否使用/MT 模式进行编译,默认使用 /MT 模式进行编译 |ON/OFF|
|CUDA_TOOKIT_ROOT_DIR|编译GPU预测库时,需设置CUDA的根目录|YOUR_CUDA_PATH| |CUDA_TOOKIT_ROOT_DIR|编译GPU预测库时,需设置CUDA的根目录|YOUR_CUDA_PATH|
请按照推荐值设置,以避免链接不必要的库。其它可选编译选项按需进行设定。 请按照推荐值设置,以避免链接不必要的库。其它可选编译选项按需进行设定。
...@@ -45,46 +45,45 @@ ...@@ -45,46 +45,45 @@
Windows下安装与编译预测库步骤:(在Windows命令提示符下执行以下指令) Windows下安装与编译预测库步骤:(在Windows命令提示符下执行以下指令)
1. 将PaddlePaddle的源码clone在当下目录的Paddle文件夹中,并进入Paddle目录: 1. 将PaddlePaddle的源码clone在当下目录的Paddle文件夹中,并进入Paddle目录,创建build目录
```bash ```bash
git clone https://github.com/PaddlePaddle/Paddle.git git clone https://github.com/PaddlePaddle/Paddle.git
cd Paddle cd Paddle
```
2. 执行cmake:
- 编译CPU预测
```bash
# 创建并进入build目录 # 创建并进入build目录
mkdir build mkdir build
cd build cd build
```
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=OFF -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF 2. 执行cmake:
- 编译CPU预测库
```bash
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF
# Windows默认使用 /MT 模式进行编译,如果想使用 /MD 模式,请使用以下命令。如不清楚两者的区别,请使用上面的命令 # Windows默认使用 /MT 模式进行编译,如果想使用 /MD 模式,请使用以下命令。如不清楚两者的区别,请使用上面的命令
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=OFF -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF -DMSVC_STATIC_CRT=OFF cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF -DMSVC_STATIC_CRT=OFF
``` ```
- 编译GPU预测库: - 编译GPU预测库:
```bash ```bash
# -DCUDA_TOOKIT_ROOT_DIR 为cuda根目录,例如-DCUDA_TOOKIT_ROOT_DIR="D:\\cuda" # -DCUDA_TOOKIT_ROOT_DIR为你所安装的cuda根目录,例如-DCUDA_TOOKIT_ROOT_DIR="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0"
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=ON -DON_INFER=ON -DWITH_PYTHON=OFF -DCUDA_TOOKIT_ROOT_DIR=YOUR_CUDA_PATH cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=ON -DON_INFER=ON -DWITH_PYTHON=OFF -DCUDA_TOOKIT_ROOT_DIR=YOUR_CUDA_PATH
``` ```
3. 使用Blend for Visual Studio 2015 打开 `paddle.sln` 文件,选择平台为`x64`,配置为`Release`,编译inference_lib_dist项目。 3. 使用Blend for Visual Studio 2015 打开 `paddle.sln` 文件,选择平台为`x64`,配置为`Release`,编译inference_lib_dist项目。
操作方法:在Visual Studio中选择相应模块,右键选择"生成"(或者"build") 操作方法:在Visual Studio中选择相应模块,右键选择"生成"(或者"build")
编译成功后,使用C++预测库所需的依赖(包括:(1)编译出的PaddlePaddle预测库和头文件;(2)第三方链接库和头文件;(3)版本信息与编译选项信息) 编译成功后,使用C++预测库所需的依赖(包括:1. 编译出的PaddlePaddle预测库和头文件;2. 第三方链接库和头文件;3. 版本信息与编译选项信息)均会存放于`fluid_inference_install_dir`目录中。
均会存放于`fluid_inference_install_dir`目录中。
version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使用OpenBlas或MKL数学库、CUDA/CUDNN版本号,如:
version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使用OpenBlas或MKL数学库、CUDA/CUDNN版本号、C++编译器版本,如:
GIT COMMIT ID: cc9028b90ef50a825a722c55e5fda4b7cd26b0d6 ```text
WITH_MKL: ON GIT COMMIT ID: 264e76cae6861ad9b1d4bcd8c3212f7a78c01e4d
WITH_MKLDNN: ON WITH_MKL: ON
WITH_GPU: ON WITH_MKLDNN: ON
CUDA version: 8.0 WITH_GPU: ON
CUDNN version: v7 CUDA version: 10.0
CUDNN version: v7.4
CXX compiler version: 19.0.24215.1
```
编译预测demo 编译预测demo
------------- -------------
...@@ -93,14 +92,13 @@ version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使 ...@@ -93,14 +92,13 @@ version.txt 中记录了该预测库的版本信息,包括Git Commit ID、使
测试环境硬件配置: 测试环境硬件配置:
| CPU | I7-8700K | | 操作系统 | win10 家庭版本 |
|:---------|:-------------------| |:---------|:-------------------|
| CPU | I7-8700K |
| 内存 | 16G | | 内存 | 16G |
| 硬盘 | 1T hdd + 256G ssd | | 硬盘 | 1T hdd + 256G ssd |
| 显卡 | GTX1080 8G | | 显卡 | GTX1080 8G |
测试环境操作系统使用 win10 家庭版本。
### 软件要求 ### 软件要求
**请您严格按照以下步骤进行安装,否则可能会导致安装失败!** **请您严格按照以下步骤进行安装,否则可能会导致安装失败!**
......
...@@ -2,26 +2,27 @@ ...@@ -2,26 +2,27 @@
Install and Compile C++ Inference Library on Windows Install and Compile C++ Inference Library on Windows
=========================== ===========================
Direct Download and Install Download and Install directly
------------- -------------
| Version | Inference Libraries(v1.8.3) | Compiler | Build tools | cuDNN | CUDA | | Version | Inference Libraries(v1.8.4) |Inference Libraries(v2.0.0-beta0)| Compiler | Build tools | cuDNN | CUDA |
|:---------|:-------------------|:-------------------|:----------------|:--------|:-------| |:---------|:-------------------|:-------------------|:----------------|:--------|:-------|
| cpu_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 | | cpu_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/2.0.0-beta0/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 |
| cpu_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/open/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3| CMake v3.16.0 | | cpu_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/open/cpu/fluid_inference_install_dir.zip) || MSVC 2015 update 3| CMake v3.16.0 |
| cuda9.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/post97/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 | | cuda9.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/post97/fluid_inference_install_dir.zip) || MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 |
| cuda9.0_cudnn7_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/open/post97/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 | | cuda9.0_cudnn7_avx_openblas | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/open/post97/fluid_inference_install_dir.zip) || MSVC 2015 update 3 | CMake v3.16.0 | 7.3.1 | 9.0 |
| cuda10.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/post107/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.4.1 | 10.0 | | cuda10.0_cudnn7_avx_mkl | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.4/win-infer/mkl/post107/fluid_inference_install_dir.zip) | [fluid_inference.zip](https://paddle-wheel.bj.bcebos.com/1.8.3/win-infer/mkl/cpu/fluid_inference_install_dir.zip) | MSVC 2015 update 3 | CMake v3.16.0 | 7.4.1 | 10.0 |
### Hardware Environment ### Hardware Environment
Hardware Configuration of the experimental environment: Hardware Configuration of the experimental environment:
| CPU | I7-8700K | |Operating System| win10 family version|
|:--------------|:-------------------| |:---------------|:-------------------|
| Memory | 16G | | CPU | I7-8700K |
| Hard Disk | 1T hdd + 256G ssd | | Memory | 16G |
| Graphics Card | GTX1080 8G | | Hard Disk | 1T hdd + 256G ssd |
| Graphics Card | GTX1080 8G |
The operating system is win10 family version in the experimental environment. The operating system is win10 family version in the experimental environment.
...@@ -36,8 +37,8 @@ Users can also compile C++ inference libraries from the PaddlePaddle core code b ...@@ -36,8 +37,8 @@ Users can also compile C++ inference libraries from the PaddlePaddle core code b
|ON_INFER|Whether to generate the inference library. Must be set to ON when compiling the inference library. | ON | |ON_INFER|Whether to generate the inference library. Must be set to ON when compiling the inference library. | ON |
|WITH_GPU|Whether to support GPU | ON/OFF | |WITH_GPU|Whether to support GPU | ON/OFF |
|WITH_MKL|Whether to support MKL | ON/OFF | |WITH_MKL|Whether to support MKL | ON/OFF |
|WITH_PYTHON|Whether the PYTHON interpreter is embedded | OFF | |WITH_PYTHON|Whether to generate the Python whl package| OFF |
|MSVC_STATIC_CRT|Whether to compile with / MT mode | ON | |MSVC_STATIC_CRT|Whether to compile with /MT mode | ON |
|CUDA_TOOKIT_ROOT_DIR | When compiling the GPU inference library, you need to set the CUDA root directory | YOUR_CUDA_PATH | |CUDA_TOOKIT_ROOT_DIR | When compiling the GPU inference library, you need to set the CUDA root directory | YOUR_CUDA_PATH |
For details on the compilation options, see [the compilation options list](../../../beginners_guide/install/Tables_en.html/#Compile) For details on the compilation options, see [the compilation options list](../../../beginners_guide/install/Tables_en.html/#Compile)
...@@ -54,21 +55,16 @@ For details on the compilation options, see [the compilation options list](../.. ...@@ -54,21 +55,16 @@ For details on the compilation options, see [the compilation options list](../..
- compile CPU inference library - compile CPU inference library
```bash ```bash
# create build directory cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF
mkdir build
# change to the build directory
cd build
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=OFF -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF
# use -DWITH_MKL to select math library: Intel MKL or OpenBLAS # use -DWITH_MKL to select math library: Intel MKL or OpenBLAS
# By default on Windows we use /MT for C Runtime Library, If you want to use /MD, please use the below command # By default on Windows we use /MT for C Runtime Library, If you want to use /MD, please use the below command
# If you have no ideas the differences between the two, use the above one # If you have no ideas the differences between the two, use the above one
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=OFF -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF -DMSVC_STATIC_CRT=OFF cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=OFF -DON_INFER=ON -DWITH_PYTHON=OFF -DMSVC_STATIC_CRT=OFF
``` ```
- compile GPU inference library - compile GPU inference library
```bash ```bash
# -DCUDA_TOOKIT_ROOT_DIR is cuda root directory, such as -DCUDA_TOOKIT_ROOT_DIR="D:\\cuda" # -DCUDA_TOOKIT_ROOT_DIR is cuda root directory, such as -DCUDA_TOOKIT_ROOT_DIR="C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v10.0"
cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=ON -DON_INFER=ON -DWITH_PYTHON=OFF -DCUDA_TOOKIT_ROOT_DIR=YOUR_CUDA_PATH cmake .. -G "Visual Studio 14 2015" -A x64 -T host=x64 -DCMAKE_BUILD_TYPE=Release -DWITH_MKL=ON -DWITH_GPU=ON -DON_INFER=ON -DWITH_PYTHON=OFF -DCUDA_TOOKIT_ROOT_DIR=YOUR_CUDA_PATH
``` ```
...@@ -76,15 +72,18 @@ For details on the compilation options, see [the compilation options list](../.. ...@@ -76,15 +72,18 @@ For details on the compilation options, see [the compilation options list](../..
The inference library will be installed in `fluid_inference_install_dir`. The inference library will be installed in `fluid_inference_install_dir`.
version.txt constains the detailed configurations about the library, including git commit ID、math library, CUDA, CUDNN versions version.txt constains the detailed configurations about the library, including git commit ID、math library, CUDA, CUDNN versions, CXX compiler version:
GIT COMMIT ID: cc9028b90ef50a825a722c55e5fda4b7cd26b0d6 ```text
WITH_MKL: ON GIT COMMIT ID: 264e76cae6861ad9b1d4bcd8c3212f7a78c01e4d
WITH_MKLDNN: ON WITH_MKL: ON
WITH_GPU: ON WITH_MKLDNN: ON
CUDA version: 8.0 WITH_GPU: ON
CUDNN version: v7 CUDA version: 10.0
CUDNN version: v7.4
CXX compiler version: 19.0.24215.1
```
Inference Demo Compilation Inference Demo Compilation
...@@ -94,13 +93,12 @@ Inference Demo Compilation ...@@ -94,13 +93,12 @@ Inference Demo Compilation
Hardware Configuration of the experimental environment: Hardware Configuration of the experimental environment:
| CPU | I7-8700K | |Operating System| win10 family version|
|:--------------|:-------------------| |:---------------|:-------------------|
| Memory | 16G | | CPU | I7-8700K |
| Hard Disk | 1T hdd + 256G ssd | | Memory | 16G |
| Graphics Card | GTX1080 8G | | Hard Disk | 1T hdd + 256G ssd |
| Graphics Card | GTX1080 8G |
The operating system is win10 family version in the experimental environment.
### Steps to Configure Environment ### Steps to Configure Environment
......
...@@ -8,7 +8,7 @@ paddle.nn.functional.common.alpha_dropout paddle.nn.functional.alpha_dropout ...@@ -8,7 +8,7 @@ paddle.nn.functional.common.alpha_dropout paddle.nn.functional.alpha_dropout
paddle.nn.functional.activation.log_sigmoid paddle.nn.functional.log_sigmoid paddle.nn.functional.activation.log_sigmoid paddle.nn.functional.log_sigmoid
paddle.fluid.executor.Executor paddle.static.Executor paddle.fluid.executor.Executor paddle.static.Executor
paddle.nn.functional.pooling.avg_pool2d paddle.nn.functional.avg_pool2d paddle.nn.functional.pooling.avg_pool2d paddle.nn.functional.avg_pool2d
paddle.fluid.dygraph.checkpoint.load_dygraph paddle.load,paddle.framework.load paddle.framework.io.load paddle.load,paddle.framework.load
paddle.fluid.dygraph.container.Sequential paddle.nn.Sequential paddle.fluid.dygraph.container.Sequential paddle.nn.Sequential
paddle.fluid.dygraph.BilinearTensorProduct paddle.nn.BilinearTensorProduct,paddle.nn.layer.BilinearTensorProduct,paddle.nn.layer.common.BilinearTensorProduct paddle.fluid.dygraph.BilinearTensorProduct paddle.nn.BilinearTensorProduct,paddle.nn.layer.BilinearTensorProduct,paddle.nn.layer.common.BilinearTensorProduct
paddle.fluid.layers.box_coder paddle.nn.functional.box_coder,paddle.nn.functional.vision.box_coder paddle.fluid.layers.box_coder paddle.nn.functional.box_coder,paddle.nn.functional.vision.box_coder
...@@ -251,7 +251,7 @@ paddle.nn.functional.activation.prelu paddle.nn.functional.prelu ...@@ -251,7 +251,7 @@ paddle.nn.functional.activation.prelu paddle.nn.functional.prelu
paddle.tensor.linalg.matmul paddle.matmul,paddle.tensor.matmul paddle.tensor.linalg.matmul paddle.matmul,paddle.tensor.matmul
paddle.fluid.layers.generate_proposals paddle.nn.functional.generate_proposals,paddle.nn.functional.vision.generate_proposals paddle.fluid.layers.generate_proposals paddle.nn.functional.generate_proposals,paddle.nn.functional.vision.generate_proposals
paddle.nn.layer.loss.SmoothL1Loss paddle.nn.SmoothL1Loss,paddle.nn.layer.SmoothL1Loss paddle.nn.layer.loss.SmoothL1Loss paddle.nn.SmoothL1Loss,paddle.nn.layer.SmoothL1Loss
paddle.fluid.dygraph.checkpoint.save_dygraph paddle.save,paddle.framework.save paddle.framework.io.save paddle.save,paddle.framework.save
paddle.fluid.core paddle.framework.core paddle.fluid.core paddle.framework.core
paddle.nn.functional.vision.grid_sample paddle.nn.functional.grid_sample paddle.nn.functional.vision.grid_sample paddle.nn.functional.grid_sample
paddle.tensor.random.rand paddle.rand,paddle.tensor.rand paddle.tensor.random.rand paddle.rand,paddle.tensor.rand
...@@ -282,7 +282,7 @@ paddle.framework.get_default_dtype paddle.get_default_dtype ...@@ -282,7 +282,7 @@ paddle.framework.get_default_dtype paddle.get_default_dtype
paddle.fluid.layers.atan paddle.atan,paddle.tensor.atan,paddle.tensor.math.atan paddle.fluid.layers.atan paddle.atan,paddle.tensor.atan,paddle.tensor.math.atan
paddle.fluid.layers.pad2d paddle.nn.functional.pad2d,paddle.nn.functional.common.pad2d paddle.fluid.layers.pad2d paddle.nn.functional.pad2d,paddle.nn.functional.common.pad2d
paddle.nn.layer.pooling.MaxPool3d paddle.nn.MaxPool3d,paddle.nn.layer.MaxPool3d paddle.nn.layer.pooling.MaxPool3d paddle.nn.MaxPool3d,paddle.nn.layer.MaxPool3d
paddle.fluid.io.load paddle.static.load,paddle.tensor.load,paddle.tensor.io.load paddle.fluid.io.load paddle.static.load
paddle.fluid.dygraph.learning_rate_scheduler.ExponentialDecay paddle.ExponentialDecay,paddle.framework.ExponentialDecay paddle.fluid.dygraph.learning_rate_scheduler.ExponentialDecay paddle.ExponentialDecay,paddle.framework.ExponentialDecay
paddle.fluid.layers.conv3d paddle.static.nn.conv3d paddle.fluid.layers.conv3d paddle.static.nn.conv3d
paddle.nn.layer.activation.Softmax paddle.nn.Softmax paddle.nn.layer.activation.Softmax paddle.nn.Softmax
...@@ -447,7 +447,7 @@ paddle.tensor.stat.numel paddle.numel,paddle.tensor.numel ...@@ -447,7 +447,7 @@ paddle.tensor.stat.numel paddle.numel,paddle.tensor.numel
paddle.nn.functional.activation.relu6 paddle.nn.functional.relu6 paddle.nn.functional.activation.relu6 paddle.nn.functional.relu6
paddle.tensor.math.cumsum paddle.cumsum,paddle.tensor.cumsum paddle.tensor.math.cumsum paddle.cumsum,paddle.tensor.cumsum
paddle.fluid.layers.resize_trilinear paddle.nn.functional.resize_trilinear,paddle.nn.functional.vision.resize_trilinear paddle.fluid.layers.resize_trilinear paddle.nn.functional.resize_trilinear,paddle.nn.functional.vision.resize_trilinear
paddle.fluid.save paddle.static.save,paddle.tensor.save,paddle.tensor.io.save paddle.fluid.io.save paddle.static.save
paddle.fluid.layers.scale paddle.scale,paddle.tensor.scale,paddle.tensor.math.scale paddle.fluid.layers.scale paddle.scale,paddle.tensor.scale,paddle.tensor.math.scale
paddle.fluid.framework.default_startup_program paddle.static.default_startup_program paddle.fluid.framework.default_startup_program paddle.static.default_startup_program
paddle.fluid.layers.noam_decay paddle.nn.functional.noam_decay,paddle.nn.functional.learning_rate.noam_decay paddle.fluid.layers.noam_decay paddle.nn.functional.noam_decay,paddle.nn.functional.learning_rate.noam_decay
...@@ -561,7 +561,6 @@ paddle.text.datasets.conll05.Conll05st paddle.text.datasets.Conll05st,paddle.tex ...@@ -561,7 +561,6 @@ paddle.text.datasets.conll05.Conll05st paddle.text.datasets.Conll05st,paddle.tex
paddle.text.datasets.imdb.Imdb paddle.text.datasets.Imdb,paddle.text.Imdb paddle.text.datasets.imdb.Imdb paddle.text.datasets.Imdb,paddle.text.Imdb
paddle.text.datasets.imikolov.Imikolov paddle.text.datasets.Imikolov,paddle.text.Imikolov paddle.text.datasets.imikolov.Imikolov paddle.text.datasets.Imikolov,paddle.text.Imikolov
paddle.text.datasets.movielens.Movielens paddle.text.datasets.Movielens,paddle.text.Movielens paddle.text.datasets.movielens.Movielens paddle.text.datasets.Movielens,paddle.text.Movielens
paddle.text.datasets.movie_reviews.MovieReviews paddle.text.datasets.MovieRevie,paddle.text.MovieRevie
paddle.text.datasets.uci_housing.UCIHousing paddle.text.datasets.UCIHousing,paddle.text.UCIHousing paddle.text.datasets.uci_housing.UCIHousing paddle.text.datasets.UCIHousing,paddle.text.UCIHousing
paddle.text.datasets.wmt14.WMT14 paddle.text.datasets.WMT14,paddle.text.WMT14 paddle.text.datasets.wmt14.WMT14 paddle.text.datasets.WMT14,paddle.text.WMT14
paddle.text.datasets.wmt16.WMT16 paddle.text.datasets.WMT16,paddle.text.WMT16 paddle.text.datasets.wmt16.WMT16 paddle.text.datasets.WMT16,paddle.text.WMT16
......
...@@ -20,6 +20,9 @@ api_set = set() ...@@ -20,6 +20,9 @@ api_set = set()
def get_all_api(root_path='paddle'): def get_all_api(root_path='paddle'):
for filefiner, name, ispkg in pkgutil.walk_packages( for filefiner, name, ispkg in pkgutil.walk_packages(
path=paddle.__path__, prefix=paddle.__name__ + '.'): path=paddle.__path__, prefix=paddle.__name__ + '.'):
# not show paddle.reader APIs
if name.startswith("paddle.reader"):
continue
try: try:
m = eval(name) m = eval(name)
except AttributeError: except AttributeError:
......
paddle.utils paddle.utils
paddle.incubate paddle.incubate
paddle.hapi.progressbar.ProgressBar paddle.hapi.progressbar.ProgressBar
paddle.metric.accuracy paddle.fluid.contrib
paddle.metric.auc paddle.optimizer._LRScheduler
paddle.fluid.dygraph.dygraph_to_static
.. _cn_api_paddle_dataset_sentiment:
sentiment
-------------------------------
脚本获取并预处理由NLTK提供的movie_reviews数据集。
.. py:function:: paddle.dataset.sentiment.get_word_dict()
按照样本中出现的单词的频率对单词进行排序。
返回: words_freq_sorted
.. py:function:: paddle.dataset.sentiment.train()
默认的训练集reader creator。
.. py:function:: paddle.dataset.sentiment.test()
默认的测试集reader creator。
.. py:function:: paddle.dataset.sentiment.convert(path)
将数据集转换为recordio格式。
...@@ -30,6 +30,35 @@ DistributedStrategy ...@@ -30,6 +30,35 @@ DistributedStrategy
**checkpoints(int):** Recompute策略的检查点,默认为空列表,也即不启用Recompute。 **checkpoints(int):** Recompute策略的检查点,默认为空列表,也即不启用Recompute。
.. py:attribute:: pipeline
是否启用Pipeline并行。目前,主要实现单机多GPU间的Pipeline并行和多机间的数据并行。Pipeline信息由用户定义程序中的device_guard确定。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.pipeline = True
.. py:attribute:: pipeline_configs
设置Pipeline策略的配置。Pipeline策略下,神经网络的不同层在不同的GPU设备。相邻的GPU设备间有用于同步隐层Tensor的队列。Pipeline并行包含多种生产者-消费者形式的硬件对,如GPU-CPU、CPU-GPU、GPU-XPU。加速PIpeline并行的最佳方式是减少Tensor队列中的Tensor大小,这样生产者可以更快的为下游消费者提供数据。
**micro_batch (int):** 每个用户定义的mini-batch中包含的更小的micro-batch的数量。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.pipeline = True
strategy.pipeline_configs = {"micro_batch": 12}
.. py:attribute:: gradient_merge .. py:attribute:: gradient_merge
梯度累加,是一种大Batch训练的策略。添加这一策略后,模型的参数每过 **k_steps** 步更新一次, 梯度累加,是一种大Batch训练的策略。添加这一策略后,模型的参数每过 **k_steps** 步更新一次,
...@@ -102,3 +131,137 @@ DistributedStrategy ...@@ -102,3 +131,137 @@ DistributedStrategy
**lamb_weight_decay(float):** lars 公式中 weight decay 系数。 默认值是 0.01. **lamb_weight_decay(float):** lars 公式中 weight decay 系数。 默认值是 0.01.
**exclude_from_weight_decay(list[str]):** 不应用 weight decay 的 layers 的名字列表,某一layer 的name 如果在列表中,这一layer 的 lamb_weight_decay将被置为 0. 默认值是 None. **exclude_from_weight_decay(list[str]):** 不应用 weight decay 的 layers 的名字列表,某一layer 的name 如果在列表中,这一layer 的 lamb_weight_decay将被置为 0. 默认值是 None.
.. py:attribute:: localsgd
是否使用LocalSGD optimizer,默认值:False。更多的细节请参考[Don't Use Large Mini-Batches, Use Local SGD](https://arxiv.org/pdf/1808.07217.pdf)
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.localsgd = True # by default this is false
.. py:attribute:: localsgd_configs
设置LocalSGD优化器的参数。用户可以配置k_steps和begin_step参数。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.localsgd = True
strategy.localsgd_configs = {"k_steps": 4,
"begin_step": 30}
**k_steps(int):** 训练过程中的全局参数更新间隔,默认值1。
**begin_step(int):** 指定从第几个step之后进行local SGD算法,默认值1。
.. py:attribute:: adaptive_localsgd
是否使用AdaptiveLocalSGD optimizer,默认值:False。更多的细节请参考[Adaptive Communication Strategies to Achieve the Best Error-Runtime Trade-off in Local-Update SGD](https://arxiv.org/pdf/1810.08313.pdf)
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.adaptive_localsgd = True # by default this is false
.. py:attribute:: adaptive_localsgd_configs
设置AdaptiveLocalSGD优化器的参数。用户可以配置init_k_steps和begin_step参数。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.adaptive_localsgd = True
strategy.adaptive_localsgd_configs = {"init_k_steps": 1,
"begin_step": 30}
**init_k_steps(int):** 自适应localsgd的初始训练步长。训练后,自适应localsgd方法将自动调整步长。 默认值1。
**begin_step(int):** 指定从第几个step之后进行Adaptive LocalSGD算法,默认值1。
.. py:attribute:: amp
是否启用自动混合精度训练。默认值:False
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.amp = True # by default this is false
.. py:attribute:: amp_configs
设置自动混合精度训练配置。为避免梯度inf或nan,amp会根据梯度值自动调整loss scale值。目前可以通过字典设置以下配置。
**init_loss_scaling(float):** 初始loss scaling值。默认值32768。
**use_dynamic_loss_scaling(bool):** 是否动态调整loss scale值。默认True。
**incr_every_n_steps(int):** 每经过n个连续的正常梯度值才会增大loss scaling值。默认值1000。
**decr_every_n_nan_or_inf(int):** 每经过n个连续的无效梯度值(nan或者inf)才会减小loss scaling值。默认值2。
**incr_ratio(float):** 每次增大loss scaling值的扩增倍数,其为大于1的浮点数。默认值2.0。
**decr_ratio(float):** 每次减小loss scaling值的比例系数,其为小于1的浮点数。默认值0.5。
**custom_white_list(list[str]):** 用户自定义OP开启fp16执行的白名单。
**custom_black_list(list[str]):** 用户自定义OP禁止fp16执行的黑名单。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.amp = True
strategy.amp_configs = {
"init_loss_scaling": 32768,
"custom_white_list": ['conv2d']}
.. py:attribute:: dgc
是否启用深度梯度压缩训练。更多信息请参考[Deep Gradient Compression](https://arxiv.org/abs/1712.01887)。 默认值:False
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.dgc = True # by default this is false
.. py:attribute:: dgc_configs
设置dgc策略的配置。目前用户可配置 rampup_begin_step,rampup_step,sparsity参数。
**rampup_begin_step(int):** 梯度压缩的起点步。默认值0。
**rampup_step(int):** 使用稀疏预热的时间步长。默认值为1。例如:如果稀疏度为[0.75,0.9375,0.984375,0.996,0.999],\
并且rampup_step为100,则在0~19步时使用0.75,在20~39步时使用0.9375,依此类推。当到达sparsity数组末尾时,此后将会使用0.999。
**sparsity(list[float]):** 从梯度张量中获取top个重要元素,比率为(1-当前稀疏度)。默认值为[0.999]。\
例如:如果sparsity为[0.99, 0.999],则将传输top [1%, 0.1%]的重要元素。
**示例代码**
.. code-block:: python
import paddle.distributed.fleet as fleet
strategy = fleet.DistributedStrategy()
strategy.dgc = True
strategy.dgc_configs = {"rampup_begin_step": 1252}
...@@ -6,80 +6,723 @@ Fleet ...@@ -6,80 +6,723 @@ Fleet
.. py:class:: paddle.distributed.fleet.Fleet .. py:class:: paddle.distributed.fleet.Fleet
Fleet是飞桨分布式训练统一API, 只需要import fleet并简单初始化后即可快速开始使用飞桨大规模分布式训练
.. py:method:: init(role_maker=None, is_collective=False) .. py:method:: init(role_maker=None, is_collective=False)
使用RoleMaker或其他配置初始化fleet
参数:
role_maker (RoleMakerBase) 已初始化好的PaddleCloudRoleMakerUserDefineRoleMaker
is_collective (bool) 在未指定role_maker的情况下,可由init方法自行初始化RoleMaker, is_collectiveTrue则按照collective模式进行创建, is_collective=False则按照ParameterServer模式进行创建
返回:None
**代码示例1**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
**代码示例2**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init(is_collective=True)
**代码示例3**
.. code-block:: python
import paddle.distributed.fleet as fleet
role = fleet.PaddleCloudRoleMaker()
fleet.init(role)
.. py:method:: is_first_worker() .. py:method:: is_first_worker()
返回当前节点是否为第一个`worker`节点, 判断当前worker_index是否为0 如果为0则返回True,否则返回False
返回:True/False
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.is_first_worker()
.. py:method:: worker_index() .. py:method:: worker_index()
返回当前节点的编号, 每个`worker`节点被分配[0, worker_num-1]内的唯一的编码ID
返回:int
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.worker_index()
.. py:method:: worker_num() .. py:method:: worker_num()
返回当前全部训练节点中`workjer`节点的个数
返回:int
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.worker_num()
.. py:method:: is_worker() .. py:method:: is_worker()
返回当前节点是否为`worker`节点
返回:True/False
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.is_worker()
.. py:method:: worker_endpoints(to_string=False) .. py:method:: worker_endpoints(to_string=False)
返回全部worker节点的ip及端口信息
返回:list/string
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.worker_endpoints()
.. py:method:: server_num() .. py:method:: server_num()
**注意:**
**该参数只在ParameterServer模式下生效**
返回当前全部Server节点的个数
返回:int
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.server_num()
.. py:method:: server_index() .. py:method:: server_index()
**注意:**
**该参数只在ParameterServer模式下生效**
返回当前节点的编号, 每个`server`节点被分配[0, server_num-1]内的唯一的编码ID
返回:int
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.server_index()
.. py:method:: server_endpoints(to_string=False) .. py:method:: server_endpoints(to_string=False)
**注意:**
**该参数只在ParameterServer模式下生效**
返回全部server节点的ip及端口信息
返回:list/string
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.server_endpoints()
.. py:method:: is_server() .. py:method:: is_server()
**注意:**
**该参数只在ParameterServer模式下生效**
返回当前节点是否为`server`节点
返回:True/False
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.is_server()
.. py:method:: barrier_worker() .. py:method:: barrier_worker()
调用集合通信功能,强制要求所有的worker在此处相互等待一次
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.barrier_worker()
.. py:method:: init_worker() .. py:method:: init_worker()
worker节点在训练前的初始化, 包括通信模块, 参数同步等
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.init_worker()
.. py:method:: init_server(*args, **kwargs) .. py:method:: init_server(*args, **kwargs)
server节点的初始化, 包括server端参数初始化,模型加载等
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.init_server()
.. py:method:: run_server() .. py:method:: run_server()
server节点的运行, 此命令会将ParameterServer的进程启动并常驻直至训练结束
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.init_server()
fleet.run_server()
.. py:method:: stop_worker() .. py:method:: stop_worker()
停止当前正在运行的worker节点
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
fleet.init()
fleet.init_worker()
"..."
fleet.stop_worker()
.. py:method:: save_inference_model(executor, dirname, feeded_var_names, target_vars, main_program=None, export_for_deployment=True) .. py:method:: save_inference_model(executor, dirname, feeded_var_names, target_vars, main_program=None, export_for_deployment=True)
修剪指定的 ``main_program`` 以构建一个专门用于预测的 ``Inference Program`` ``Program`` 含义详见 :ref:`api_guide_Program` )。 所得到的 ``Inference Program`` 及其对应的所>有相关参数均被保存到 ``dirname`` 指定的目录中。
参数:
- **executor** (Executor) 用于保存预测模型的 ``executor`` ,详见 :ref:`api_guide_executor`
- **dirname** (str) 指定保存预测模型结构和参数的文件目录。
- **feeded_var_names** (list[str]) 字符串列表,包含着Inference Program预测时所需提供数据的所有变量名称(即所有输入变量的名称)。
- **target_vars** (list[Variable]) ``Variable`` (详见 :ref:`api_guide_Program` )类型列表,包含着模型的所有输出变量。通过这些输出变量即可得到模型的预测结果。
- **main_program** (Program,可选) 通过该参数指定的 ``main_program`` 可构建一个专门用于预测的 ``Inference Program`` 若为None, 则使用全局默认的 ``_main_program_`` >默认值为None
- **export_for_deployment** (bool,可选) 若为True,则 ``main_program`` 指定的Program将被修改为只支持直接预测部署的Program。否则,将存储更多的信息,方便优化和再训练。目前
只支持设置为True,且默认值为True
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
import paddle.fluid as fluid
fleet.init()
# build net
# fleet.distributed_optimizer(...)
exe = fluid.Executor(fluid.CPUPlace())
fleet.save_inference_model(exe, "dirname", ["feednames1"], [acc, loss], fluid.default_main_program())
.. py:method:: save_persistables(executor, dirname, main_program=None) .. py:method:: save_persistables(executor, dirname, main_program=None)
保存全量模型参数
参数:
- **executor** (Executor) 用于保存持久性变量的 ``executor`` ,详见 :ref:`api_guide_executor`
- **dirname** (str) 用于储存持久性变量的文件目录。
- **main_program** (Program,可选) 需要保存持久性变量的Program ``Program`` 含义详见 :ref:`api_guide_Program` )。如果为None,则使用default_main_Program 。默认值为None>
返回:无
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
import paddle.fluid as fluid
fleet.init()
# build net
# fleet.distributed_optimizer(...)
exe = fluid.Executor(fluid.CPUPlace())
fleet.save_persistables(exe, "dirname", fluid.default_main_program())
.. py:method:: distributed_optimizer(optimizer, strategy=None) .. py:method:: distributed_optimizer(optimizer, strategy=None)
基于分布式布式并行策略进行模型的拆分及优化。
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
role = fleet.role_maker.PaddleCloudRoleMaker(is_collective=True)
fleet.init(role)
strategy = fleet.DistributedStrategy()
optimizer = paddle.optimizer.SGD(learning_rate=0.001)
optimizer = fleet.distributed_optimizer(optimizer, strategy=strategy)
.. py:method:: distributed_model(model) .. py:method:: distributed_model(model)
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
返回分布式数据并行模型。
参数:
model (Layer) - 用户定义的模型,此处模型是指继承动态图Layer的网络。
返回:分布式数据并行模型,该模型同样继承动态图Layer
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import paddle
import paddle.nn as nn
from paddle.distributed import fleet
class LinearNet(nn.Layer):
def __init__(self):
super(LinearNet, self).__init__()
self._linear1 = nn.Linear(10, 10)
self._linear2 = nn.Linear(10, 1)
def forward(self, x):
return self._linear2(self._linear1(x))
# 1. enable dynamic mode
paddle.disable_static()
# 2. initialize fleet environment
fleet.init(is_collective=True)
# 3. create layer & optimizer
layer = LinearNet()
loss_fn = nn.MSELoss()
adam = paddle.optimizer.Adam(
learning_rate=0.001, parameters=layer.parameters())
# 4. get data_parallel model using fleet
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
# 5. run layer
inputs = paddle.randn([10, 10], 'float32')
outputs = dp_layer(inputs)
labels = paddle.randn([10, 1], 'float32')
loss = loss_fn(outputs, labels)
print("loss:", loss.numpy())
loss = dp_layer.scale_loss(loss)
loss.backward()
dp_layer.apply_collective_grads()
adam.step()
adam.clear_grad()
.. py:method:: state_dict() .. py:method:: state_dict()
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
``dict`` 返回当前 ``optimizer`` 使用的所有Tensor 。比如对于Adam优化器,将返回 beta1, beta2, momentum Tensor
返回:dict, 当前 ``optimizer`` 使用的所有Tensor
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import numpy as np
import paddle
from paddle.distributed import fleet
paddle.disable_static()
fleet.init(is_collective=True)
value = np.arange(26).reshape(2, 13).astype("float32")
a = paddle.fluid.dygraph.to_variable(value)
layer = paddle.nn.Linear(13, 5)
adam = paddle.optimizer.Adam(learning_rate=0.01, parameters=layer.parameters())
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
state_dict = adam.state_dict()
.. py:method:: set_state_dict(state_dict)
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
加载 ``optimizer`` Tensor字典给当前 ``optimizer``
返回:None
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import numpy as np
import paddle
from paddle.distributed import fleet
paddle.disable_static()
fleet.init(is_collective=True)
value = np.arange(26).reshape(2, 13).astype("float32")
a = paddle.fluid.dygraph.to_variable(value)
layer = paddle.nn.Linear(13, 5)
adam = paddle.optimizer.Adam(learning_rate=0.01, parameters=layer.parameters())
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
state_dict = adam.state_dict()
paddle.framework.save(state_dict, "paddle_dy")
para_state_dict, opti_state_dict = paddle.framework.load( "paddle_dy")
adam.set_state_dict(opti_state_dict)
.. py:method:: set_lr(value) .. py:method:: set_lr(value)
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
手动设置当前 ``optimizer`` 的学习率。
参数:
value (float) - 需要设置的学习率的值。
返回:None
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import numpy as np
import paddle
from paddle.distributed import fleet
paddle.disable_static()
fleet.init(is_collective=True)
value = np.arange(26).reshape(2, 13).astype("float32")
a = paddle.fluid.dygraph.to_variable(value)
layer = paddle.nn.Linear(13, 5)
adam = paddle.optimizer.Adam(learning_rate=0.01, parameters=layer.parameters())
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
lr_list = [0.2, 0.3, 0.4, 0.5, 0.6]
for i in range(5):
adam.set_lr(lr_list[i])
lr = adam.get_lr()
print("current lr is {}".format(lr))
# Print:
# current lr is 0.2
# current lr is 0.3
# current lr is 0.4
# current lr is 0.5
# current lr is 0.6
.. py:method:: get_lr() .. py:method:: get_lr()
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
获取当前步骤的学习率。
返回:float,当前步骤的学习率。
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import numpy as np
import paddle
from paddle.distributed import fleet
paddle.disable_static()
fleet.init(is_collective=True)
value = np.arange(26).reshape(2, 13).astype("float32")
a = paddle.fluid.dygraph.to_variable(value)
layer = paddle.nn.Linear(13, 5)
adam = paddle.optimizer.Adam(learning_rate=0.01, parameters=layer.parameters())
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
lr = adam.get_lr()
print(lr) # 0.01
.. py:method:: step() .. py:method:: step()
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
执行一次优化器并进行参数更新。
返回:None
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import paddle
import paddle.nn as nn
from paddle.distributed import fleet
class LinearNet(nn.Layer):
def __init__(self):
super(LinearNet, self).__init__()
self._linear1 = nn.Linear(10, 10)
self._linear2 = nn.Linear(10, 1)
def forward(self, x):
return self._linear2(self._linear1(x))
# 1. enable dynamic mode
paddle.disable_static()
# 2. initialize fleet environment
fleet.init(is_collective=True)
# 3. create layer & optimizer
layer = LinearNet()
loss_fn = nn.MSELoss()
adam = paddle.optimizer.Adam(
learning_rate=0.001, parameters=layer.parameters())
# 4. get data_parallel model using fleet
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
# 5. run layer
inputs = paddle.randn([10, 10], 'float32')
outputs = dp_layer(inputs)
labels = paddle.randn([10, 1], 'float32')
loss = loss_fn(outputs, labels)
print("loss:", loss.numpy())
loss = dp_layer.scale_loss(loss)
loss.backward()
dp_layer.apply_collective_grads()
adam.step()
adam.clear_grad()
.. py:method:: clear_grad() .. py:method:: clear_grad()
**注意:**
**1. API只在** `Dygraph <../../user_guides/howto/dygraph/DyGraph.html>`_ **模式下生效**
清除需要优化的参数的梯度。
返回:None
**代码示例**
.. code-block:: python
# 这个示例需要由fleetrun启动, 用法为:
# fleetrun --gpus=0,1 example.py
# 脚本example.py中的代码是下面这个示例.
import paddle
import paddle.nn as nn
from paddle.distributed import fleet
class LinearNet(nn.Layer):
def __init__(self):
super(LinearNet, self).__init__()
self._linear1 = nn.Linear(10, 10)
self._linear2 = nn.Linear(10, 1)
def forward(self, x):
return self._linear2(self._linear1(x))
# 1. enable dynamic mode
paddle.disable_static()
# 2. initialize fleet environment
fleet.init(is_collective=True)
# 3. create layer & optimizer
layer = LinearNet()
loss_fn = nn.MSELoss()
adam = paddle.optimizer.Adam(
learning_rate=0.001, parameters=layer.parameters())
# 4. get data_parallel model using fleet
adam = fleet.distributed_optimizer(adam)
dp_layer = fleet.distributed_model(layer)
# 5. run layer
inputs = paddle.randn([10, 10], 'float32')
outputs = dp_layer(inputs)
labels = paddle.randn([10, 1], 'float32')
loss = loss_fn(outputs, labels)
print("loss:", loss.numpy())
loss = dp_layer.scale_loss(loss)
loss.backward()
dp_layer.apply_collective_grads()
adam.step()
adam.clear_grad()
.. py:method:: minimize(loss, startup_program=None, parameter_list=None, no_grad_set=None) .. py:method:: minimize(loss, startup_program=None, parameter_list=None, no_grad_set=None)
......
...@@ -5,6 +5,41 @@ PaddleCloudRoleMaker ...@@ -5,6 +5,41 @@ PaddleCloudRoleMaker
.. py:class:: paddle.distributed.fleet.PaddleCloudRoleMaker .. py:class:: paddle.distributed.fleet.PaddleCloudRoleMaker
PaddleCloudRoleMaker是基于从环境变量中获取分布式相关信息进行分布式配置初始化的接口.
它会自动根据用户在环境变量中的配置进行分布式训练环境初始化,目前PaddleCloudRoleMaker支持ParameterServer分布式训练及Collective分布式训练两种模式的初始化。
**代码示例**
.. code-block:: python
import os
import paddle.distributed.fleet as fleet
os.environ["PADDLE_PSERVER_NUMS"] = "2"
os.environ["PADDLE_TRAINERS_NUM"] = "2"
os.environ["POD_IP"] = "127.0.0.1"
os.environ["PADDLE_PORT"] = "36001"
os.environ["TRAINING_ROLE"] = "PSERVER"
os.environ["PADDLE_PSERVERS_IP_PORT_LIST"] = \
"127.0.0.1:36001,127.0.0.2:36001"
os.environ["PADDLE_TRAINER_ID"] = "0"
fleet.PaddleCloudRoleMaker(is_collective=False)
.. py:method:: to_string()
将当前环境变量以字符串的形式输出
返回: string
**代码示例**:
.. code-block:: python
import paddle.distributed.fleet as fleet
role = fleet.PaddleCloudRoleMaker(is_collective=False)
role.to_string()
...@@ -5,6 +5,45 @@ UserDefinedRoleMaker ...@@ -5,6 +5,45 @@ UserDefinedRoleMaker
.. py:class:: paddle.distributed.fleet.UserDefinedRoleMaker .. py:class:: paddle.distributed.fleet.UserDefinedRoleMaker
UserDefinedRoleMaker是基于从用户自定义的参数中获取分布式相关信息进行分布式配置初始化的接口
它会自动根据用户的自定义配置进行分布式训练环境初始化,目前UserDefinedRoleMaker支持ParameterServer分布式训练及Collective分布式训练两种模式的初始化。
**代码示例**
.. code-block:: python
import paddle.distributed.fleet as fleet
from paddle.distributed.fleet.base.role_maker import Role
fleet.UserDefinedRoleMaker(
current_id=0,
role=Role.SERVER,
worker_num=2,
server_endpoints=["127.0.0.1:36011", "127.0.0.1:36012"])
.. py:method:: to_string()
将当前环境变量以字符串的形式输出
返回: string
**代码示例**:
.. code-block:: python
import paddle.distributed.fleet as fleet
from paddle.distributed.fleet.base.role_maker import Role
role = fleet.UserDefinedRoleMaker(
current_id=0,
role=Role.SERVER,
worker_num=2,
server_endpoints=["127.0.0.1:36011", "127.0.0.1:36012"])
role.to_string()
...@@ -4,7 +4,189 @@ UtilBase ...@@ -4,7 +4,189 @@ UtilBase
------------------------------- -------------------------------
.. py:class:: paddle.distributed.fleet.UtilBase .. py:class:: paddle.distributed.fleet.UtilBase
分布式训练工具类,主要提供集合通信、文件系统操作等接口。
.. py:method:: all_reduce(input, mode="sum", comm_world="worker")
在指定的通信集合间进行归约操作,并将归约结果返回给集合中每个实例。
参数:
- **input** (list|numpy.array) – 归约操作的输入。
- **mode** (str) - 归约操作的模式,包含求和,取最大值和取最小值,默认为求和归约。
- **comm_world** (str) - 归约操作的通信集合,包含: server集合(“server"),worker集合("worker")及所有节点集合("all"),默认为worker集合。
返回:
- Numpy.array|None: 一个和 `input` 形状一致的numpy数组或None.
**代码示例**:
.. code-block:: python
# Save the following code in `train.py` , and then execute the command `fleetrun --server_num 2 --worker_num 2 train.py` .
from paddle.distributed.fleet.base.util_factory import fleet_util
import paddle.distributed.fleet as fleet
from paddle.distributed.fleet import PaddleCloudRoleMaker
import sys
import numpy as np
def train():
role = PaddleCloudRoleMaker(
is_collective=False,
init_gloo=True,
path="./tmp_gloo")
fleet.init(role)
fleet_util._set_role_maker(role)
if fleet.is_server():
input = [1, 2]
output = fleet_util.all_reduce(input, "sum", "server")
print(output)
# [2, 4]
elif fleet.is_worker():
input = np.array([3, 4])
output = fleet_util.all_reduce(input, "sum", "worker")
print(output)
# [6, 8]
output = fleet_util.all_reduce(input, "sum", "all")
print(output)
# [8, 12]
if __name__ == "__main__":
train()
.. py:method:: barrier(comm_world="worker")
在指定的通信集合间进行阻塞操作,以实现集合间进度同步。
参数:
- **comm_world** (str) - 阻塞操作的通信集合,包含: server集合(“server"),worker集合("worker")及所有节点集合("all"),默认为worker集合。
**代码示例**:
.. code-block:: python
# Save the following code in `train.py` , and then execute the command `fleetrun --server_num 2 --worker_num 2 train.py` .
from paddle.distributed.fleet.base.util_factory import fleet_util
import paddle.distributed.fleet as fleet
from paddle.distributed.fleet import PaddleCloudRoleMaker
import sys
def train():
role = PaddleCloudRoleMaker(
is_collective=False,
init_gloo=True,
path="./tmp_gloo")
fleet.init(role)
fleet_util._set_role_maker(role)
if fleet.is_server():
fleet_util.barrier("server")
print("all server arrive here")
elif fleet.is_worker():
fleet_util.barrier("worker")
print("all server arrive here")
fleet_util.barrier("all")
print("all servers and workers arrive here")
if __name__ == "__main__":
train()
.. py:method:: all_gather(input, comm_world="worker")
在指定的通信集合间进行聚合操作,并将聚合的结果返回给集合中每个实例。
参数:
- **input** (int|float) - 聚合操作的输入。
- **comm_world** (str) - 聚合操作的通信集合,包含: server集合(“server"),worker集合("worker")及所有节点集合("all"),默认为worker集合。
返回:
- **output** (List): List格式的聚合结果。
**代码示例**:
.. code-block:: python
# Save the following code in `train.py` , and then execute the command `fleetrun --server_num 2 --worker_num 2 train.py` .
from paddle.distributed.fleet.base.util_factory import fleet_util
import paddle.distributed.fleet as fleet
from paddle.distributed.fleet import PaddleCloudRoleMaker
import sys
def train():
role = PaddleCloudRoleMaker(
is_collective=False,
init_gloo=True,
path="./tmp_gloo")
fleet.init(role)
fleet_util._set_role_maker(role)
if fleet.is_server():
input = fleet.server_index()
output = fleet_util.all_gather(input, "server")
print(output)
# output = [0, 1]
elif fleet.is_worker():
input = fleet.worker_index()
output = fleet_util.all_gather(input, "worker")
# output = [0, 1]
print(output)
output = fleet_util.all_gather(input, "all")
print(output)
# output = [0, 1, 0, 1]
if __name__ == "__main__":
train()
.. py:method:: get_file_shard(files)
在数据并行的分布式训练中,获取属于当前训练节点的文件列表。
.. code-block:: text
示例 1: 原始所有文件列表 `files` = [a, b, c ,d, e],训练节点个数 `trainer_num` = 2,那么属于零号节点的训练文件为[a, b, c],属于1号节点的训练文件为[d, e]。
示例 2: 原始所有文件列表 `files` = [a, b],训练节点个数 `trainer_num` = 3,那么属于零号节点的训练文件为[a],属于1号节点的训练文件为[b],属于2号节点的训练文件为[]。
参数:
- **files** (List):原始所有文件列表。
返回:
- List: 属于当前训练节点的文件列表。
**代码示例**:
.. code-block:: python
from paddle.distributed.fleet.base.util_factory import fleet_util
import paddle.distributed.fleet.base.role_maker as role_maker
role = role_maker.UserDefinedRoleMaker(
is_collective=False,
init_gloo=False,
current_id=0,
role=role_maker.Role.WORKER,
worker_endpoints=["127.0.0.1:6003", "127.0.0.1:6004"],
server_endpoints=["127.0.0.1:6001", "127.0.0.1:6002"])
fleet_util._set_role_maker(role)
files = fleet_util.get_file_shard(["file1", "file2", "file3"])
# files = ["file1", "file2"]
.. py:method:: print_on_rank(message, rank_id)
在编号为 `rank_id` 的节点上打印指定信息。
参数:
- **message** (str) – 打印内容。
- **rank_id** (int) - 节点编号。
**代码示例**:
.. code-block:: python
from paddle.distributed.fleet.base.util_factory import fleet_util
import paddle.distributed.fleet.base.role_maker as role_maker
role = role_maker.UserDefinedRoleMaker(
is_collective=False,
init_gloo=False,
current_id=0,
role=role_maker.Role.WORKER,
worker_endpoints=["127.0.0.1:6003", "127.0.0.1:6004"],
server_endpoints=["127.0.0.1:6001", "127.0.0.1:6002"])
fleet_util._set_role_maker(role)
fleet_util.print_on_rank("I'm worker 0", 0)
\ No newline at end of file
.. _cn_api_distributed_fleet_utils_fs_ExecuteError:
ExecuteError
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.ExecuteError
.. _cn_api_distributed_fleet_utils_fs_FSFileExistsError:
FSFileExistsError
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.FSFileExistsError
.. _cn_api_distributed_fleet_utils_fs_FSFileNotExistsError:
FSFileNotExistsError
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.FSFileNotExistsError
.. _cn_api_distributed_fleet_utils_fs_FSShellCmdAborted:
FSShellCmdAborted
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.FSShellCmdAborted
.. _cn_api_distributed_fleet_utils_fs_FSTimeOut:
FSTimeOut
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.FSTimeOut
.. _cn_api_distributed_fleet_utils_fs_FS:
FS
-------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.FS
...@@ -3,8 +3,279 @@ ...@@ -3,8 +3,279 @@
HDFSClient HDFSClient
------------------------------- -------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.HDFSClient .. py:class:: paddle.distributed.fleet.utils.HDFSClient
一个HADOOP文件系统工具类。
参数:
- **hadoop_home** (str):HADOOP HOME地址。
- **configs** (dict): HADOOP文件系统配置。需包含 `fs.default.name` 和 `hadoop.job.ugi` 这两个字段。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.ls_dir("hdfs:/test_hdfs_client")
.. py:method:: ls_dir(fs_path)
列出 `fs_path` 路径下所有的文件和子目录。
参数:
- **fs_path** (str): HADOOP文件路径。
返回:
- Tuple, 一个包含所有子目录和文件名的2-Tuple,格式形如: ([subdirname1, subdirname1, ...], [filename1, filename2, ...])。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
subdirs, files = client.ls_dir("hdfs:/test_hdfs_client")
.. py:method:: mkdirs(fs_path)
创建一个目录。
参数:
- **fs_path** (str): HADOOP文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.mkdirs("hdfs:/test_hdfs_client")
.. py:method:: delete(fs_path)
删除HADOOP文件(或目录)。
参数:
- **fs_path** (str): HADOOP文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.delete("hdfs:/test_hdfs_client")
.. py:method:: is_file(fs_path)
判断当前路径是否是一个文件。
参数:
- **fs_path** (str): HADOOP文件路径。
返回:
- Bool:若当前路径存在且是一个文件,返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
ret = client.is_file("hdfs:/test_hdfs_client")
.. py:method:: is_dir(fs_path)
判断当前路径是否是一个目录。
参数:
- **fs_path** (str): HADOOP文件路径。
返回:
- Bool:若当前路径存在且是一个目录,返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
ret = client.is_file("hdfs:/test_hdfs_client")
.. py:method:: is_exist(fs_path)
判断当前路径是否存在。
参数:
- **fs_path** (str): HADOOP文件路径。
返回:
- Bool:若当前路径存在返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
ret = client.is_exist("hdfs:/test_hdfs_client")
.. py:method:: upload(local_path, fs_path)
上传本地文件至HADOOP文件系统。
参数:
- **local_path** (str): 本地文件路径。
- **fs_path** (str): HADOOP文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.upload("test_hdfs_client", "hdfs:/test_hdfs_client")
.. py:method:: download(fs_path, local_path)
下载HADOOP文件至本地文件系统。
参数:
- **local_path** (str): 本地文件路径。
- **fs_path** (str): HADOOP文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.download("hdfs:/test_hdfs_client", "./")
.. py:method:: touch(fs_path, exist_ok=True)
创建一个HADOOP文件。
参数:
- **fs_path** (str): HADOOP文件路径。
- **exist_ok** (bool): 路径已存在时程序是否报错。若 `exist_ok = True`,则直接返回,反之则抛出文件存在的异常,默认不抛出异常。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.touch("hdfs:/test_hdfs_client")
.. py:method:: mv(fs_src_path, fs_dst_path, overwrite=False)
HADOOP系统文件移动。
参数:
- **fs_src_path** (str): 移动前源文件路径名。
- **fs_dst_path** (str): 移动后目标文件路径名。
- **overwrite** (bool): 若目标文件已存在,是否删除进行重写,默认不重写并抛出异常。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
client.mv("hdfs:/test_hdfs_client", "hdfs:/test_hdfs_client2")
.. py:method:: list_dirs(fs_path)
列出HADOOP文件路径下所有的子目录。
参数:
- **fs_path** (str): HADOOP文件路径。
返回:
- List: 该路径下所有的子目录名。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import HDFSClient
hadoop_home = "/home/client/hadoop-client/hadoop/"
configs = {
"fs.default.name": "hdfs://xxx.hadoop.com:54310",
"hadoop.job.ugi": "hello,hello123"
}
client = HDFSClient(hadoop_home, configs)
subdirs = client.list_dirs("hdfs:/test_hdfs_client")
...@@ -3,8 +3,196 @@ ...@@ -3,8 +3,196 @@
LocalFS LocalFS
------------------------------- -------------------------------
.. py:class:: paddle.distributed.fleet.utils.fs.LocalFS .. py:class:: paddle.distributed.fleet.utils.LocalFS
一个本地文件系统工具类。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
subdirs, files = client.ls_dir("./")
.. py:method:: ls_dir(fs_path)
列出 `fs_path` 路径下所有的文件和子目录。
参数:
- **fs_path** (str): 本地文件路径。
返回:
- Tuple, 一个包含所有子目录和文件名的2-Tuple,格式形如: ([subdirname1, subdirname1, ...], [filename1, filename2, ...])。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
subdirs, files = client.ls_dir("./")
.. py:method:: mkdirs(fs_path)
创建一个本地目录。
参数:
- **fs_path** (str): 本地文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.mkdirs("test_mkdirs")
client.delete("test_mkdirs")
.. py:method:: rename(fs_src_path, fs_dst_path)
重命名本地文件名。
参数:
- **fs_src_path** (str):重命名前原始文件名。
- **fs_dst_path** (str):新文件名。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.touch("test_rename_src")
print(client.is_exists("test_rename_src")) # True
client.rename("test_rename_src", "test_rename_dst")
print(client.is_exists("test_rename_src")) # False
print(client.is_exists("test_rename_dst")) # True
client.delete("test_rename_dst")
.. py:method:: delete(fs_path)
删除本地文件(或目录)。
参数:
- **fs_path** (str): 本地文件路径。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.mkdirs("test_localFS_mkdirs")
client.delete("test_localFS_mkdirs")
.. py:method:: is_file(fs_path)
判断当前路径是否是一个文件。
参数:
- **fs_path** (str): 本地文件路径。
返回:
- Bool:若当前路径存在且是一个文件,返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.touch("test_is_file")
print(client.is_file("test_is_file")) # True
client.delete("test_is_file")
.. py:method:: is_dir(fs_path)
判断当前路径是否是一个目录。
参数:
- **fs_path** (str): 本地文件路径。
返回:
- Bool:若当前路径存在且是一个目录,返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.mkdirs("test_is_dir")
print(client.is_dir("test_is_file")) # True
client.delete("test_is_dir")
.. py:method:: is_exist(fs_path)
判断当前路径是否存在。
参数:
- **fs_path** (str): 本地文件路径。
返回:
- Bool:若当前路径存在返回 `True` ,反之则返回 `False` 。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
ret = local_fs.is_exist("test_is_exist")
.. py:method:: touch(fs_path, exist_ok=True)
创建一个本地文件。
参数:
- **fs_path** (str): 本地文件路径。
- **exist_ok** (bool): 文件路径已存在时程序是否报错。若 `exist_ok = True`,则直接返回,反之则抛出文件存在的异常,默认不抛出异常。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.touch("test_touch")
client.delete("test_touch")
.. py:method:: mv(src_path, dst_path, overwrite=False)
本地文件移动。
参数:
- **src_path** (str): 移动前源文件路径名。
- **dst_path** (str): 移动后目标文件路径名。
- **overwrite** (bool): 若目标文件已存在,是否删除进行重写,默认不重写并抛出异常。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
client.touch("test_mv_src")
client.mv("test_mv_src", "test_mv_dst")
client.delete("test_mv_dst")
.. py:method:: list_dirs(fs_path)
列出本地路径下所有的子目录。
参数:
- **fs_path** (str): 本地文件路径。
返回:
- List: 该路径下所有的子目录名。
**示例代码**:
.. code-block:: python
from paddle.distributed.fleet.utils import LocalFS
client = LocalFS()
subdirs = client.list_dirs("./")
\ No newline at end of file
...@@ -4,17 +4,17 @@ load ...@@ -4,17 +4,17 @@ load
---- ----
.. py:function:: paddle.load(model_path, config=None) .. py:function:: paddle.fluid.dygraph.load_dygraph(model_path, config=None)
该接口用于从磁盘中加载Layer和Optimizer的 ``state_dict`` ,该接口会同时加载 ``model_path + ".pdparams"`` 和 ``model_path + ".pdopt"`` 中的内容。 该接口用于从磁盘中加载Layer和Optimizer的 ``state_dict`` ,该接口会同时加载 ``model_path + ".pdparams"`` 和 ``model_path + ".pdopt"`` 中的内容。
.. note:: .. note::
由于一些历史原因,如果从 ``paddle.io.save_inference_model`` 的存储结果中载入 ``state_dict`` ,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。 如果从 ``paddle.static.save_inference_model`` 的存储结果中载入 ``state_dict`` ,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。
参数: 参数:
- **model_path** (str) – 保存state_dict的文件前缀。该路径不应该包括后缀 ``.pdparams`` 或 ``.pdopt``。 - **model_path** (str) – 保存state_dict的文件前缀。该路径不应该包括后缀 ``.pdparams`` 或 ``.pdopt``。
- **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.io.save_inference_model`` 存储模型的格式。默认为 ``None``。 - **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.static.save_inference_model`` 存储模型的格式。默认为 ``None``。
返回: 两个 ``dict`` ,即从文件中恢复的模型参数 ``dict`` 和优化器参数 ``dict``,如果只找到其中一个的存储文件,另一个返回None 返回: 两个 ``dict`` ,即从文件中恢复的模型参数 ``dict`` 和优化器参数 ``dict``,如果只找到其中一个的存储文件,另一个返回None
...@@ -29,13 +29,14 @@ load ...@@ -29,13 +29,14 @@ load
.. code-block:: python .. code-block:: python
import paddle import paddle
import paddle.fluid as fluid
paddle.disable_static() paddle.disable_static()
emb = paddle.nn.Embedding([10, 10]) emb = paddle.nn.Embedding(10, 10)
state_dict = emb.state_dict() state_dict = emb.state_dict()
paddle.save(state_dict, "paddle_dy") fluid.save_dygraph(state_dict, "paddle_dy")
scheduler = paddle.optimizer.lr_scheduler.NoamLR( scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True) d_model=0.01, warmup_steps=100, verbose=True)
...@@ -43,9 +44,9 @@ load ...@@ -43,9 +44,9 @@ load
learning_rate=scheduler, learning_rate=scheduler,
parameters=emb.parameters()) parameters=emb.parameters())
state_dict = adam.state_dict() state_dict = adam.state_dict()
paddle.save(state_dict, "paddle_dy") fluid.save_dygraph(state_dict, "paddle_dy")
para_state_dict, opti_state_dict = paddle.load("paddle_dy") para_state_dict, opti_state_dict = fluid.load_dygraph("paddle_dy")
...@@ -5,7 +5,7 @@ SaveLoadConfig ...@@ -5,7 +5,7 @@ SaveLoadConfig
.. py:class:: paddle.SaveLoadConfig() .. py:class:: paddle.SaveLoadConfig()
用于配置接口 :ref:`cn_api_fluid_dygraph_jit_save` 和 :ref:`cn_api_fluid_dygraph_jit_load` 存储载入 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 时的附加选项。 用于配置接口 ``paddle.jit.save/load`` 和 ``paddle.load`` 存储载入时的附加选项。
**示例代码:** **示例代码:**
...@@ -74,10 +74,10 @@ SaveLoadConfig ...@@ -74,10 +74,10 @@ SaveLoadConfig
.. py:attribute:: output_spec .. py:attribute:: output_spec
选择保存模型( :ref:`cn_api_fluid_dygraph_TranslatedLayer` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。 选择保存模型( ``paddle.jit.TranslatedLayer`` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。
默认情况下,原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量都将配置为存储后模型 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 的输出变量。 默认情况下,原始 ``paddle.nn.Layer`` 的forward方法的所有返回变量都将配置为存储后模型 ``paddle.jit.TranslatedLayer`` 的输出变量。
``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量, ``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 ``paddle.nn.Layer`` 的forward方法的所有返回变量,
将会依据输入的 ``output_spec`` 列表对存储的模型进行裁剪。 将会依据输入的 ``output_spec`` 列表对存储的模型进行裁剪。
.. note:: .. note::
...@@ -132,7 +132,7 @@ SaveLoadConfig ...@@ -132,7 +132,7 @@ SaveLoadConfig
.. py:attribute:: model_filename .. py:attribute:: model_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。 存储转写 ``paddle.nn.Layer`` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。
**示例代码** **示例代码**
.. code-block:: python .. code-block:: python
...@@ -183,7 +183,7 @@ SaveLoadConfig ...@@ -183,7 +183,7 @@ SaveLoadConfig
.. py:attribute:: params_filename .. py:attribute:: params_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。 存储转写 ``paddle.nn.Layer`` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。
**示例代码** **示例代码**
.. code-block:: python .. code-block:: python
...@@ -236,10 +236,13 @@ SaveLoadConfig ...@@ -236,10 +236,13 @@ SaveLoadConfig
.. py:attribute:: separate_params .. py:attribute:: separate_params
配置是否将 :ref:`cn_api_fluid_dygraph_Layer` 的参数存储为分散的文件。 配置是否将 :ref:`cn_api_fluid_dygraph_Layer` 的参数存储为分散的文件。
(这是为了兼容接口 :ref:`cn_api_fluid_io_save_inference_model` 的行为) (这是为了兼容接口 ``paddle.static.save_inference_model`` 的行为)
如果设置为 ``True`` ,每个参数将会被存储为一个文件,文件名为参数名,同时``SaveLoadConfig.params_filename`` 指定的文件名将不会生效。默认为 ``False``。 如果设置为 ``True`` ,每个参数将会被存储为一个文件,文件名为参数名,同时``SaveLoadConfig.params_filename`` 指定的文件名将不会生效。默认为 ``False``。
.. note::
仅用于 ``paddle.load`` 方法.
**示例代码** **示例代码**
.. code-block:: python .. code-block:: python
...@@ -273,7 +276,7 @@ SaveLoadConfig ...@@ -273,7 +276,7 @@ SaveLoadConfig
adam.clear_grad() adam.clear_grad()
model_path = "simplenet.example.model.separate_params" model_path = "simplenet.example.model.separate_params"
config = paddle.jit.SaveLoadConfig() config = paddle.SaveLoadConfig()
config.separate_params = True config.separate_params = True
# saving with configs.separate_params # saving with configs.separate_params
...@@ -307,11 +310,11 @@ SaveLoadConfig ...@@ -307,11 +310,11 @@ SaveLoadConfig
linear = paddle.nn.Linear(5, 1) linear = paddle.nn.Linear(5, 1)
state_dict = linear.state_dict() state_dict = linear.state_dict()
paddle.save(state_dict, "paddle_dy") paddle.save(state_dict, "paddle_dy.pdparams")
configs = paddle.SaveLoadConfig() config = paddle.SaveLoadConfig()
configs.keep_name_table = True config.keep_name_table = True
para_state_dict, _ = paddle.load("paddle_dy", configs) para_state_dict = paddle.load("paddle_dy.pdparams", config)
print(para_state_dict) print(para_state_dict)
# the name_table is 'StructuredToParameterName@@' # the name_table is 'StructuredToParameterName@@'
......
...@@ -410,12 +410,12 @@ buffer是一个非参数类型的变量,不会被优化器更新,但在评 ...@@ -410,12 +410,12 @@ buffer是一个非参数类型的变量,不会被优化器更新,但在评
paddle.disable_static() paddle.disable_static()
emb = paddle.nn.Embedding([10, 10]) emb = paddle.nn.Embedding(10, 10)
state_dict = emb.state_dict() state_dict = emb.state_dict()
paddle.save(state_dict, "paddle_dy") paddle.save(state_dict, "paddle_dy.pdparams")
para_state_dict, _ = paddle.load("paddle_dy") para_state_dict = paddle.load("paddle_dy.pdparams")
emb.set_state_dict(para_state_dict) emb.set_state_dict(para_state_dict)
.. _cn_api_fluid_dygraph_jit_load: .. _cn_api_fluid_load:
load load
----------------- -------------------------------
.. py:function:: paddle.fluid.dygraph.jit.load(model_path, configs=None) .. py:function:: paddle.fluid.load(program, model_path, executor=None, var_list=None)
:api_attr: 声明式编程模式(静态图)
将接口 :ref:`cn_api_fluid_dygraph_jit_save` 或者 :ref:`cn_api_fluid_io_save_inference_model` 存储的模型载入为 :ref:`cn_api_fluid_dygraph_TranslatedLayer` ,用于预测推理或者fine-tune训练。
.. note::
由于一些历史原因,如果载入的模型是通过 :ref:`cn_api_fluid_io_save_inference_model` 存储的, 该接口从Program中过滤出参数和优化器信息,然后从文件中获取相应的值。
在使用它进行fine-tune训练时会存在一些局限:
1. 命令式编程模式不支持 ``LoDTensor`` ,所有原先输入变量或者参数依赖于LoD信息的模型暂时无法使用; 如果Program和加载的文件之间参数的维度或数据类型不匹配,将引发异常。
2. 所有存储模型的feed变量都需要被传入 ``Translatedlayer`` 的forward方法;
3. 原模型变量的 ``stop_gradient`` 信息已丢失且无法准确恢复; 该函数还可以加载用[save_params,save_persistables,save_vars]接口保存的模型文件。
4. 原模型参数的 ``trainable`` 信息已丢失且无法准确恢复。 当[save_params,save_persistables,save_vars]保存的模型格式为单个大文件时,var_list不能为None。
参数: 参数:
- **model_path** (str) - 存储模型的目录。 - **program** ( :ref:`cn_api_fluid_Program` ) – 要加载的Program。
- **configs** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象。默认为 ``None``。 - **model_path** (str) – 保存Program的目录名称+文件前缀。格式为 ``目录名称/文件前缀`` 。
- **executor** (Executor, 可选) - 当startup program没有运行时,用于初始化参数的Executor。默认值:None。
返回:TranslatedLayer - 一个能够执行存储模型的 ``Layer`` 对象。 - **var_list** (list, 可选) - 指定加载的变量列表,该参数只在加载旧接口[save_params,save_persistables,save_vars]保存的模型文件时使用。当加载的是多个小文件时,变量列表可以是所有加载文件中变量的子集;当加载的单个大文件时,变量列表必须和加载文件中的变量保持一致。
**示例代码** 返回: 无
1. 载入由接口 :ref:`cn_api_fluid_dygraph_jit_save` 存储的模型进行预测推理及fine-tune训练。 **代码示例**
.. code-block:: python .. code-block:: python
import numpy as np # example1
import paddle.fluid as fluid import paddle
from paddle.fluid.dygraph import Linear import paddle.fluid as fluid
from paddle.fluid.dygraph import declarative
BATCH_SIZE = 32 paddle.enable_static()
BATCH_NUM = 20
def random_batch_reader(): x = fluid.data( name="x", shape=[10, 10], dtype='float32')
def _get_random_images_and_labels(image_shape, label_shape): y = fluid.layers.fc(x, 10)
image = np.random.random(size=image_shape).astype('float32') z = fluid.layers.fc(y, 10)
label = np.random.random(size=label_shape).astype('int64') place = fluid.CPUPlace()
return image, label exe = fluid.Executor(place)
def __reader__(): exe.run(fluid.default_startup_program())
for _ in range(BATCH_NUM): fluid.save(fluid.default_main_program(), "./test_path")
batch_image, batch_label = _get_random_images_and_labels( fluid.load(fluid.default_main_program(), "./test_path")
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label # example2
return __reader__ # 注意example1和example2应该分开执行,避免干扰。
class LinearNet(fluid.dygraph.Layer): import paddle.fluid as fluid
def __init__(self, in_size, out_size):
super(LinearNet, self).__init__() x = fluid.data( name="x", shape=[10, 10], dtype='float32')
self._linear = Linear(in_size, out_size) y = fluid.layers.fc(x, 10)
@declarative z = fluid.layers.fc(y, 10)
def forward(self, x): place = fluid.CPUPlace()
return self._linear(x) exe = fluid.Executor(place)
# 开启命令式编程模式 exe.run(fluid.default_startup_program())
fluid.enable_dygraph() fluid.save(fluid.default_main_program(), "./test_path")
# 1. 训练存储模型. fluid.load(fluid.default_main_program(), "./test_path", exe)
# 创建网络
net = LinearNet(784, 1)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# 训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
net.clear_gradients()
model_path = "linear.example.model"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[img])
# 2. 载入模型 & 预测
# 载入模型
infer_net = fluid.dygraph.jit.load(model_path)
# 预测
x = fluid.dygraph.to_variable(np.random.random((1, 784)).astype('float32'))
pred = infer_net(x)
# 3. 载入模型 & fine-tune训练
# 载入模型
train_net = fluid.dygraph.jit.load(model_path)
train_net.train()
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=train_net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# fine-tune训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = train_net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
train_net.clear_gradients()
2. 载入由接口 :ref:`cn_api_fluid_io_save_inference_model` 存储的模型进行预测推理及fine-tune训练。
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
BATCH_SIZE = 32
BATCH_NUM = 20
def random_batch_reader():
def _get_random_images_and_labels(image_shape, label_shape):
image = np.random.random(size=image_shape).astype('float32')
label = np.random.random(size=label_shape).astype('int64')
return image, label
def __reader__():
for _ in range(BATCH_NUM):
batch_image, batch_label = _get_random_images_and_labels(
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label
return __reader__
img = fluid.data(name='img', shape=[None, 784], dtype='float32')
label = fluid.data(name='label', shape=[None, 1], dtype='int64')
pred = fluid.layers.fc(input=img, size=10, act='softmax')
loss = fluid.layers.cross_entropy(input=pred, label=label)
avg_loss = fluid.layers.mean(loss)
optimizer = fluid.optimizer.SGD(learning_rate=0.001)
optimizer.minimize(avg_loss)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
loader = fluid.io.DataLoader.from_generator(
feed_list=[img, label], capacity=5, iterable=True)
loader.set_batch_generator(random_batch_reader(), places=place)
# 1. 训练 & 存储预测模型
for data in loader():
exe.run(
fluid.default_main_program(),
feed=data,
fetch_list=[avg_loss])
model_path = "fc.example.model"
fluid.io.save_inference_model(
model_path, ["img"], [pred], exe)
# 开启命令式编程模式
fluid.enable_dygraph()
# 2. 载入模型 & 预测
fc = fluid.dygraph.jit.load(model_path)
x = fluid.dygraph.to_variable(np.random.random((1, 784)).astype('float32'))
pred = fc(x)
# 3. 载入模型 & fine-tune训练
fc = fluid.dygraph.jit.load(model_path)
fc.train()
sgd = fluid.optimizer.SGD(learning_rate=0.001,
parameter_list=fc.parameters())
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(
random_batch_reader(), places=place)
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = fc(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
sgd.minimize(avg_loss)
.. _cn_api_fluid_save:
save
-------------------------------
.. py:function:: paddle.fluid.save(program, model_path)
:api_attr: 声明式编程模式(静态图)
:alias_main: paddle.static.save
:alias: paddle.static.save
:old_api: paddle.fluid.save
该接口将传入的参数、优化器信息和网络描述保存到 ``model_path`` 。
参数包含所有的可训练 :ref:`cn_api_fluid_Variable` ,将保存到后缀为 ``.pdparams`` 的文件中。
优化器信息包含优化器使用的所有变量。对于Adam优化器,包含beta1、beta2、momentum等。
所有信息将保存到后缀为 ``.pdopt`` 的文件中。(如果优化器没有需要保存的变量(如sgd),则不会生成)。
网络描述是程序的描述。它只用于部署。描述将保存到后缀为 ``.pdmodel`` 的文件中。
参数:
- **program** ( :ref:`cn_api_fluid_Program` ) – 要保存的Program。
- **model_path** (str) – 保存program的文件前缀。格式为 ``目录名称/文件前缀``。如果文件前缀为空字符串,会引发异常。
返回: 无
**代码示例**
.. code-block:: python
import paddle
import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data(name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc(x, 10)
z = fluid.layers.fc(y, 10)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
fluid.save(fluid.default_main_program(), "./test_path")
.. _cn_api_fluid_dygraph_jit_save:
save
-----------------
.. py:function:: paddle.fluid.dygraph.jit.save(layer, model_path, input_spec=None, configs=None)
将输入的经过 ``@declarative`` 装饰的 :ref:`cn_api_fluid_dygraph_Layer` 存储为 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 格式的模型,
载入后可用于预测推理或者fine-tune训练。
该接口将会将输入 :ref:`cn_api_fluid_dygraph_Layer` 转写后的模型结构 ``Program`` 和所有必要的持久参数变量存储至输入路径 ``model_path`` 中。
默认存储的 ``Program`` 文件名为 ``__model__``, 默认存储持久参数变量的文件名为 ``__variables__``,
同时会将变量的一些描述信息存储至文件 ``__variables.info__``,这些额外的信息将在fine-tune训练中使用。
存储的模型能够被以下API载入使用:
- :ref:`cn_api_fluid_dygraph_jit_load`
- :ref:`cn_api_fluid_io_load_inference_model` (需要配置参数 ``params_filename='__variables__'`` )
- 其他预测库API
参数:
- **layer** (Layer) - 需要存储的 :ref:`cn_api_fluid_dygraph_Layer` 对象。输入的 ``Layer`` 需要经过 ``@declarative`` 装饰。
- **model_path** (str) - 存储模型的目录。
- **input_spec** (list[Variable], 可选) - 描述存储模型的输入。此参数是传入当前存储的 ``TranslatedLayer`` forward方法的一个示例输入。如果为 ``None`` ,所有原 ``Layer`` forward方法的输入变量将都会被配置为存储模型的输入变量。默认为 ``None``。
- **configs** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象。默认为 ``None``。
返回:无
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
BATCH_SIZE = 32
BATCH_NUM = 20
def random_batch_reader():
def _get_random_images_and_labels(image_shape, label_shape):
image = np.random.random(size=image_shape).astype('float32')
label = np.random.random(size=label_shape).astype('int64')
return image, label
def __reader__():
for _ in range(BATCH_NUM):
batch_image, batch_label = _get_random_images_and_labels(
[BATCH_SIZE, 784], [BATCH_SIZE, 1])
yield batch_image, batch_label
return __reader__
class LinearNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(LinearNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
return self._linear(x)
# 开启命令式编程模式
fluid.enable_dygraph()
# 创建网络
net = LinearNet(784, 1)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
# 创建DataLoader
train_loader = fluid.io.DataLoader.from_generator(capacity=5)
train_loader.set_batch_generator(random_batch_reader())
# 训练
for data in train_loader():
img, label = data
label.stop_gradient = True
cost = net(img)
loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss)
avg_loss.backward()
adam.minimize(avg_loss)
net.clear_gradients()
# 存储模型
model_path = "linear.example.model"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[img])
.. _cn_api_fluid_dygraph_jit_SaveLoadConfig:
SaveLoadConfig
-------------------------------
.. py:class:: paddle.fluid.dygraph.jit.SaveLoadConfig()
用于配置接口 :ref:`cn_api_fluid_dygraph_jit_save` 和 :ref:`cn_api_fluid_dygraph_jit_load` 存储载入 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 时的附加选项。
**示例代码:**
1. 在存储模型时使用 ``SaveLoadConfig``
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
# 在存储模型时使用SaveLoadConfig
model_path = "simplenet.example.model"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
2. 在载入模型时使用 ``SaveLoadConfig``
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
# 开启命令式编程模式
fluid.enable_dygraph()
# 在载入模型时使用SaveLoadconfig
model_path = "simplenet.example.model"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
# 预测
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
属性
::::::::::::
.. py:attribute:: output_spec
选择保存模型( :ref:`cn_api_fluid_dygraph_TranslatedLayer` )的输出变量,通过指定的这些变量能够使模型仅计算特定的结果。
默认情况下,原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量都将配置为存储后模型 :ref:`cn_api_fluid_dygraph_TranslatedLayer` 的输出变量。
``output_spec`` 属性类型需要是 ``list[Variable]``。如果输入的 ``output_spec`` 列表不是原始 :ref:`cn_api_fluid_dygraph_Layer` 的forward方法的所有返回变量,
将会依据输入的 ``output_spec`` 列表对存储的模型进行裁剪。
.. note::
``output_spec`` 属性仅在存储模型时使用。
**示例代码:**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
loss = fluid.layers.mean(z)
return z, loss
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out, loss = net(x)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
# 使用SaveLoadconfig.output_spec
model_path = "simplenet.example.model.output_spec"
configs = fluid.dygraph.jit.SaveLoadConfig()
# 仅在存储模型中保留预测结果,丢弃loss
configs.output_spec = [out]
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
# 仅有预测结果输出
pred = infer_net(x)
.. py:attribute:: model_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 模型结构 ``Program`` 的文件名称。默认文件名为 ``__model__``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.model_filename"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.model_filename = "__simplenet__"
# 配置configs.model_filename存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# __simplenet__ __variables__ __variables.info__
# 配置configs.model_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. py:attribute:: params_filename
存储转写 :ref:`cn_api_fluid_dygraph_Layer` 所有持久参数(包括 ``Parameters`` 和持久的 ``Buffers``)的文件名称。默认文件名称为 ``__variable__``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.params_filename"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.params_filename = "__params__"
# 配置configs.params_filename存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# __model__ __params__ __variables.info__
# 配置configs.params_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. py:attribute:: separate_params
配置是否将 :ref:`cn_api_fluid_dygraph_Layer` 的参数存储为分散的文件。
(这是为了兼容接口 :ref:`cn_api_fluid_io_save_inference_model` 的行为)
如果设置为 ``True`` ,每个参数将会被存储为一个文件,文件名为参数名,同时``SaveLoadConfig.params_filename`` 指定的文件名将不会生效。默认为 ``False``。
**示例代码**
.. code-block:: python
import numpy as np
import paddle.fluid as fluid
from paddle.fluid.dygraph import Linear
from paddle.fluid.dygraph import declarative
class SimpleNet(fluid.dygraph.Layer):
def __init__(self, in_size, out_size):
super(SimpleNet, self).__init__()
self._linear = Linear(in_size, out_size)
@declarative
def forward(self, x):
y = self._linear(x)
z = self._linear(y)
return z
# 开启命令式编程模式
fluid.enable_dygraph()
# 训练模型
net = SimpleNet(8, 8)
adam = fluid.optimizer.AdamOptimizer(learning_rate=0.1, parameter_list=net.parameters())
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
for i in range(10):
out = net(x)
loss = fluid.layers.mean(out)
loss.backward()
adam.minimize(loss)
net.clear_gradients()
model_path = "simplenet.example.model.separate_params"
configs = fluid.dygraph.jit.SaveLoadConfig()
configs.separate_params = True
# 配置configs.separate_params存储模型
fluid.dygraph.jit.save(
layer=net,
model_path=model_path,
input_spec=[x],
configs=configs)
# [结果] 存储模型目录文件包括:
# linear_0.b_0 linear_0.w_0 __model__ __variables.info__
# 配置configs.params_filename载入模型
infer_net = fluid.dygraph.jit.load(model_path, configs=configs)
x = fluid.dygraph.to_variable(np.random.random((4, 8)).astype('float32'))
pred = infer_net(x)
.. _cn_api_paddle_framework_io_load:
load
-----
.. py:function:: paddle.load(path, config=None)
从指定路径载入可以在paddle中使用的对象实例。
.. note::
目前仅支持载入 Layer 或者 Optimizer 的 ``state_dict`` 。
.. note::
``paddle.load`` 支持从paddle1.x版本中静态图save相关API的存储结果中载入 ``state_dict`` 。 但是从``paddle.static.save_inference_model/paddle.fluid.io.save_params/paddle.fluid.io.save_persistables`` 等API的存储结果中载入 ``state_dict`` 时,动态图模式下参数的结构性变量名将无法被恢复。并且在将载入的 ``state_dict`` 配置到当前Layer中时,需要配置 ``Layer.set_state_dict`` 的参数 ``use_structured_name=False`` 。
参数:
- **path** (str) – 载入目标对象实例的路径。通常该路径是目标文件的路径,在兼容载入 ``paddle.jit.save/paddle.static.save_inference_model`` 的存储结果时,该路径是一个目录。
- **config** (SaveLoadConfig, 可选) - 用于指定额外配置选项的 :ref:`cn_api_fluid_dygraph_jit_SaveLoadConfig` 对象,这些选项主要是用于兼容 ``paddle.jit.save/paddle.static.save_inference_model`` 存储结果的格式。默认为 ``None``。
返回: 一个可以在paddle中使用的对象实例
返回类型: Object
**代码示例**
.. code-block:: python
import paddle
paddle.disable_static()
emb = paddle.nn.Embedding(10, 10)
layer_state_dict = emb.state_dict()
paddle.save(layer_state_dict, "emb.pdparams")
scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True)
adam = paddle.optimizer.Adam(
learning_rate=scheduler,
parameters=emb.parameters())
opt_state_dict = adam.state_dict()
paddle.save(opt_state_dict, "adam.pdopt")
load_layer_state_dict = paddle.load("emb.pdparams")
load_opt_state_dict = paddle.load("adam.pdopt")
.. _cn_api_paddle_framework_io_save:
save
-----
.. py:function:: paddle.save(obj, model_path)
将对象实例obj保存到指定的路径中。
.. note::
目前仅支持存储 Layer 或者 Optimizer 的 ``state_dict`` 。
参数:
- **obj** (Object) – 要保存的对象实例。
- **path** (str) – 保存对象实例的路径。如果存储到当前路径,输入的path字符串将会作为保存的文件名。
返回: 无
**代码示例**
.. code-block:: python
import paddle
paddle.disable_static()
emb = paddle.nn.Embedding(10, 10)
layer_state_dict = emb.state_dict()
paddle.save(layer_state_dict, "emb.pdparams")
scheduler = paddle.optimizer.lr_scheduler.NoamLR(
d_model=0.01, warmup_steps=100, verbose=True)
adam = paddle.optimizer.Adam(
learning_rate=scheduler,
parameters=emb.parameters())
opt_state_dict = adam.state_dict()
paddle.save(opt_state_dict, "adam.pdopt")
.. _cn_api_fluid_io_buffered: .. _cn_api_io_buffered:
buffered buffered
------------------------------- -------------------------------
.. py:function:: paddle.fluid.io.buffered(reader, size) .. py:function:: paddle.io.buffered(reader, size)
...@@ -14,4 +14,21 @@ buffered ...@@ -14,4 +14,21 @@ buffered
- **reader** (callable) – 读取数据的reader - **reader** (callable) – 读取数据的reader
- **size** (int) – 最大buffer的大小 - **size** (int) – 最大buffer的大小
返回:缓存的reader(读取器) 返回:缓存的reader(读取器)
\ No newline at end of file
**代码示例**
.. code-block:: python
import paddle
def reader():
for i in range(3):
yield i
# Create a buffered reader, and the buffer size is 2.
buffered_reader = paddle.io.buffered(reader, 2)
# Output: 0 1 2
for i in buffered_reader():
print(i)
.. _cn_api_fluid_io_cache: .. _cn_api_io_cache:
cache cache
------------------------------- -------------------------------
.. py:function:: paddle.fluid.io.cache(reader) .. py:function:: paddle.io.cache(reader)
...@@ -15,4 +15,21 @@ cache ...@@ -15,4 +15,21 @@ cache
返回:每次都会从内存中yields数据的一个装饰reader。 返回:每次都会从内存中yields数据的一个装饰reader。
返回类型:生成器 返回类型:数据保存在内存的reader(读取器)
\ No newline at end of file
**代码示例**
.. code-block:: python
import paddle
def reader():
for i in range(3):
yield i
# All data is cached into memory
cached_reader = paddle.io.cache(reader)
# Output: 0 1 2
for i in cached_reader():
print(i)
.. _cn_api_paddle_metric_accuracy:
accuracy
-------------------------------
.. py:function:: paddle.metric.accuracy(input, label, k=1, correct=None, total=None)
accuracy layer。 参考 https://en.wikipedia.org/wiki/Precision_and_recall
使用输入和标签计算准确率。 如果正确的标签在topk个预测值里,则计算结果加1。注意:输出正确率的类型由input类型决定,input和lable的类型可以不一样。
参数
:::::::::
- **input** (Tensor|LoDTensor)-数据类型为float32,float64。输入为网络的预测值。shape为 ``[sample_number, class_dim]`` 。
- **label** (Tensor|LoDTensor)-数据类型为int64,int32。输入为数据集的标签。shape为 ``[sample_number, 1]`` 。
- **k** (int64|int32) - 取每个类别中k个预测值用于计算。
- **correct** (int64|int32)-正确预测值的个数。
- **total** (int64|int32)-总共的预测值。
返回
:::::::::
``Tensor``,计算出来的正确率,数据类型为float32的Tensor。
代码示例
:::::::::
.. code-block:: python
import paddle.fluid as fluid
import numpy as np
data = fluid.layers.data(name="input", shape=[-1, 32, 32], dtype="float32")
label = fluid.layers.data(name="label", shape=[-1,1], dtype="int")
fc_out = fluid.layers.fc(input=data, size=10)
predict = fluid.layers.softmax(input=fc_out)
result = fluid.layers.accuracy(input=predict, label=label, k=5)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
x = np.random.rand(3, 32, 32).astype("float32")
y = np.array([[1],[0],[1]])
output= exe.run(feed={"input": x,"label": y},
fetch_list=[result[0]])
print(output)
"""
Output:
[array([0.6666667], dtype=float32)]
"""
.. _cn_api_paddle_metric_auc:
auc
-------------------------------
.. py:function:: paddle.metric.auc(input, label, curve='ROC', num_thresholds=200, topk=1, slide_steps=1)
**Area Under the Curve(AUC) Layer**
该层根据前向输出和标签计算AUC,在二分类(binary classification)估计中广泛使用。
注:如果输入标注包含一种值,只有0或1两种情况,数据类型则强制转换成布尔值。相关定义可以在这里: https://en.wikipedia.org/wiki/Receiver_operating_characteristic#Area_under_the_curve 找到
有两种可能的曲线:
1. ROC:受试者工作特征曲线
2. PR:准确率召回率曲线
参数:
:::::::::
- **input** (Tensor|LoDTensor) - 数据类型为float32,float64。浮点二维变量,值的范围为[0,1]。每一行降序排列。该输入为网络预测值的输入。
- **label** (Tensor|LoDTensor) - 数据类型为int32,int64。二维整型变量,为训练数据的标签。
- **curve** (str) - 曲线类型,可以为 ``ROC`` 或 ``PR``,默认 ``ROC``。
- **num_thresholds** (int) - 将roc曲线离散化时使用的临界值数。默认200。
- **topk** (int) - 取topk的输出值用于计算。
- **slide_steps** (int) - 当计算batch auc时,不仅用当前步也用于先前步。slide_steps=1,表示用当前步;slide_steps = 3表示用当前步和前两步;slide_steps = 0,则用所有步。
返回:
:::::::::
``Tensor``, 代表当前AUC的一个元组, 数据类型为float32或float64的Tensor。
返回的元组为auc_out, batch_auc_out, [batch_stat_pos, batch_stat_neg, stat_pos, stat_neg]。
auc_out为准确率的结果。
batch_auc_out为batch准确率的结果。
batch_stat_pos为batch计算时label=1的统计值
batch_stat_neg为batch计算时label=0的统计值
stat_pos计算时label=1的统计值
stat_neg为计算时label=0的统计值
代码示例:
:::::::::
.. code-block:: python
import paddle.fluid as fluid
import numpy as np
data = fluid.layers.data(name="input", shape=[-1, 32,32], dtype="float32")
label = fluid.layers.data(name="label", shape=[1], dtype="int")
fc_out = fluid.layers.fc(input=data, size=2)
predict = fluid.layers.softmax(input=fc_out)
result=fluid.layers.auc(input=predict, label=label)
place = fluid.CPUPlace()
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
x = np.random.rand(3,32,32).astype("float32")
y = np.array([1,0,1])
output= exe.run(feed={"input": x,"label": y},
fetch_list=[result[0]])
print(output)
"""
output:
[array([0.5])]
"""
.. _cn_api_paddle_nn_UpSample:
UpSample
-------------------------------
.. py:class:: paddle.nn.UpSample(out_shape=None, scale=None, resample='BILINEAR', actual_shape=None, align_corners=True, align_mode=1, data_format='NCHW')
**注意:** 参数 ``actual_shape`` 将被弃用,请使用 ``out_shape`` 替代。
该OP用于调整一个batch中图片的大小。
输入为3-D Tensor时形状为(num_batches, channels, in_w),输入为4-D Tensor时形状为(num_batches, channels, in_h, in_w)或者(num_batches, in_h, in_w, channels),输入为5-D Tensor时形状为(num_batches, channels, in_d, in_h, in_w)或者(num_batches, in_d, in_h, in_w, channels),并且调整大小只适用于深度,高度和宽度对应的维度。
支持的插值方法:
NEAREST:最近邻插值
LINEAR:线性插值
BILINEAR:双线性插值
TRALINEAR:三线性插值
BICUBIC:双三次插值
最近邻插值是在输入张量的高度和宽度上进行最近邻插值。
线性插值是用一条线连接两个已知量来确定两个已知量之间的一个未知量的值的方法。
双线性插值是线性插值的扩展,用于在直线2D网格上插值两个变量(例如,该操作中的H方向和W方向)的函数。 关键思想是首先在一个方向上执行线性插值,然后在另一个方向上再次执行线性插值。
三线插值是线性插值的一种扩展,是3参数的插值方程(比如op里的D,H,W方向),在三个方向上进行线性插值。
双三次插值是在二维网格上对数据点进行插值的三次插值的扩展,它能创造出比双线性和最近临插值更为光滑的图像边缘。
Align_corners和align_mode是可选参数,插值的计算方法可以由它们选择。
示例:
::
For scale:
if align_corners = True && out_size > 1 :
scale_factor = (in_size-1.0)/(out_size-1.0)
else:
scale_factor = float(in_size/out_size)
Nearest neighbor interpolation:
if:
align_corners = False
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = \left \lfloor {H_{in} * scale_{}factor}} \right \rfloor
W_out = \left \lfloor {W_{in} * scale_{}factor}} \right \rfloor
else:
align_corners = True
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = round(H_{in} * scale_{factor})
W_out = round(W_{in} * scale_{factor})
Bilinear interpolation:
if:
align_corners = False , align_mode = 0
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
Bicubic interpolation:
if:
align_corners = False
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,H_in,W_in)
output: (N,C,H_out,W_out) where:
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
Trilinear interpolation:
if:
align_corners = False , align_mode = 0
input : (N,C,D_in,H_in,W_in)
output: (N,C,D_out,H_out,W_out) where:
D_out = (D_{in}+0.5) * scale_{factor} - 0.5
H_out = (H_{in}+0.5) * scale_{factor} - 0.5
W_out = (W_{in}+0.5) * scale_{factor} - 0.5
else:
input : (N,C,D_in,H_in,W_in)
output: (N,C,D_out,H_out,W_out) where:
D_out = D_{in} * scale_{factor}
H_out = H_{in} * scale_{factor}
W_out = W_{in} * scale_{factor}
有关最近邻插值的详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Nearest-neighbor_interpolation
有关线性插值的详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Linear_interpolation
有关双线性插值的详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Bilinear_interpolation
有关三线插值的详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Trilinear_interpolation
有关双三次插值的详细信息,请参阅维基百科:
https://en.wikipedia.org/wiki/Bicubic_interpolation
参数:
- **input** (Variable) - 3-D,4-D或5-D Tensor,数据类型为float32、float64或uint8,其数据格式由参数 ``data_format`` 指定。
- **out_shape** (list|tuple|Variable|None) - 输出Tensor,输入为3D张量时,形状为为(out_w)的1-D Tensor。输入为4D张量时,形状为为(out_h, out_w)的2-D Tensor。输入为5-D Tensor时,形状为(out_d, out_h, out_w)的3-D Tensor。如果 :code:`out_shape` 是列表,每一个元素可以是整数或者形状为[1]的变量。如果 :code:`out_shape` 是变量,则其维度大小为1。默认值为None。
- **scale** (float|Variable|None)-输入的高度或宽度的乘数因子 。 out_shape和scale至少要设置一个。out_shape的优先级高于scale。默认值为None。
- **name** (str|None) - 该参数供开发人员打印调试信息时使用,具体用法请参见 :ref:`api_guide_Name` 。默认值为None。
- **resample** (str) - 插值方法。支持“线性”,“双线性”,“三线性”,“临近插值”,"双三次"。默认值为双线性插值。
- **align_corners** (bool)- 一个可选的bool型参数,如果为True,则将输入和输出张量的4个角落像素的中心对齐,并保留角点像素的值。 默认值为True
- **align_mode** (int)- 双线性插值的可选项。 可以是 '0' 代表src_idx = scale *(dst_indx + 0.5)-0.5;如果为'1' ,代表src_idx = scale * dst_index。
- **data_format** (str,可选)- 指定输入的数据格式,输出的数据格式将与输入保持一致。对于3-D Tensor,支持 NCHW(num_batches, channels, width),对于4-D Tensor,支持 NCHW(num_batches, channels, height, width) 或者 NHWC(num_batches, height, width, channels),对于5-D Tensor,支持 NCDHW(num_batches, channels, depth, height, width)或者 NDHWC(num_batches, depth, height, width, channels),默认值:'NCHW'。
返回:3-D Tensor,形状为 (num_batches, channels, out_w) ;4-D Tensor,形状为 (num_batches, channels, out_h, out_w) 或 (num_batches, out_h, out_w, channels);或者5-D Tensor,形状为 (num_batches, channels, out_d, out_h, out_w) 或 (num_batches, out_d, out_h, out_w, channels)。
返回类型: 变量(variable)
抛出异常:
- :code:`TypeError` - out_shape应该是一个列表、元组或变量。
- :code:`TypeError` - actual_shape应该是变量或None。
- :code:`ValueError` - image_resize的"resample"只能是"LINEAR"或"BILINEAR"或"TRILINEAR"或"NEAREST"或"BICUBIC"。
- :code:`ValueError` - out_shape 和 scale 不可同时为 None。
- :code:`ValueError` - out_shape 的长度必须为2如果输入是4D张量。
- :code:`ValueError` - out_shape 的长度必须为3如果输入是5D张量。
- :code:`ValueError` - scale应大于0。
- :code:`TypeError` - align_corners 应为bool型。
- :code:`ValueError` - align_mode 只能取 ‘0’ 或 ‘1’。
- :code:`ValueError` - data_format 只能取 ‘NCW’、 ‘NCHW’、‘NHWC’、‘NCDHW’ 或者 ‘NDHWC’。
**代码示例**
.. code-block:: python
import paddle
import numpy as np
upsample_op = paddle.nn.UpSample(out_shape=[12,12])
input_data = np.random.rand(2,3,6,10).astype("float32")
#imperative mode
import paddle.fluid.dygraph as dg
with dg.guard(place) as g:
input = dg.to_variable(input_data)
output = upsample_op(input=input)
print(output.shape)
# [2L, 3L, 12L, 12L]
\ No newline at end of file
.. THIS FILE IS GENERATED BY `gen_doc.{py|sh}`
!DO NOT EDIT THIS FILE MANUALLY!
.. _api_fluid_io_ComposeNotAligned:
ComposeNotAligned
-----------------
.. autoclass:: paddle.fluid.io.ComposeNotAligned
:members:
:inherited-members:
:noindex:
表示一种错误状态,说明调用compose API时, reader的输出数据没有对齐。
.. _cn_api_fluid_io_buffered:
buffered
-------------------------------
.. py:function:: paddle.fluid.io.buffered(reader, size)
创建一个缓存数据读取器,它读取数据并且存储进缓存区,从缓存区读取数据将会加速,只要缓存不是空的。
参数:
- **reader** (callable) – 读取数据的reader
- **size** (int) – 最大buffer的大小
返回:缓存的reader(读取器)
\ No newline at end of file
.. _cn_api_fluid_io_cache:
cache
-------------------------------
.. py:function:: paddle.fluid.io.cache(reader)
缓存reader数据到内存中,小心此方法可能会花长时间来处理数据,并且会占用大量内存。 ``reader()`` 只能被调用一次。
参数:
- **reader** (callable) – 读取数据的reader,每次都会yields数据。
返回:每次都会从内存中yields数据的一个装饰reader。
返回类型:生成器
\ No newline at end of file
.. _cn_api_fluid_io_chain:
chain
-------------------------------
.. py:function:: paddle.fluid.io.chain(*readers)
该接口将多个数据读取器组成一个数据读取器,它依次返回多个数据读取器的输出数据,同时不改变输出数据原先的格式。
举例来说,如果有3个输入读取器且输出分别为[0,0,0]、[10,10,10]和[20,20,20],那么调用该接口产生的新数据读取器的输出为[0,0,0], [10,10,10], [20,20,20]。
参数:
- **readers(list)** – 输入的数据读取器。
返回: 新的数据读取器。
返回类型:callable
**代码示例**
.. code-block:: python
import paddle.fluid as fluid
def reader_creator_3(start):
def reader():
for i in range(start, start + 3):
yield [i, i, i]
return reader
c = fluid.io.chain(reader_creator_3(0), reader_creator_3(10), reader_creator_3(20))
for e in c():
print(e)
# 输出结果如下:
# [0, 0, 0]
# [1, 1, 1]
# [2, 2, 2]
# [10, 10, 10]
# [11, 11, 11]
# [12, 12, 12]
# [20, 20, 20]
# [21, 21, 21]
# [22, 22, 22]
.. _cn_api_fluid_io_compose:
compose
-------------------------------
.. py:function:: paddle.fluid.io.compose(*readers, **kwargs)
该接口将多个数据读取器组合为一个数据读取器,返回读取器的输出包含所有输入读取器的输出。
例如:如果输入为三个reader,三个reader的输出分别为:(1,2)、3、(4,5),则组合reader的输出为:(1,2,3,4,5)。
参数:
- **readers** - 将被组合的多个数据读取器(Reader),数据读取器的定义参见 :ref:`cn_api_paddle_data_reader_reader` 。
- **check_alignment** (bool) - 可选,指明是否对输入reader进行对齐检查,默认值为True。如果为True,将检查输入reader是否正确对齐。如果为False,将不检查对齐并自动丢弃无法对齐的末尾数据。
返回:数据读取器(Reader)。
**代码示例**:
.. code-block:: python
import paddle.fluid as fluid
def reader_creator_10(dur):
def reader():
for i in range(10):
yield i
return reader
reader = fluid.io.compose(reader_creator_10(0), reader_creator_10(0))
注意: 运行过程可能会抛出异常 ``ComposeNotAligned`` ,原因是输入的readers数据未对齐。 当check_alignment设置为False时,不会检查并触发该异常。
.. _cn_api_fluid_io_firstn:
firstn
-------------------------------
.. py:function:: paddle.fluid.io.firstn(reader, n)
该接口创建一个数据读取器,它可以返回的最大样本数为n。
参数:
- **reader** (callable) – 输入的数据读取器。
- **n** (int) – 可以返回的最大样本数。
返回: 新的的数据读取器。
返回类型: callable
.. code-block:: python
import paddle.fluid as fluid
def reader():
for i in range(100):
yield i
firstn_reader = fluid.io.firstn(reader, 5)
for e in firstn_reader():
print(e)
# 输出结果为:0 1 2 3 4
.. _cn_api_fluid_io_map_readers:
map_readers
-------------------------------
.. py:function:: paddle.fluid.io.map_readers(func, *readers)
该接口将创建一个数据读取器(Reader),其中 `func` 函数的输出将直接作为新数据读取器的输出, `readers` 的输出将作为函数 `func` 的输入参数。
例如:如果输入的 `readers` 为两个输出分别为:2、3 的 `reader` ,输入的 `func` 为乘法函数 `mul(x, y)` ,则得到的新建 `reader` 的输出为:6。
参数:
- **func** - 读取数据并返回数据项的函数, `func` 的输出将直接作为新创建的数据读取器的输出。
- **readers** - 输入的一个或多个数据读取器(Reader),这些数据读取器的输出数据将作为函数 `func` 的输入参数。数据读取器的定义参见 :ref:`cn_api_paddle_data_reader_reader` 。
返回: 新创建的数据读取器(Reader)
**代码示例**:
.. code-block:: python
import paddle.fluid as fluid
d = {"h": 0, "i": 1}
def func(x):
return d[x]
def reader():
yield "h"
yield "i"
map_reader_result = fluid.io.map_readers(func, reader)
.. _cn_api_fluid_io_multiprocess_reader:
multiprocess_reader
-------------------------------
.. py:function:: paddle.fluid.io.multiprocess_reader(readers, use_pipe=True, queue_size=1000)
使用python多进程从 ``readers`` 中读取数据,然后使用 ``multiprocessing.Pipe`` 或 ``multiprocessing.Queue`` 合并所有数据。 ``readers`` 列表中的每个reader会被创建一个独立的进程来调用,reader之间应该相互独立,互不影响,避免出现多进程读取的冲突问题.
multiprocess.queue需要/dev/shm的rw访问权限,某些平台不支持。
参数:
- **readers** (list(generator)|tuple(generator)) - python生成器list, 用来读取数据
- **use_pipe** (bool,可选) - use_pipe控制multiprocess_reader内部用 ``pipe`` 还是 ``queue`` 来实现进程间通信,默认为 ``True`` 使用 ``pipe`` 进行通信
- **queue_size** (int,可选) - 如果使用queue来进行进程间通信 (``use_pipe=False``), 则该参数用来设定队列大小
返回:使用多进程封装readers之后的reader
返回类型:python生成器
**代码示例**
.. code-block:: python
import paddle.fluid as fluid
from paddle.fluid.io import multiprocess_reader
import numpy as np
def fake_reader(start, end):
def __impl__():
for i in range(start, end):
yield [np.array([1, 2, 3]) * i],
return __impl__
with fluid.program_guard(fluid.Program(), fluid.Program()):
place = fluid.CPUPlace()
image = fluid.layers.data(
name='image', dtype='int64', shape=[3])
fluid.layers.Print(image)
reader = fluid.io.PyReader(
feed_list=[image], capacity=2)
image_p_1 = image + 1
decorated_reader = multiprocess_reader(
[fake_reader(1, 5), fake_reader(6, 10)], False)
reader.decorate_sample_generator(decorated_reader, batch_size=2, places=[place])
exe = fluid.Executor(place)
exe.run(fluid.default_startup_program())
for data in reader():
exe.run(feed=data, fetch_list=[image_p_1])
.. _cn_api_fluid_io_xmap_readers:
xmap_readers
-------------------------------
.. py:function:: paddle.fluid.io.xmap_readers(mapper, reader, process_num, buffer_size, order=False)
多线程下,使用自定义映射器 reader 返回样本到输出队列。
参数:
- **mapper** (callable): 映射 reader 数据的函数。
- **reader** (callable): 产生数据的 reader。
- **process_num** (int): 处理样本的线程数。
- **buffer_size** (int): 数据缓冲队列大小。
- **order** (bool): 是否保持原始 reader 数据顺序,默认为 False。
返回:一个用户定义的 reader `装饰器 <https://en.wikipedia.org/wiki/Python_syntax_and_semantics#Decorators>`_ 。
返回类型:callable,可调用对象。
**代码示例**:
.. code-block:: python
import paddle.fluid as fluid
import time
def reader_creator_10(dur):
def reader():
for i in range(10):
time.sleep(dur)
yield i
return reader
def mapper(x):
return (x + 1)
orders = (True, False)
thread_num = (1, 2, 4, 8, 16)
buffer_size = (1, 2, 4, 8, 16)
for order in orders:
for t_num in thread_num:
for size in buffer_size:
user_reader = fluid.io.xmap_readers(mapper,
reader_creator_10(0),
t_num, size, order)
for n in range(3):
result = list()
for i in user_reader():
result.append(i)
if not order:
result.sort()
for idx, e in enumerate(result):
assert e == mapper(idx)
\ No newline at end of file
...@@ -32,9 +32,12 @@ load_inference_model ...@@ -32,9 +32,12 @@ load_inference_model
.. code-block:: python .. code-block:: python
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
import numpy as np import numpy as np
paddle.enable_static()
# 构建模型 # 构建模型
main_prog = fluid.Program() main_prog = fluid.Program()
startup_prog = fluid.Program() startup_prog = fluid.Program()
......
...@@ -22,8 +22,11 @@ load_program_state ...@@ -22,8 +22,11 @@ load_program_state
.. code-block:: python .. code-block:: python
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data( name="x", shape=[10, 10], dtype='float32') x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc( x, 10) y = fluid.layers.fc( x, 10)
z = fluid.layers.fc( y, 10) z = fluid.layers.fc( y, 10)
......
...@@ -37,8 +37,11 @@ save_inference_model ...@@ -37,8 +37,11 @@ save_inference_model
.. code-block:: python .. code-block:: python
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
paddle.enable_static()
path = "./infer_model" path = "./infer_model"
# 用户定义网络,此处以softmax回归为例 # 用户定义网络,此处以softmax回归为例
......
...@@ -24,8 +24,11 @@ set_program_state ...@@ -24,8 +24,11 @@ set_program_state
.. code-block:: python .. code-block:: python
import paddle
import paddle.fluid as fluid import paddle.fluid as fluid
paddle.enable_static()
x = fluid.data( name="x", shape=[10, 10], dtype='float32') x = fluid.data( name="x", shape=[10, 10], dtype='float32')
y = fluid.layers.fc( x, 10) y = fluid.layers.fc( x, 10)
z = fluid.layers.fc( y, 10) z = fluid.layers.fc( y, 10)
......
.. _cn_api_tensor_empty_like:
empty_like
-------------------------------
.. py:function:: paddle.empty_like(shape, dtype=None, name=None)
该OP根据 ``x`` 的shape和数据类型 ``dtype`` 创建未初始化的Tensor。如果 ``dtype`` 为None,则Tensor的数据类型与 ``x`` 相同。
参数:
- **x** (Tensor) – 输入Tensor, 输出Tensor和x具有相同的形状,x的数据类型可以是bool,float16,float32,float64,int32,int64。
- **dtype** (np.dtype|str, 可选)- 输出变量的数据类型,可以是bool,float16,float32,float64,int32,int64。若参数为None,则输出变量的数据类型和输入变量相同,默认值为None。
- **name** (str,可选)- 具体用法请参见 :ref:`api_guide_Name`,一般无需设置,默认值为None。
返回:返回一个根据 ``x`` 和 ``dtype`` 创建并且尚未初始化的Tensor。
**代码示例**:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static() # Now we are in imperative mode
paddle.set_device("cpu") # and use cpu device
x = paddle.randn([2, 3], 'float32')
output = paddle.empty_like(x)
#[[1.8491974e+20 1.8037303e+28 1.7443726e+28] # uninitialized
# [4.9640171e+28 3.0186127e+32 5.6715899e-11]] # uninitialized
.. _cn_api_tensor_mv:
mv
-------------------------------
.. py:function:: paddle.mv(x, vec, name=None)
该op计算矩阵 ``x`` 和向量 ``vec`` 的乘积。
参数
:::::::::
- **x** (Tensor) : 输入变量,类型为 Tensor,形状为 :math:`[M, N]`,数据类型为float32, float64。
- **vec** (Tensor) : 输入变量,类型为 Tensor,形状为 :math:`[N]`,数据类型为float32, float64。
- **name** (str,可选)- 具体用法请参见 :ref:`api_guide_Name` ,一般无需设置,默认值为None。
返回
:::::::::
- Tensor,矩阵 ``x`` 和向量 ``vec`` 的乘积。
代码示例
::::::::::
.. code-block:: python
# x: [M, N], vec: [N]
# paddle.mv(x, vec) # out: [M]
import numpy as np
import paddle
paddle.disable_static()
x_data = np.array([[2, 1, 3], [3, 0, 1]]).astype("float64")
x = paddle.to_tensor(x_data)
vec_data = np.array([3, 5, 1])
vec = paddle.to_tensor(vec_data).astype("float64")
out = paddle.mv(x, vec)
paddle.enable_static()
.. _cn_api_text_datasets_MovieReviews:
MovieReviews
-------------------------------
.. py:class:: paddle.text.datasets.MovieReviews()
该类是对`NLTK movie reviews <http://www.nltk.org/nltk_data/>`_ 测试数据集的实现。
参数
:::::::::
- data_filestr- 保存压缩数据的路径,如果参数:attr:`download`设置为True
可设置为None。默认为None
- modestr- 'train' 'test' 模式。默认为'train'
- downloadbool- 如果:attr:`data_file`未设置,是否自动下载数据集。默认为True
返回值
:::::::::
``Dataset``NLTK movie reviews数据集实例。
代码示例
:::::::::
.. code-block:: python
import paddle
from paddle.text.datasets import MovieReviews
class SimpleNet(paddle.nn.Layer):
def __init__(self):
super(SimpleNet, self).__init__()
def forward(self, word, category):
return paddle.sum(word), category
paddle.disable_static()
movie_reviews = MovieReviews(mode='train')
for i in range(10):
word_list, category = movie_reviews[i]
word_list = paddle.to_tensor(word_list)
category = paddle.to_tensor(category)
model = SimpleNet()
word_list, category = model(word_list, category)
print(word_list.numpy().shape, category.numpy())
...@@ -552,7 +552,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0]) ...@@ -552,7 +552,7 @@ static_layer.save_inference_model(save_dirname, feed=[0], fetch=[0])
# 声明式编程中需要使用执行器执行之前已经定义好的网络 # 声明式编程中需要使用执行器执行之前已经定义好的网络
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
# 声明式编程中需要调用执行器的run方法执行计算过程 # 声明式编程中需要调用执行器的run方法执行计算过程
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
``` ```
......
...@@ -96,23 +96,19 @@ with fluid.dygraph.guard(fluid.CPUPlace()): ...@@ -96,23 +96,19 @@ with fluid.dygraph.guard(fluid.CPUPlace()):
## 模型训练&评估 ## 模型训练&评估
##### 问题:在CPU上进行模型训练,如何使用多线程 ##### 问题:使用CPU进行模型训练,如何利用多处理器进行加速
+ 答复:可以参考使用[ParallelExecutor API](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.3/api_cn/fluid_cn.html#parallelexecutor) + 答复:在1.8版本的动态图模式下,CPU训练加速可以从以下两点进行配置:
---------- 1. 使用多进程DataLoader加速数据读取:训练数据较多时,数据处理往往会成为训练速度的瓶颈,paddle提供了异步数据读取接口DataLoader,可以使用多进程进行数据加载,充分利用多处理的优势,具体使用方法及示例请参考API文档:[fluid.io.DataLLoader](https://www.paddlepaddle.org.cn/documentation/docs/en/api/io/DataLoader.html#dataloader)
##### 问题:如何提高单CPU多线程利用率?
+ 答复:线程数是设备同时并行执行程序的个数,可以将线程数设置为“CPU的个数*CPU的核数”。可以通过
`os.getenv("CPU_NUM")`或者`os.environ['CPU_NUM'] = str(2)`获取相关参数值 2. 推荐使用支持MKL(英特尔数学核心函数库)的paddle安装包,MKL相比Openblas等通用计算库在计算速度上有显著的优势,能够提升您的训练效率
---------- ----------
##### 问题:使用NVIDIA多卡运行Paddle时报错,`Error:NCCL ContextMap`或者`Error:hang住`(log日志打印突然卡住),如何解决? ##### 问题:使用NVIDIA多卡运行Paddle时报错 Nccl error,如何解决?
+ 答复:参考[NCCL Tests](https://github.com/NVIDIA/nccl-tests)检测您的环境。如果检测不通过,请登录[NCCL官网](https://developer.nvidia.com/zh-cn)下载NCCl,安装后重新检测。 + 答复:这个错误大概率是环境配置不正确导致的,建议您使用NVIDIA官方提供的方法参考检测自己的环境是否配置正确。具体地,可以使用[ NCCL Tests ](https://github.com/NVIDIA/nccl-tests) 检测您的环境;如果检测不通过,请登录[ NCCL官网 ](https://developer.nvidia.com/zh-cn)下载NCCl,安装后重新检测。
---------- ----------
...@@ -128,34 +124,26 @@ with fluid.dygraph.guard(fluid.CPUPlace()): ...@@ -128,34 +124,26 @@ with fluid.dygraph.guard(fluid.CPUPlace()):
---------- ----------
##### 问题:训练过程中提示显存不足,如何处理? ##### 问题:训练时报错提示显存不足,如何解决?
+ 答复:这是一种常见情况,你可以尝试调整`batch_size`大小,也可以更改网络模型,或者参考官方文档[显存分配与优化](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/advanced_usage/best_practice/memory_optimize.html) 。建议用户使用[AI Studio 学习与 实训社区训练](https://aistudio.baidu.com/aistudio/index),获取免费GPU算力,速度更快。
----------
##### 问题:GPU显存占用过高,如何解决?
+ 答复:建议调整 `FLAGS_fraction_of_gpu_memory_to_use` ,并检查`batch_size` 。通过设置较小的`batch_size`能降低显存消耗;`FLAGS_fraction_of_gpu_memory_to_use`默认值为 =0.92, 当申请不到需要的显存时会直接报内存不足。如遇到此情况,可以先检查一下GPU卡是否被占用,再设置较小的值,以启动程序。 + 答复:可以尝试按如下方法解决:
---------- 1. 检查是当前模型是否占用了过多显存,可尝试减小`batch_size`
##### 问题:GPU内存不足,报错 `Error:Out of memory error GPU`,如何处理? 2. 开启以下三个选项:
+ 问题描述:
![图片](https://agroup-bos-bj.cdn.bcebos.com/bj-3cbc8370534cb998f321af9b32aa2859403d9c9d) ```
#一旦不再使用即释放内存垃圾,=1.0 垃圾占用内存大小达到10G时,释放内存垃圾`
export FLAGS_eager_delete_tensor_gb=0.0`
#启用快速垃圾回收策略,不等待cuda kernel 结束,直接释放显存`
export FLAGS_fast_eager_deletion_mode=1`
#该环境变量设置只占用0%的显存`
export FLAGS_fraction_of_gpu_memory_to_use=0`
```
+ 解决方案: 详细请参考官方文档[存储分配与优化](https://www.paddlepaddle.org.cn/documentation/docs/zh/advanced_guide/performance_improving/singlenode_training_improving/memory_optimize.html) 调整相关配置。
1. 检查是当前模型是否占用内存过高,可尝试减小`batch_size` 此外,建议您使用[AI Studio 学习与 实训社区训练](https://aistudio.baidu.com/aistudio/index),获取免费GPU算力,提升您的训练效率。
2. 开启以下三个选项:
`#一旦不再使用即释放内存垃圾,=1.0 垃圾占用内存大小达到10G时,释放内存垃圾`
`export FLAGS_eager_delete_tensor_gb=0.0`
`#启用快速垃圾回收策略,不等待cuda kernel 结束,直接释放显存`
`export FLAGS_fast_eager_deletion_mode=1`
`#该环境变量设置只占用0%的显存`
`export FLAGS_fraction_of_gpu_memory_to_use=0`
---------- ----------
...@@ -163,20 +151,11 @@ with fluid.dygraph.guard(fluid.CPUPlace()): ...@@ -163,20 +151,11 @@ with fluid.dygraph.guard(fluid.CPUPlace()):
+ 答复:有如下两点建议: + 答复:有如下两点建议:
1. 如果数据预处理耗时较长,可使用py_Reader 或 multiprocess_reader加速; 1. 如果数据预处理耗时较长,可使用DataLoader加速数据读取过程,具体请参考API文档:[fluid.io.DataLLoader](https://www.paddlepaddle.org.cn/documentation/docs/en/api/io/DataLoader.html#dataloader)
2. 如果提高GPU计算量,可以增加`batch_size`,但是注意调节其他超参数。
以上两点均为比较通用的方案,其他的优化方案和模型相关,可参考相应models示例。
----------
##### 问题:使用CPU或GPU时,如何设置`num_threds`?
+ 答复: 2. 如果提高GPU计算量,可以增大`batch_size`,但是注意同时调节其他超参数以确保训练配置的正确性。
1. 如果是CPU,最大可以设置到当前CPU的内核数。 以上两点均为比较通用的方案,其他的优化方案和模型相关,可参考官方模型库 [models](https://github.com/PaddlePaddle/models) 中的具体示例。
2. 如果是GPU,受显卡多处理器的寄存器数目限制,例如GeForce 8800GT的显卡,最多8192个寄存器。假设每个线程需要的寄存器等于16,则最多只有512个线程。再高的线程将会将数据切换的显卡显存,反而降低执行效率。
---------- ----------
...@@ -184,44 +163,28 @@ with fluid.dygraph.guard(fluid.CPUPlace()): ...@@ -184,44 +163,28 @@ with fluid.dygraph.guard(fluid.CPUPlace()):
+ 答复:请先参考[显存分配与优化文档](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/advanced_usage/best_practice/memory_optimize.html) 开启存储优化开关,包括显存垃圾及时回收和Op内部的输出复用输入等。若存储空间仍然不够,建议: + 答复:请先参考[显存分配与优化文档](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/advanced_usage/best_practice/memory_optimize.html) 开启存储优化开关,包括显存垃圾及时回收和Op内部的输出复用输入等。若存储空间仍然不够,建议:
1. 降低`batch_size` 1. 降低 `batch_size`
2. 对index进行排序,减少padding的数量。 2. 对index进行排序,减少padding的数量。
---------- ----------
##### 问题:Executor与ParallelExecutor有什么区别?
+ 答复:如果没有指定Scope,所有的Executor都会共享一个Scope,即`global_scope`
1. `fluid.Executor`执行对象是Program,可以认为是一个轻量级的执行器,目前主要用于参数初始化、参数加载、参数模型保存。
2. `fluid.ParallelExecutor`的执行对象是Graph,ParallelExecutor内部会将Program转为Graph,这样更便于对模型进行分析。
----------
##### 问题:训练过程中如果出现不收敛的情况,如何处理? ##### 问题:训练过程中如果出现不收敛的情况,如何处理?
+ 答复:不收敛的原因有很多,可以参考如下方式排查: + 答复:不收敛的原因有很多,可以参考如下方式排查:
1. 检查数据集中训练数据的准确率,数据是否有很多错误,特征是否归一化; 1. 检查数据集中训练数据的准确率,数据是否有错误,特征是否归一化;
2. 简化网络结构,先基于benchmark实验,确保在baseline网络结构和数据集上的收敛结果正确; 2. 简化网络结构,先基于benchmark实验,确保在baseline网络结构和数据集上的收敛结果正确;
3. 对于复杂的网络,每次只增加一个改动,确保改动后的网络正确; 3. 对于复杂的网络,每次只增加一个改动,确保改动后的网络正确;
4. 检查网络在训练数据上的Loss是否下降; 4. 检查网络在训练数据上的Loss是否下降;
5. 检查学习率、优化算法是否合适,学习率过大会导致不收敛; 5. 检查学习率、优化算法是否合适,学习率过大会导致不收敛;
6. 检查`batch_size`设置是否合适,`batch_size`过小会导致不收敛; 6. 检查`batch_size`设置是否合适,`batch_size`过小会导致不收敛;
7. 检查梯度计算是否正确,是否有梯度过大的情况,是否为NaN 7. 检查梯度计算是否正确,是否有梯度过大的情况,是否为`NaN`
---------- ----------
##### 问题:Loss为NaN,如何处理? ##### 问题:Loss为NaN,如何处理?
+ 答复:可能由于网络的设计问题,Loss过大(Loss为NaN)会导致梯度爆炸。如果没有改网络结构,但是出现了NaN,可能是数据读取导致,比如标签对应关系错误。 + 答复:可能是网络设计存在问题,Loss过大(Loss为NaN)会导致梯度爆炸。如果没有改网络结构,但是出现了NaN,可能是数据读取导致,比如标签对应关系错误。
----------
##### 问题:在AI Studio上使用GPU训练时报错 `Attempt to use GPU for prediction, but environment variable CUDA_VISIBLE_DEVICES was not set correctly.`,如何处理?
+ 答复:需要在Notebook环境中增加:`%set_env CUDA_VISIBLE_DEVICES=0`
---------- ----------
...@@ -238,7 +201,33 @@ with fluid.dygraph.guard(fluid.CPUPlace()): ...@@ -238,7 +201,33 @@ with fluid.dygraph.guard(fluid.CPUPlace()):
##### 问题:增量训练中,如何保存模型和恢复训练? ##### 问题:增量训练中,如何保存模型和恢复训练?
+ 答复:在增量训练过程中,不仅需要保存模型的参数,也需要保存模型训练的状态(如learning_rate)。使用[save_persistables](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/api_cn/dygraph_cn.html#save-persistables)保存模型训练的参数和状态;恢复训练时,使用[load_persistables](https://www.paddlepaddle.org.cn/documentation/docs/zh/1.5/api_cn/dygraph_cn.html#load-persistables)进行恢复训练。 + 答复:在增量训练过程中,不仅需要保存模型的参数,也需要保存优化器的参数。
具体地,在1.8版本中需要使用Layer和Optimizer的`state_dict``set_dict`方法配合`fluid.save_dygraph/load_dygraph`使用。简要示例如下:
```
import paddle.fluid as fluid
with fluid.dygraph.guard():
emb = fluid.dygraph.Embedding([10, 10])
state_dict = emb.state_dict()
fluid.save_dygraph(state_dict, "paddle_dy")
adam = fluid.optimizer.Adam( learning_rate = fluid.layers.noam_decay( 100, 10000),
parameter_list = emb.parameters() )
state_dict = adam.state_dict()
fluid.save_dygraph(state_dict, "paddle_dy")
para_state_dict, opti_state_dict = fluid.load_dygraph("paddle_dy")
emb.set_dict(para_state_dict)
adam.set_dict(opti_state_dict)
```
更多介绍请参考以下API文档:
- [save_dygraph](https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/dygraph_cn/save_dygraph_cn.html#save-dygraph)
- [load_dygraph](https://www.paddlepaddle.org.cn/documentation/docs/zh/api_cn/dygraph_cn/load_dygraph_cn.html#load-dygraph)
---------- ----------
......
.. _cn_user_guide_broadcasting:
==================
广播 (broadcasting)
==================
飞桨(PaddlePaddle,以下简称Paddle)和其他框架一样,提供的一些API支持广播(broadcasting)机制,允许在一些运算时使用不同形状的张量。
通常来讲,如果有一个形状较小和一个形状较大的张量,我们希望多次使用较小的张量来对较大的张量执行一些操作,看起来像是较小形状的张量的形状首先被扩展到和较大形状的张量一致,然后做运算。
值得注意的是,这期间并没有对较小形状张量的数据拷贝操作。
飞桨的广播机制主要遵循如下规则(参考 `Numpy 广播机制 <https://numpy.org/doc/stable/user/basics.broadcasting.html#module-numpy.doc.broadcasting>`_ ):
1. 每个张量至少为一维张量
2. 从后往前比较张量的形状,当前维度的大小要么相等,要么其中一个等于一,要么其中一个不存在
例如:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
y = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
# 两个张量 形状一致,可以广播
x = paddle.to_tensor(np.ones((2, 3, 1, 5), np.float32))
y = paddle.to_tensor(np.ones((3, 4, 1), np.float32))
# 从后向前依次比较:
# 第一次:y的维度大小是1
# 第二次:x的维度大小是1
# 第三次:x和y的维度大小相等
# 第四次:y的维度不存在
# 所以 x和y是可以广播的
# 相反
x = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
y = paddle.to_tensor(np.ones((2, 3, 6), np.float32))
# 此时x和y是不可广播的,因为第一次比较 4不等于6
现在我们知道什么情况下两个张量是可以广播的,两个张量进行广播语义后的结果张量的形状计算规则如下:
1. 如果两个张量的形状的长度不一致,那么需要在较小形状长度的矩阵像前添加1,只到两个张量的形状长度相等。
2. 保证两个张量形状相等之后,每个维度上的结果维度就是当前维度上较大的那个。
例如:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 1), np.float32))
z = x + y
print(z.shape)
# z的形状: [2,3,4]
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 2), np.float32))
z = x + y
print(z.shape)
# InvalidArgumentError: Broadcast dimension mismatch.
除此之外,飞桨的elementwise系列API针对广播机制增加了axis参数,当使用较小形状的y来来匹配较大形状的x的时候,且满足y的形状的长度小于x的形状长度,
axis表示y在x上应用广播机制的时候的起始维度的位置,当设置了asis参数后,张量的维度比较顺序变成了从axis开始,从前向后比较。当axis=-1时,axis = rank(x) - rank(y),
同时y的大小为1的尾部维度将被忽略。
例如:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 1), np.float32))
z = paddle.elementwise_add(x, y, axis=1)
# z的形状 [2, 3, 4]
x = paddle.to_tensor(np.ones((2, 3, 4, 5), np.float32))
y = paddle.to_tensor(np.ones((4, 5), np.float32))
z = paddle.elementwise_add(x, y, axis=1)
print(z.shape)
# InvalidArgumentError: Broadcast dimension mismatch.
# 因为指定了axis之后,计算广播的维度从axis开始从前向后比较
x = paddle.to_tensor(np.ones((2, 3, 4, 5), np.float32))
y = paddle.to_tensor(np.ones((3), np.float32))
z = paddle.elementwise_add(x, y, axis=1)
print(z.shape)
# z的形状 [2, 3, 4, 5]
# 因为此时是从axis=1的维度开始,从前向后比较维度进行广播
.. _user_guide_broadcasting:
==================
Broadcasting
==================
PaddlePaddle provides broadcasting semantics in some APIs like other deep learning frameworks, which allows using tensors with different shapes while operating.
In General, broadcast is the rule how the smaller tensor is “broadcast” across the larger tsnsor so that they have same shapes.
Note that no copies happened while broadcasting.
In Paddlepaddle, tensors are broadcastable when following rulrs hold(ref: `Numpy Broadcasting <https://numpy.org/doc/stable/user/basics.broadcasting.html#module-numpy.doc.broadcasting>`_ ):
1. there should be at least one dimention in each tensor
2. when we compare their shapes element-wise from backward to forward, two dimensions are compatible when
they are equal, or one of them is 1, or one of them does not exist.
For example:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
y = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
# Two tensor have some shpes are broadcastable
x = paddle.to_tensor(np.ones((2, 3, 1, 5), np.float32))
y = paddle.to_tensor(np.ones((3, 4, 1), np.float32))
# compare from backward to forward:
# 1st step:y's dimention is 1
# 2nd step:x's dimention is 1
# 3rd step:two dimentions are the same
# 4st step:y's dimention does not exist
# So, x and y are broadcastable
# In Compare
x = paddle.to_tensor(np.ones((2, 3, 4), np.float32))
y = paddle.to_tensor(np.ones((2, 3, 6), np.float32))
# x and y are not broadcastable because in first step form tail, x's dimention 4 is not equal to y's dimention 6
Now we know in what condition two tensors are broadcastable, how to calculate the resulting tensor's size follows the rules:
1. If the number of dimensions of x and y are not equal, prepend 1 to the dimensions of the tensor with fewer dimensions to make them equal length.
2. Then, for each dimension size, the resulting dimension size is the max of the sizes of x and y along that dimension.
For example:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 1), np.float32))
z = x + y
print(z.shape)
# z'shape: [2,3,4]
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 2), np.float32))
z = x + y
print(z.shape)
# InvalidArgumentError: Broadcast dimension mismatch.
In addition, axis is introduced to PaddlePaddle's broadcasting semantics. when using smaller shape tensor y to broadcast a larger tensor x,
and y's length of dimentions is smaller than x's, we can specify a aixs to indicate the starting dimention to do broadcasting.
In this case, the comparation on dimentions runs from forward to backward started at axis. when axis=-1, axis = rank(x) - rank(y).
when the last dimention of y is 1, it will be ignored.
For example:
.. code-block:: python
import paddle
import numpy as np
paddle.disable_static()
x = paddle.to_tensor(np.ones((2, 1, 4), np.float32))
y = paddle.to_tensor(np.ones((3, 1), np.float32))
z = paddle.elementwise_add(x,y,axis=1)
# z'shape [2, 3, 4]
x = paddle.to_tensor(np.ones((2, 3, 4, 5), np.float32))
y = paddle.to_tensor(np.ones((4, 5), np.float32))
z = paddle.elementwise_add(x, y, axis=1)
print(z.shape)
# InvalidArgumentError: Broadcast dimension mismatch.
# axis is indicated, comparation between dimentions starts at axis.
x = paddle.to_tensor(np.ones((2, 3, 4, 5), np.float32))
y = paddle.to_tensor(np.ones((3), np.float32))
z = paddle.elementwise_add(x, y, axis=1)
print(z.shape)
# z'shape [2, 3, 4, 5]
# Start comparation at axis=1 from forward to backward.
...@@ -111,7 +111,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就 ...@@ -111,7 +111,7 @@ trace是指在模型运行时记录下其运行过哪些算子。TracedLayer就
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
......
...@@ -109,7 +109,7 @@ Load model and run it in static graph mode: ...@@ -109,7 +109,7 @@ Load model and run it in static graph mode:
place = paddle.CPUPlace() place = paddle.CPUPlace()
exe = paddle.Executor(place) exe = paddle.Executor(place)
program, feed_vars, fetch_vars = paddle.io.load_inference_model(save_dirname, exe) program, feed_vars, fetch_vars = paddle.static.load_inference_model(save_dirname, exe)
fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars) fetch, = exe.run(program, feed={feed_vars[0]: in_np}, fetch_list=fetch_vars)
However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance: However, as tracing only records operators once, if user's code contains Tensor-dependent (including Tensor value or Tensor shape) control flow, that is the Tensor can cause different operators being executed, then TracedLayer cannot handle this case. For instance:
......
...@@ -2,23 +2,26 @@ ...@@ -2,23 +2,26 @@
使用教程 使用教程
######## ########
PaddlePaddle (PArallel Distributed Deep LEarning)是一个易用、高效、灵活、可扩展的深度学习框架。 飞桨开源框架(PaddlePaddle)是一个易用、高效、灵活、可扩展的深度学习框架。
您可参考PaddlePaddle的 `Github <https://github.com/PaddlePaddle/Paddle>`_ 了解详情,也可阅读 `版本说明 <../release_note_cn.html>`_ 了解新版本的特性。 您可参考飞桨框架的 `Github <https://github.com/PaddlePaddle/Paddle>`_ 了解详情,也可阅读 `版本说明 <../release_note_cn.html>`_ 了解2.0beta版本的特性。
让我们从学习PaddlePaddle基本概念这里开始: 让我们从学习飞桨的基本概念这里开始:
- `Tensor概念介绍 <./tensor_introduction_cn.html>`_ : 飞桨中数据的表示方式,Tensor概念介绍。
- `Tensor概念介绍 <tensor_introduction.html>`_ : 飞桨中数据的表示方式,Tensor概念介绍, - `飞桨广播介绍 <./broadcasting_cn.html>`_ : 飞桨中广播概念的介绍。
- `版本迁移 <./migration_cn.html>`_:介绍 Paddle 1 到Paddle 2的变化与Paddle1to2转换工具的使用。 - `飞桨框架2.0beta升级指南 <./upgrade_guide_cn.html>`_: 介绍飞桨开源框架2.0beta的主要变化和如何升级。
- `动态图转静态图 <./dygraph_to_static/index_cn.html>`_:介绍 Paddle 动态图转静态图的方法 - `版本迁移工具 <./migration_cn.html>`_: 介绍paddle1to2转换工具的使用。
- `模型存储与载入 <./model_save_load_cn.html>`_:介绍 Paddle 模型与参数存储载入的方法 - `动态图转静态图 <./dygraph_to_static/index_cn.html>`_: 介绍飞桨动态图转静态图的方法
- `模型存储与载入 <./model_save_load_cn.html>`_: 介绍飞桨模型与参数存储载入的方法
.. toctree:: .. toctree::
:hidden: :hidden:
tensor_introduction.md tensor_introduction_cn.md
broadcasting_cn.rst
upgrade_guide_cn.md
migration_cn.rst migration_cn.rst
dygraph_to_static/index_cn.rst dygraph_to_static/index_cn.rst
model_save_load_cn.rst model_save_load_cn.rst
...@@ -10,6 +10,7 @@ Please refer to `PaddlePaddle Github <https://github.com/PaddlePaddle/Paddle>`_ ...@@ -10,6 +10,7 @@ Please refer to `PaddlePaddle Github <https://github.com/PaddlePaddle/Paddle>`_
Let's start with studying basic concept of PaddlePaddle: Let's start with studying basic concept of PaddlePaddle:
- `Introduction to Tensor <tensor_introduction_en.html>`_ : Introduction of Tensor, which is the representation of data in Paddle. - `Introduction to Tensor <tensor_introduction_en.html>`_ : Introduction of Tensor, which is the representation of data in Paddle.
- `broadcasting <./broadcasting_en.html>`_ : Introduction of broadcasting.
- `migration tools <./migration_en.html>`_:how to use migration tools to upgrade your code. - `migration tools <./migration_en.html>`_:how to use migration tools to upgrade your code.
- `dynamic to static <./dygraph_to_static/index_en.html>`_:how to convert your model from dynamic graph to static graph. - `dynamic to static <./dygraph_to_static/index_en.html>`_:how to convert your model from dynamic graph to static graph.
...@@ -17,5 +18,6 @@ Let's start with studying basic concept of PaddlePaddle: ...@@ -17,5 +18,6 @@ Let's start with studying basic concept of PaddlePaddle:
:hidden: :hidden:
tensor_introduction_en.md tensor_introduction_en.md
broadcasting_en.md
migration_en.rst migration_en.rst
dygraph_to_static/index_en.rst dygraph_to_static/index_en.rst
版本迁移 版本迁移工具
==================== ====================
飞桨框架v2.0-beta,最重要的变化为API体系的全面升级以及动态图能力的全面完善。下文将简要介绍Paddle 在飞桨框架2.0beta中,我们API的位置、命名、参数、行为,进行了系统性的调整和规范, 将API体系从1.X版本的 ``paddle.fluid.*`` 迁移到了 ``paddle.*`` 下。paddle.fluid目录下暂时保留了1.8版本API,主要是兼容性考虑,未来会被删除。
2的变化。
主要变化 使用版本迁移工具自动迁移您的paddle1.x的代码到Paddle2.0beta的代码
--------
在飞桨框架v2.0中,我们做了许多的升级。首先,全面完善了动态图模式,相较于静态图而言,动态图每次执行一个运算,可以立即得到结果,能够使算法的开发变得更加高效。此外,本版本对API目录,进行了较大的调整。将API体系从1.X版本的
``paddle.fluid.*`` 迁移到了 ``paddle.*`` 下。原则上,Paddle
2仍支持Paddle 1下的所有语法。但是,我们会逐步废弃掉 ``paddle.fluid``
下的API,强烈建议您将Paddle 1的代码迁移到Paddle
2下,以避免后续带来不必要的麻烦。下文将介绍手动与自动两种方式,来完成Paddle
1到Paddle 2的迁移。
手动将Paddle 1 的代码迁移到 Paddle 2
------------------------------------
本节将介绍如何将您的代码手动的从Paddle 1迁移到Paddle 2。
1、API的变化
~~~~~~~~~~~~
对于Paddle
1下的API,您可以通过我们提供的API升级表(TODO),查看每个API的升级关系,从而手动完成修改。
### 2、句法的变化 在Paddle 1中,通过 ``with fluid.dygraph.guard():``
开启动态图模式,在Paddle 2.0-beta中,可以直接通过
``paddle.disable_static()``\ 开启动态图。
Paddle1to2 自动迁移您的代码到Paddle2
------------------------------------ ------------------------------------
Paddle 2 包含了许多API的变化,为了节约您将代码从Paddle 1迁移到Paddle WARNING: 版本自动迁移工具并不能处理所有的情况,在使用本工具后,您仍然需要手工来进行检查并做相应的调整。
2的时间,我们提供了自动迁移工具–Paddle1to2,能够帮助您快速完成代码迁移。
安装 安装
~~~~ ~~~~
Paddle1to2可以通过pip的方式安装,方式如下: paddle1to2工具可以通过pip的方式安装,方式如下:
.. code:: ipython3 .. code:: ipython3
! pip install -U paddle1to2 $ pip install -U paddle1to2
基本用法 基本用法
~~~~~~~~ ~~~~~~~~
...@@ -50,14 +24,13 @@ Paddle1to2 可以使用下面的方式,快速使用: ...@@ -50,14 +24,13 @@ Paddle1to2 可以使用下面的方式,快速使用:
.. code:: ipython3 .. code:: ipython3
! paddle1to2 --inpath /path/to/model.py $ paddle1to2 --inpath /path/to/model.py
这将在命令行中,以\ ``diff``\ 的形式,展示model.py从Paddle 1转换为Paddle 这将在命令行中,以\ ``diff``\ 的形式,展示model.py从Paddle1.x转换为Paddle2.0beta的变化。如果您确认上述变化没有问题,只需要再执行:
2的变化。如果您确认上述变化没有问题,只需要再执行:
.. code:: ipython3 .. code:: ipython3
! paddle1to2 --inpath /path/to/model.py --write $ paddle1to2 --inpath /path/to/model.py --write
就会原地改写model.py,将上述变化改写到您的源文件中。 就会原地改写model.py,将上述变化改写到您的源文件中。
注意:我们会默认备份源文件,到~/.paddle1to2/下。 注意:我们会默认备份源文件,到~/.paddle1to2/下。
...@@ -86,26 +59,23 @@ Paddle1to2 可以使用下面的方式,快速使用: ...@@ -86,26 +59,23 @@ Paddle1to2 可以使用下面的方式,快速使用:
开始 开始
^^^^ ^^^^
在使用Paddle 1to2前,需要确保您已经安装了Paddle 2.0-beta版本。 在使用paddle1to2前,需要确保您已经安装了Paddle2.0beta版本。
.. code:: ipython3 .. code:: ipython3
import paddle import paddle
print (paddle.__version__) print (paddle.__version__)
# TODO change to paddle 2.0-beta
.. parsed-literal:: .. parsed-literal::
0.0.0 2.0.0-beta0
克隆\ `PaddlePaddle/models <https://github.com/PaddlePaddle/models>`__\ 来作为工具的测试。 克隆\ `paddlePaddle/models <https://github.com/PaddlePaddle/models>`__\ 来作为工具的测试。
.. code:: ipython3 .. code:: ipython3
! git clone https://github.com/PaddlePaddle/models $ git clone https://github.com/PaddlePaddle/models
.. parsed-literal:: .. parsed-literal::
...@@ -121,90 +91,89 @@ Paddle1to2 可以使用下面的方式,快速使用: ...@@ -121,90 +91,89 @@ Paddle1to2 可以使用下面的方式,快速使用:
查看帮助文档 查看帮助文档
^^^^^^^^^^^^ ^^^^^^^^^^^^
paddle1to2 会随着 paddle 您可以直接通过下面的方式,查看帮助文档。
2.0-beta安装。所以您可以直接通过下面的方式,查看帮助文档。
.. code:: ipython3 .. code:: ipython3
! paddle1to2 -h $ paddle1to2 -h
.. parsed-literal:: .. parsed-literal::
usage: paddle1to2 [-h] [--log-level {DEBUG,INFO,WARNING,ERROR}] usage: paddle1to2 [-h] [--log-level {DEBUG,INFO,WARNING,ERROR}]
[--no-log-file] [--log-filepath LOG_FILEPATH] --inpath [--no-log-file] [--log-filepath LOG_FILEPATH] --inpath
INPATH [--backup [BACKUP]] [--write] [--no-confirm] INPATH [--backup [BACKUP]] [--write] [--no-confirm]
[--refactor {refactor_import,norm_api_alias,args_to_kwargs,refactor_kwargs,api_rename,refactor_with,post_refactor}] [--refactor {refactor_import,norm_api_alias,args_to_kwargs,refactor_kwargs,api_rename,refactor_with,post_refactor}]
[--print-match] [--print-match]
optional arguments: optional arguments:
-h, --help show this help message and exit -h, --help show this help message and exit
--log-level {DEBUG,INFO,WARNING,ERROR} --log-level {DEBUG,INFO,WARNING,ERROR}
set log level, default is INFO set log level, default is INFO
--no-log-file don't log to file --no-log-file don't log to file
--log-filepath LOG_FILEPATH --log-filepath LOG_FILEPATH
set log file path, default is "report.log" set log file path, default is "report.log"
--inpath INPATH the file or directory path you want to upgrade. --inpath INPATH the file or directory path you want to upgrade.
--backup [BACKUP] backup directory, default is the "~/.paddle1to2/". --backup [BACKUP] backup directory, default is the "~/.paddle1to2/".
--write modify files in-place. --write modify files in-place.
--no-confirm write files in-place without confirm, ignored without --no-confirm write files in-place without confirm, ignored without
--write. --write.
--refactor {refactor_import,norm_api_alias,args_to_kwargs,refactor_kwargs,api_rename,refactor_with,post_refactor} --refactor {refactor_import,norm_api_alias,args_to_kwargs,refactor_kwargs,api_rename,refactor_with,post_refactor}
this is a debug option. Specify refactor you want to this is a debug option. Specify refactor you want to
run. If none, all refactors will be run. run. If none, all refactors will be run.
--print-match this is a debug option. Print matched code and node --print-match this is a debug option. Print matched code and node
for each file. for each file.
Paddle 1的例子 paddle1.x的例子
^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^
这里是一个基于Paddle 1实现的一个mnist分类,部分内容如下: 这里是一个基于paddle1.x实现的一个mnist分类,部分内容如下:
.. code:: ipython3 .. code:: ipython3
! head -n 198 models/dygraph/mnist/train.py | tail -n 20 $ head -n 198 models/dygraph/mnist/train.py | tail -n 20
.. parsed-literal:: .. code:: ipython3
with fluid.dygraph.guard(place): with fluid.dygraph.guard(place):
if args.ce: if args.ce:
print("ce mode") print("ce mode")
seed = 33 seed = 33
np.random.seed(seed) np.random.seed(seed)
fluid.default_startup_program().random_seed = seed fluid.default_startup_program().random_seed = seed
fluid.default_main_program().random_seed = seed fluid.default_main_program().random_seed = seed
if args.use_data_parallel: if args.use_data_parallel:
strategy = fluid.dygraph.parallel.prepare_context() strategy = fluid.dygraph.parallel.prepare_context()
mnist = MNIST() mnist = MNIST()
adam = AdamOptimizer(learning_rate=0.001, parameter_list=mnist.parameters()) adam = AdamOptimizer(learning_rate=0.001, parameter_list=mnist.parameters())
if args.use_data_parallel: if args.use_data_parallel:
mnist = fluid.dygraph.parallel.DataParallel(mnist, strategy) mnist = fluid.dygraph.parallel.DataParallel(mnist, strategy)
train_reader = paddle.batch( train_reader = paddle.batch(
paddle.dataset.mnist.train(), batch_size=BATCH_SIZE, drop_last=True) paddle.dataset.mnist.train(), batch_size=BATCH_SIZE, drop_last=True)
if args.use_data_parallel: if args.use_data_parallel:
train_reader = fluid.contrib.reader.distributed_batch_reader( train_reader = fluid.contrib.reader.distributed_batch_reader(
train_reader) train_reader)
使用Paddle1to2进行转化 使用paddle1to2进行转化
^^^^^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^^^^^
paddle1to2支持单文件的转化,您可以通过下方的命令直接转化单独的文件。 paddle1to2支持单文件的转化,您可以通过下方的命令直接转化单独的文件。
.. code:: ipython3 .. code:: ipython3
!paddle1to2 --inpath models/dygraph/mnist/train.py $ paddle1to2 --inpath models/dygraph/mnist/train.py
注意,对于参数的删除及一些特殊情况,我们都会打印WARNING信息,需要您仔细核对相关内容。 注意,对于参数的删除及一些特殊情况,我们都会打印WARNING信息,需要您仔细核对相关内容。
如果您觉得上述信息没有问题,可以直接对文件进行原地修改,方式如下: 如果您觉得上述信息没有问题,可以直接对文件进行原地修改,方式如下:
.. code:: ipython3 .. code:: ipython3
!paddle1to2 --inpath models/dygraph/mnist/train.py --write $ paddle1to2 --inpath models/dygraph/mnist/train.py --write
此时,命令行会弹出下方的提示: 此时,命令行会弹出下方的提示:
...@@ -220,15 +189,14 @@ paddle1to2支持单文件的转化,您可以通过下方的命令直接转化 ...@@ -220,15 +189,14 @@ paddle1to2支持单文件的转化,您可以通过下方的命令直接转化
.. code:: ipython3 .. code:: ipython3
! cat report.log $ cat report.log
注意事项 注意事项
~~~~~~~~ ~~~~~~~~
- 本迁移工具不能完成所有API的迁移,有少量的API需要您手动完成迁移,具体信息可见WARNING。 - 本迁移工具不能完成所有API的迁移,有少量的API需要您手动完成迁移,具体信息可见WARNING。
使用Paddle 2 使用paddle 2
~~~~~~~~~~~~ ~~~~~~~~~~~~
完成迁移后,代码就从Paddle 1迁移到了Paddle 2,您就可以在Paddle 完成迁移后,代码就从paddle1.x迁移到了paddle2.0beta,您就可以在paddle2.0beta下进行相关的开发。
2下进行相关的开发。
...@@ -25,16 +25,16 @@ ...@@ -25,16 +25,16 @@
.. image:: https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/paddle/guides/images/load_2.0.png?raw=true .. image:: https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/paddle/guides/images/load_2.0.png?raw=true
1.2 静态图存储载入体系(飞桨框架1.x) 1.2 静态图存储载入体系(飞桨框架1.x)
---------------------------- --------------------------------
静态图存储载入相关接口为飞桨框架1.x版本的主要使用接口,出于兼容性的目的,这些接口仍然可以在飞桨框架2.x使用,但不再推荐。相关接口包括: 静态图存储载入相关接口为飞桨框架1.x版本的主要使用接口,出于兼容性的目的,这些接口仍然可以在飞桨框架2.x使用,但不再推荐。相关接口包括:
- paddle.io.save - paddle.static.save
- paddle.io.load - paddle.static.load
- paddle.io.save_inference_model - paddle.static.save_inference_model
- paddle.io.load_inference_model - paddle.static.load_inference_model
- paddle.io.load_program_state - paddle.static.load_program_state
- paddle.io.set_program_state - paddle.static.set_program_state
由于飞桨框架2.0不再主推静态图模式,故本文不对以上主要用于飞桨框架1.x的相关接口展开介绍,如有需要,可以阅读对应API文档。 由于飞桨框架2.0不再主推静态图模式,故本文不对以上主要用于飞桨框架1.x的相关接口展开介绍,如有需要,可以阅读对应API文档。
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
- paddle.Model.save - paddle.Model.save
- paddle.Model.load - paddle.Model.load
飞桨框架2.0高阶API存储载入接口体系清晰,表意直观,若有需要,建议直接阅读相关API文档,此处不再赘述。 飞桨框架2.0高阶API仅有一套Save/Load接口,表意直观,体系清晰,若有需要,建议直接阅读相关API文档,此处不再赘述。
.. note:: .. note::
本教程着重介绍飞桨框架2.x的各个存储载入接口的关系及各种使用场景,不对接口参数进行详细介绍,如果需要了解具体接口参数的含义,请直接阅读对应API文档。 本教程着重介绍飞桨框架2.x的各个存储载入接口的关系及各种使用场景,不对接口参数进行详细介绍,如果需要了解具体接口参数的含义,请直接阅读对应API文档。
...@@ -56,10 +56,7 @@ ...@@ -56,10 +56,7 @@
若仅需要存储/载入模型的参数,可以使用 ``paddle.save/load`` 结合Layer和Optimizer的state_dict达成目的,此处state_dict是对象的持久参数的载体,dict的key为参数名,value为参数真实的numpy array值。 若仅需要存储/载入模型的参数,可以使用 ``paddle.save/load`` 结合Layer和Optimizer的state_dict达成目的,此处state_dict是对象的持久参数的载体,dict的key为参数名,value为参数真实的numpy array值。
2.1 参数存储 结合以下简单示例,介绍参数存储和载入的方法,以下示例完成了一个简单网络的训练过程:
------------
参数存储时,先获取目标对象(Layer或者Optimzier)的state_dict,然后将state_dict存储至磁盘,示例如下:
.. code-block:: python .. code-block:: python
...@@ -128,20 +125,53 @@ ...@@ -128,20 +125,53 @@
# train # train
train(layer, loader, loss_fn, adam) train(layer, loader, loss_fn, adam)
# save
model_path = "linear_net"
param_state_dict = layer.state_dict() 2.1 参数存储
paddle.save(param_state_dict, model_path) ------------
参数存储时,先获取目标对象(Layer或者Optimzier)的state_dict,然后将state_dict存储至磁盘,示例如下(接前述示例):
opt_state_dict = adam.state_dict() .. code-block:: python
paddle.save(opt_state_dict, model_path)
# save
paddle.save(layer.state_dict(), "linear_net.pdparams")
paddle.save(adam.state_dict(), "adam.pdopt")
2.2 参数载入 2.2 参数载入
------------ ------------
参数载入时,先从磁盘载入保存的state_dict,然后通过set_state_dict方法配置到目标对象中,示例如下: 参数载入时,先从磁盘载入保存的state_dict,然后通过set_state_dict方法配置到目标对象中,示例如下(接前述示例):
.. code-block:: python
# load
layer_state_dict = paddle.load("linear_net.pdparams")
opt_state_dict = paddle.load("adam.pdopt")
layer.set_state_dict(layer_state_dict)
adam.set_state_dict(opt_state_dict)
三、模型&参数存储载入(训练部署)
############################
若要同时存储/载入模型结构和参数,可以使用 ``paddle.jit.save/load`` 实现。
3.1 模型&参数存储
----------------
模型&参数存储根据训练模式不同,有两种使用情况:
(1) 动转静训练 + 模型&参数存储
(2) 动态图训练 + 模型&参数存储
3.1.1 动转静训练 + 模型&参数存储
``````````````````````````````
动转静训练相比直接使用动态图训练具有更好的执行性能,训练完成后,直接将目标Layer传入 ``paddle.jit.save`` 存储即可。:
一个简单的网络训练示例如下:
.. code-block:: python .. code-block:: python
...@@ -175,6 +205,7 @@ ...@@ -175,6 +205,7 @@
super(LinearNet, self).__init__() super(LinearNet, self).__init__()
self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM) self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
@paddle.jit.to_static
def forward(self, x): def forward(self, x):
return self._linear(x) return self._linear(x)
...@@ -207,28 +238,20 @@ ...@@ -207,28 +238,20 @@
drop_last=True, drop_last=True,
num_workers=2) num_workers=2)
# load
model_path = "linear_net"
param_state_dict, opt_state_dict = paddle.load(model_path)
layer.set_state_dict(param_state_dict)
adam.set_state_dict(opt_state_dict)
# train # train
train(layer, loader, loss_fn, adam) train(layer, loader, loss_fn, adam)
.. note::
``paddle.load`` 接口可能仍会改动,后续可能改为仅返回一个单独的dict。
三、模型&参数存储载入(训练部署) 随后使用 ``paddle.jit.save`` 对模型和参数进行存储(接前述示例):
############################
若要同时存储/载入模型结构和参数,可以使用 ``paddle.jit.save/load`` 实现。 .. code-block:: python
3.1 模型&参数存储 # save
---------------- model_path = "linear.example.model"
paddle.jit.save(layer, model_path)
同时存储模型和参数,需要结合动静转换功能使用。有以下三项注意点:
通过动转静训练后保存模型&参数,有以下两项注意点:
(1) Layer对象的forward方法需要经由 ``paddle.jit.to_static`` 装饰 (1) Layer对象的forward方法需要经由 ``paddle.jit.to_static`` 装饰
...@@ -322,9 +345,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -322,9 +345,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
return self._linear(x) return self._linear(x)
(3) 使用 ``paddle.jit.save`` 存储模型和参数 3.1.2 动态图训练 + 模型&参数存储
``````````````````````````````
动态图模式相比动转静模式更加便于调试,如果您仍需要使用动态图直接训练,也可以在动态图训练完成后调用 ``paddle.jit.save`` 直接存储模型和参数。
直接将目标Layer传入 ``paddle.jit.save`` 存储即可,完整示例如下 同样是一个简单的网络训练示例
.. code-block:: python .. code-block:: python
...@@ -332,6 +358,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -332,6 +358,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
import paddle import paddle
import paddle.nn as nn import paddle.nn as nn
import paddle.optimizer as opt import paddle.optimizer as opt
from paddle.static import InputSpec
BATCH_SIZE = 16 BATCH_SIZE = 16
BATCH_NUM = 4 BATCH_NUM = 4
...@@ -358,7 +385,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -358,7 +385,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
super(LinearNet, self).__init__() super(LinearNet, self).__init__()
self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM) self._linear = nn.Linear(IMAGE_SIZE, CLASS_NUM)
@paddle.jit.to_static
def forward(self, x): def forward(self, x):
return self._linear(x) return self._linear(x)
...@@ -377,8 +403,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -377,8 +403,6 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
place = paddle.CPUPlace() place = paddle.CPUPlace()
paddle.disable_static(place) paddle.disable_static(place)
# 1. train & save model.
# create network # create network
layer = LinearNet() layer = LinearNet()
loss_fn = nn.CrossEntropyLoss() loss_fn = nn.CrossEntropyLoss()
...@@ -396,14 +420,47 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -396,14 +420,47 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# train # train
train(layer, loader, loss_fn, adam) train(layer, loader, loss_fn, adam)
训练完成后使用 ``paddle.jit.save`` 对模型和参数进行存储:
.. code-block:: python
# save # save
model_path = "linear.example.model" model_path = "linear.example.dy_model"
paddle.jit.save(layer, model_path) paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[InputSpec(shape=[None, 784], dtype='float32')])
动态图训练后使用 ``paddle.jit.save`` 存储模型和参数注意点如下:
.. note:: (1) 相比动转静训练,Layer对象的forward方法不需要额外装饰,保持原实现即可
后续仍会优化此处的使用方式,支持不装饰 ``to_static`` 也能够通过 ``paddle.jit.save`` 直接存储模型和参数。
(2) 与动转静训练相同,请确保Layer.forward方法中仅实现预测功能,避免将训练所需的loss计算逻辑写入forward方法
(3) 在最后使用 ``paddle.jit.save`` 时,需要指定Layer的 ``InputSpec`` ,Layer对象forward方法的每一个参数均需要对应的 ``InputSpec`` 进行描述,不能省略。这里的 ``input_spec`` 参数支持两种类型的输入:
- ``InputSpec`` 列表
使用InputSpec描述forward输入参数的shape,dtype和name,如前述示例(此处示例中name省略,name省略的情况下会使用forward的对应参数名作为name,所以这里的name为 ``x`` ):
.. code-block:: python
paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[InputSpec(shape=[None, 784], dtype='float32')])
- Example Tensor 列表
除使用InputSpec之外,也可以直接使用forward训练时的示例输入,此处可以使用前述示例中迭代DataLoader得到的 ``image`` ,示例如下:
.. code-block:: python
paddle.jit.save(
layer=layer,
model_path=model_path,
input_spec=[image])
3.2 模型&参数载入 3.2 模型&参数载入
---------------- ----------------
...@@ -512,7 +569,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -512,7 +569,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# load # load
model_path = "linear.example.model" model_path = "linear.example.model"
state_dict, _ = paddle.load(model_path) state_dict = paddle.load(model_path)
# inference # inference
layer.set_state_dict(state_dict, use_structured_name=False) layer.set_state_dict(state_dict, use_structured_name=False)
...@@ -526,7 +583,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -526,7 +583,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
如果您是从飞桨框架1.x切换到2.x,曾经使用飞桨框架1.x的接口存储模型或者参数,飞桨框架2.x也对这种情况进行了兼容性支持,包括以下几种情况。 如果您是从飞桨框架1.x切换到2.x,曾经使用飞桨框架1.x的接口存储模型或者参数,飞桨框架2.x也对这种情况进行了兼容性支持,包括以下几种情况。
4.1 从 ``paddle.io.save_inference_model`` 存储结果中载入模型&参数 4.1 从 ``paddle.static.save_inference_model`` 存储结果中载入模型&参数
------------------------------------------------------------------ ------------------------------------------------------------------
曾用接口名为 ``paddle.fluid.io.save_inference_model`` 。 曾用接口名为 ``paddle.fluid.io.save_inference_model`` 。
...@@ -535,7 +592,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -535,7 +592,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
使用 ``paddle.jit.load`` 配合 ``paddle.SaveLoadConfig`` 载入模型和参数。 使用 ``paddle.jit.load`` 配合 ``paddle.SaveLoadConfig`` 载入模型和参数。
模型准备及训练示例,该示例为后续所有示例的前序逻辑: 飞桨1.x模型准备及训练示例,该示例为后续所有示例的前序逻辑:
.. code-block:: python .. code-block:: python
...@@ -670,7 +727,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -670,7 +727,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
model_path = "fc.example.model" model_path = "fc.example.model"
load_param_dict, _ = paddle.load(model_path) load_param_dict = paddle.load(model_path)
如果您指定了存储的模型文件名,可以按照以下方式载入(接前述示例): 如果您指定了存储的模型文件名,可以按照以下方式载入(接前述示例):
...@@ -680,7 +737,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -680,7 +737,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
config = paddle.SaveLoadConfig() config = paddle.SaveLoadConfig()
config.model_filename = "__simplenet__" config.model_filename = "__simplenet__"
load_param_dict, _ = paddle.load(model_path, config) load_param_dict = paddle.load(model_path, config)
如果您指定了存储的参数文件名,可以按照以下方式载入(接前述示例): 如果您指定了存储的参数文件名,可以按照以下方式载入(接前述示例):
...@@ -690,7 +747,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -690,7 +747,7 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
config = paddle.SaveLoadConfig() config = paddle.SaveLoadConfig()
config.params_filename = "__params__" config.params_filename = "__params__"
load_param_dict, _ = paddle.load(model_path, config) load_param_dict = paddle.load(model_path, config)
.. note:: .. note::
一般预测模型不会存储优化器Optimizer的参数,因此此处载入的仅包括模型本身的参数。 一般预测模型不会存储优化器Optimizer的参数,因此此处载入的仅包括模型本身的参数。
...@@ -698,12 +755,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -698,12 +755,12 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
.. note:: .. note::
由于 ``structured_name`` 是动态图下独有的变量命名方式,因此从静态图存储结果载入的state_dict在配置到动态图的Layer中时,需要配置 ``Layer.set_state_dict(use_structured_name=False)`` 。 由于 ``structured_name`` 是动态图下独有的变量命名方式,因此从静态图存储结果载入的state_dict在配置到动态图的Layer中时,需要配置 ``Layer.set_state_dict(use_structured_name=False)`` 。
4.2 从 ``paddle.io.save`` 存储结果中载入参数 4.2 从 ``paddle.static.save`` 存储结果中载入参数
---------------------------------------------- ----------------------------------------------
曾用接口名为 ``paddle.fluid.save`` 。 曾用接口名为 ``paddle.fluid.save`` 。
``paddle.fluid.save`` 的存储格式与2.x动态图接口 ``paddle.save`` 存储格式是类似的,同样存储了dict格式的参数,因此可以直接使用 ``paddle.load`` 载入state_dict,示例如下(接前述示例): ``paddle.fluid.save`` 的存储格式与2.x动态图接口 ``paddle.save`` 存储格式是类似的,同样存储了dict格式的参数,因此可以直接使用 ``paddle.load`` 载入state_dict,但需要注意不能仅传入保存的路径,而要传入保存参数的文件名,示例如下(接前述示例):
.. code-block:: python .. code-block:: python
...@@ -715,22 +772,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -715,22 +772,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
# enable dygraph mode # enable dygraph mode
paddle.disable_static(place) paddle.disable_static(place)
load_param_dict, _ = paddle.load(model_path) load_param_dict = paddle.load("fc.example.model.save.pdparams")
.. note:: .. note::
由于 ``paddle.fluid.save`` 接口原先在静态图模式下的定位是存储训练时参数,或者说存储Checkpoint,故尽管其同时存储了模型结构,目前也暂不支持从 ``paddle.fluid.save`` 的存储结果中同时载入模型和参数,后续如有需求再考虑支持。 由于 ``paddle.fluid.save`` 接口原先在静态图模式下的定位是存储训练时参数,或者说存储Checkpoint,故尽管其同时存储了模型结构,目前也暂不支持从 ``paddle.fluid.save`` 的存储结果中同时载入模型和参数,后续如有需求再考虑支持。
4.3 从 ``paddle.io.save_params/save_persistables`` 存储结果中载入参数 4.3 从 ``paddle.fluid.io.save_params/save_persistables`` 存储结果中载入参数
----------------------------------------------------------------------- -------------------------------------------------------------------------
.. note:: 这两个接口在飞桨1.x版本时,已经不再推荐作为存储模型参数的接口使用,故并未继承至飞桨2.x,之后也不会再推荐使用这两个接口存储参数。
以下方式仅为暂时解决方案,后续计划会在 ``paddle.load`` 接口支持此功能。
对于使用这两个接口存储参数兼容载入的支持,分为两种情况,下面以 ``paddle.fluid.io.save_params`` 接口为例介绍相关使用方法:
曾用接口名为 ``paddle.fluid.io.save_params/save_persistables`` 。 (1) 使用默认方式存储,各参数分散存储为单独的文件,文件名为参数名
此处可以使用 ``paddle.io.load_program_state`` 接口从以上两个接口的存储结果中载入state_dict,并用于动态图Layer的配置,示例如下(接前述示例): 这种存储方式仍然可以使用 ``paddle.load`` 接口兼容载入,使用示例如下(接前述示例):
.. code-block:: python .. code-block:: python
...@@ -739,4 +797,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收 ...@@ -739,4 +797,23 @@ Layer更准确的语义是描述一个具有预测功能的模型对象,接收
fluid.io.save_params(exe, model_path) fluid.io.save_params(exe, model_path)
# load # load
state_dict = paddle.io.load_program_state(model_path) state_dict = paddle.load(model_path)
print(state_dict)
(2) 指定了参数存储的文件,将所有参数存储至单个文件中
将所有参数存储至单个文件中会导致存储结果中丢失Tensor名和Tensor数据之间的映射关系,因此这部分丢失的信息需要用户传入进行补足。为了确保正确性,这里不仅要传入Tensor的name列表,同时要传入Tensor的shape和dtype等描述信息,通过检查和存储数据的匹配性确保严格的正确性,这导致载入数据的恢复过程变得比较复杂,仍然需要一些飞桨1.x的概念支持。后续如果此项需求较为普遍,我们将会考虑将该项功能兼容支持到 ``paddle.load`` 中,但由于信息丢失而导致的使用复杂性仍然是存在的,因此建议您避免仅使用这两个接口存储参数。
目前暂时推荐您使用 ``paddle.static.load_program_state`` 接口解决此处的载入问题,需要获取原Program中的参数列表传入该方法,使用示例如下(接前述示例):
.. code-block:: python
# save by fluid.io.save_params
model_path = "fc.example.model.save_params_with_filename"
fluid.io.save_params(exe, model_path, filename="__params__")
# load
import os
params_file_path = os.path.join(model_path, "__params__")
var_list = fluid.default_main_program().all_parameters()
state_dict = paddle.io.load_program_state(params_file_path, var_list)
# 飞桨框架2.0beta升级指南
## 升级概要
本版本是2.0版的公测版,相对1.8版本有重大升级,涉及开发方面的重要变化如下:
- 动态图功能完善,动态图模下数据表示概念为Tensor,推荐使用动态图模式;
- API目录体系调整,API的命名和别名进行了统一规范化,虽然兼容老版API,但请使用新API体系开发;
- 数据处理、组网方式、模型训练、多卡启动、模型保存和推理等开发流程都有了对应优化,请对应查看说明;
以上变化请仔细阅读本指南。对于已有模型的升级,我们还提供了2.0转换工具(见附录)提供更自动化的辅助。
其他一些功能增加方面诸如动态图对量化训练、混合精度的支持、动静转换等方面不在本指南列出,具体可查看[Release Note](https://github.com/PaddlePaddle/Paddle/releases/tag/v2.0.0-beta0#)或对应文档。
## 一、动态图
### 推荐优先使用动态图模式
飞桨2.0版本将会把动态图作为默认模式。2.0-beta版本虽然还未做默认切换,但推荐大家优先使用动态图模式,需要在程序开始时调用`paddle.disable_static`切换到动态图。2.0-rc版本后默认模式将切换为动态图,此行代码可删除。(2.0-rc版本后如果还想使用静态图,可通过调用`paddle.enable_static`切换)。
```python
import paddle
# 2.0-beta版本需要调用下面代码,切换到动态图模式
# 2.0-rc版本可以删除这一行
paddle.disable_static()
```
### 使用Tensor概念表示数据
静态图模式下,由于组网时使用的数据不能实时访问,Paddle用Variable来表示数据。
动态图下,从直观性等角度考虑,将数据表示概念统一为Tensor。动态图下Tensor的创建主要有两种方法:
1. 通过调用paddle.to_tensor函数,将python scalar/list,或者numpy.ndarray数据转换为Paddle的Tensor。具体使用方法,请查看官网的API文档。
```python
import paddle
paddle.disable_static()
paddle.to_tensor(1)
paddle.to_tensor((1.1, 2.2))
paddle.to_tensor(np.random.randn(3, 4))
```
2. 通过调用 `paddle.zeros, paddle.ones, paddle.full, paddle.arange, paddle.rand, paddle.randn, paddle.randint, paddle.normal, paddle.uniform` 等函数,创建并返回Tensor。
## 二、API
### API目录结构
为了API组织更加简洁和清晰,将原来padddle.fluid.xxx的目录体系全新升级为paddle.xxx,并对子目录的组织进行了系统的条理化优化。同时还增加了高层API,可以高低搭配使用。paddle.fluid目录下暂时保留了1.8版本API,主要是兼容性考虑,未来会被删除。
**基于2.0的开发任务,请使用paddle目录下的API,不要再使用paddle.fluid目录下的API。** 如果发现Paddle目录下有API缺失的情况,推荐使用基础API进行组合实现;您也可以通过在 [github](https://github.com/paddlepaddle/paddle) 上提issue的方式向我们反馈。
**2.0-beta版本的API 整体目录结构如下**
| 目录 | 功能和包含的API |
| :--- | --------------- |
| paddle.* | paddle根目录下保留了常用API的别名,当前包括:paddle.tensor和paddle.framework目录下的所有API |
| paddle.tensor | 跟tensor操作相关的API,比如:创建zeros, 矩阵运算matmul, 变换concat, 计算add, 查找argmax等 |
| paddle.nn | 跟组网相关的API,比如:Linear,卷积,LSTM,损失函数,激活函数等 |
| paddle.static.nn | 静态图下组网专用API,比如:输入占位符data, 全连接层fc, 控制流while_loop/cond |
| paddle.static | 静态图下基础框架相关API,比如:Variable, Program, Executor等 |
| paddle.framework | 框架通用API和动态图模式的API,比如:to_tensor, no_grad等 |
| paddle.optimizer | 优化算法相关API,比如:SGD,Adagrad, Adam等 |
| paddle.optimizer.lr_scheduler | 学习率衰减相关API |
| paddle.metric | 评估指标计算相关的API,比如:accuracy, auc等 |
| paddle.io | 数据输入输出相关API,比如:Dataset, DataLoader等 |
| paddle.device | 设备管理相关API,比如:CPUPlace, CUDAPlace等 |
| paddle.distributed | 分布式相关基础API |
| paddle.distributed.fleet | 分布式相关高层API |
| paddle.vision | 视觉领域API,比如,数据集,数据处理,常用基础网络结构,比如resnet |
| paddle.text | NLP领域API, 比如,数据集,数据处理,常用网络结构,比如Transformer |
### API别名规则
- 为了方便用户使用,API会在不同的路径下建立别名:
- 所有framework, tensor目录下的API,均在paddle根目录建立别名;除少数特殊API外,其他API在paddle根目录下均没有别名。
- paddle.nn目录下除functional目录以外的所有API,在paddle.nn目录下均有别名;functional目录中的API,在paddle.nn目录下均没有别名。
- **推荐用户优先使用较短的路径的别名**,比如`paddle.add -> paddle.tensor.add`,推荐优先使用`paddle.add`
- 以下为一些特殊的别名关系,推荐使用左边的API名称:
- paddle.sigmoid -> paddle.tensor.sigmoid -> paddle.nn.functional.sigmoid
- paddle.tanh -> paddle.tensor.tanh -> paddle.nn.functional.tanh
- paddle.remainder -> paddle.mod -> paddle.floor_mod
- paddle.divide -> paddle.true_divide
- paddle.rand -> paddle.uniform
- paddle.randn -> paddle.standard_normal
- Optimizer.clear_grad -> Optimizer.clear_gradients
- Optimizer.set_state_dict -> Optimizer.set_dict
- Optimizer.get_lr -> Optimizer.current_step_lr
- Layer.clear_grad -> Layer.clear_gradients
- Layer.set_state_dict -> Layer.set_dict
### 常用API名称变化
- 加、减、乘、除使用全称,不使用简称
- 对于当前逐元素操作,不加elementwise前缀
- 对于按照某一轴操作,不加reduce前缀
- Conv, Pool, Dropout, BatchNorm, Pad组网类API根据输入数据类型增加1d, 2d, 3d后缀
| Paddle 1.8 API名称 | Paddle 2.0-beta 对应的名称|
| --------------- | ------------------------ |
| paddle.fluid.layers.elementwise_add | paddle.add |
| paddle.fluid.layers.elementwise_sub | paddle.subtract |
| paddle.fluid.layers.elementwise_mul | paddle.multiply |
| paddle.fluid.layers.elementwise_div | paddle.divide |
| paddle.fluid.layers.elementwise_max | paddle.maximum |
| paddle.fluid.layers.elementwise_min | paddle.minimum |
| paddle.fluid.layers.reduce_sum | paddle.sum |
| paddle.fluid.layers.reduce_prod | paddle.prod |
| paddle.fluid.layers.reduce_max | paddle.max |
| paddle.fluid.layers.reduce_min | paddle.min |
| paddle.fluid.layers.reduce_all | paddle.all |
| paddle.fluid.layers.reduce_any | paddle.any |
| paddle.fluid.dygraph.Conv2D | paddle.nn.Conv2d |
| paddle.fluid.dygraph.Conv2DTranspose | paddle.nn.ConvTranspose2d |
| paddle.fluid.dygraph.Pool2D | paddle.nn.MaxPool2d, paddle.nn.AvgPool2d |
## 三、开发流程
### 数据处理
数据处理推荐使用**paddle.io目录下的Dataset,Sampler, BatchSampler, DataLoader接口**,不推荐reader类接口。一些常用的数据集已经在paddle.vision.datasets和paddle.text.datasets目录实现,具体参考API文档。
```python
from paddle.io import Dataset
class MyDataset(Dataset):
"""
步骤一:继承paddle.io.Dataset类
"""
def __init__(self, mode='train'):
"""
步骤二:实现构造函数,定义数据读取方式,划分训练和测试数据集
"""
super(MyDataset, self).__init__()
if mode == 'train':
self.data = [
['traindata1', 'label1'],
['traindata2', 'label2'],
['traindata3', 'label3'],
['traindata4', 'label4'],
]
else:
self.data = [
['testdata1', 'label1'],
['testdata2', 'label2'],
['testdata3', 'label3'],
['testdata4', 'label4'],
]
def __getitem__(self, index):
"""
步骤三:实现__getitem__方法,定义指定index时如何获取数据,并返回单条数据(训练数据,对应的标签)
"""
data = self.data[index][0]
label = self.data[index][1]
return data, label
def __len__(self):
"""
步骤四:实现__len__方法,返回数据集总数目
"""
return len(self.data)
# 测试定义的数据集
train_dataset = MyDataset(mode='train')
val_dataset = MyDataset(mode='test')
print('=============train dataset=============')
for data, label in train_dataset:
print(data, label)
print('=============evaluation dataset=============')
for data, label in val_dataset:
print(data, label)
```
### 组网方式
#### Sequential 组网
针对顺序的线性网络结构我们可以直接使用Sequential来快速完成组网,可以减少类的定义等代码编写。
```python
import paddle
paddle.disable_static()
# Sequential形式组网
mnist = paddle.nn.Sequential(
paddle.nn.Flatten(),
paddle.nn.Linear(784, 512),
paddle.nn.ReLU(),
paddle.nn.Dropout(0.2),
paddle.nn.Linear(512, 10)
)
```
#### SubClass组网
针对一些比较复杂的网络结构,就可以使用Layer子类定义的方式来进行模型代码编写,在`__init__`构造函数中进行组网Layer的声明,在`forward`中使用声明的Layer变量进行前向计算。子类组网方式也可以实现sublayer的复用,针对相同的layer可以在构造函数中一次性定义,在forward中多次调用。
```python
import paddle
paddle.disable_static()
# Layer类继承方式组网
class Mnist(paddle.nn.Layer):
def __init__(self):
super(Mnist, self).__init__()
self.flatten = paddle.nn.Flatten()
self.linear_1 = paddle.nn.Linear(784, 512)
self.linear_2 = paddle.nn.Linear(512, 10)
self.relu = paddle.nn.ReLU()
self.dropout = paddle.nn.Dropout(0.2)
def forward(self, inputs):
y = self.flatten(inputs)
y = self.linear_1(y)
y = self.relu(y)
y = self.dropout(y)
y = self.linear_2(y)
return y
mnist = Mnist()
```
### 模型训练
#### 使用高层API
增加了paddle.Model高层API,大部分任务可以使用此API用于简化训练、评估、预测类代码开发。注意区别Model和Net概念,Net是指继承paddle.nn.Layer的网络结构;而Model是指持有一个Net实例,同时指定损失函数、优化算法、评估指标的可训练、评估、预测的实例。具体参考高层API的代码示例。
```python
import paddle
paddle.disable_static()
train_dataset = paddle.vision.datasets.MNIST(mode='train')
test_dataset = paddle.vision.datasets.MNIST(mode='test')
lenet = paddle.vision.models.LeNet()
# Mnist继承paddle.nn.Layer属于Net,model包含了训练功能
model = paddle.Model(lenet)
# 设置训练模型所需的optimizer, loss, metric
model.prepare(
paddle.optimizer.Adam(learning_rate=0.001, parameters=model.parameters()),
paddle.nn.CrossEntropyLoss(),
paddle.metric.Accuracy(topk=(1, 2))
)
# 启动训练
model.fit(train_dataset, epochs=2, batch_size=64, log_freq=200)
# 启动评估
model.evaluate(test_dataset, log_freq=20, batch_size=64)
```
#### 使用基础API
```python
import paddle
paddle.disable_static()
train_dataset = paddle.vision.datasets.MNIST(mode='train')
test_dataset = paddle.vision.datasets.MNIST(mode='test')
lenet = paddle.vision.models.LeNet()
# 加载训练集 batch_size 设为 64
train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), batch_size=64, shuffle=True)
def train():
epochs = 2
adam = paddle.optimizer.Adam(learning_rate=0.001, parameters=lenet.parameters())
# 用Adam作为优化函数
for epoch in range(epochs):
for batch_id, data in enumerate(train_loader()):
x_data, y_data = data
predicts = lenet(x_data)
loss = paddle.nn.functional.cross_entropy(predicts, y_data, reduction='mean')
acc = paddle.metric.accuracy(predicts, y_data, k=1)
avg_acc = paddle.mean(acc)
loss.backward()
if batch_id % 100 == 0:
print("epoch: {}, batch_id: {}, loss is: {}, acc is: {}".format(epoch, batch_id, loss.numpy(), avg_acc.numpy()))
adam.step()
adam.clear_grad()
# 启动训练
train()
```
### 单机多卡启动
2.0增加paddle.distributed.spawn函数来启动单机多卡训练,同时原有的paddle.distributed.launch的方式依然保留。
#### 方式1、launch启动
##### 高层API场景
当调用paddle.Model高层来实现训练时,想要启动单机多卡训练非常简单,代码不需要做任何修改,只需要在启动时增加一下参数`-m paddle.distributed.launch`
```bash
# 单机单卡启动,默认使用第0号卡
$ python train.py
# 单机多卡启动,默认使用当前可见的所有卡
$ python -m paddle.distributed.launch train.py
# 单机多卡启动,设置当前使用的第0号和第1号卡
$ python -m paddle.distributed.launch --selected_gpus='0,1' train.py
# 单机多卡启动,设置当前使用第0号和第1号卡
$ export CUDA_VISIABLE_DEVICES='0,1'
$ python -m paddle.distributed.launch train.py
```
##### 基础API场景
如果使用基础API实现训练,想要启动单机多卡训练,需要对单机单卡的代码进行4处修改,具体如下:
```python
import paddle
import paddle.distributed as dist
paddle.disable_static()
train_dataset = paddle.vision.datasets.MNIST(mode='train')
test_dataset = paddle.vision.datasets.MNIST(mode='test')
# 加载训练集 batch_size 设为 64
train_loader = paddle.io.DataLoader(train_dataset, places=paddle.CPUPlace(), batch_size=64, shuffle=True)
def train():
# 第1处改动,初始化并行环境
dist.init_parallel_env()
# 第2处改动,增加paddle.DataParallel封装
net = paddle.DataParallel(LeNet())
epochs = 2
adam = paddle.optimizer.Adam(learning_rate=0.001, parameters=net.parameters())
# 用Adam作为优化函数
for epoch in range(epochs):
for batch_id, data in enumerate(train_loader()):
x_data = data[0]
y_data = data[1]
predicts = net(x_data) acc = paddle.metric.accuracy(predicts, y_data, k=2)
avg_acc = paddle.mean(acc)
loss = paddle.nn.functional.cross_entropy(predicts, y_data)
# 第3处改动,归一化loss
avg_loss = net.scale_loss(avg_loss)
avg_loss.backward()
# 第4处改动,同步梯度
net.apply_collective_grads()
if batch_id % 100 == 0:
print("epoch: {}, batch_id: {}, loss is: {}, acc is: {}".format(epoch, batch_id, avg_loss.numpy(), avg_acc.numpy()))
adam.step()
adam.clear_grad()
# 启动训练
train()
```
修改完后保存文件,然后使用跟高层API相同的启动方式即可
```bash
# 单机单卡启动,默认使用第0号卡
$ python train.py
# 单机多卡启动,默认使用当前可见的所有卡
$ python -m paddle.distributed.launch train.py
# 单机多卡启动,设置当前使用的第0号和第1号卡
$ python -m paddle.distributed.launch --selected_gpus '0,1' train.py
# 单机多卡启动,设置当前使用第0号和第1号卡
$ export CUDA_VISIABLE_DEVICES='0,1'
$ python -m paddle.distributed.launch train.py
```
#### 方式2、spawn启动
launch方式启动训练,以文件为单位启动多进程,需要用户在启动时调用`paddle.distributed.launch`,对于进程的管理要求较高。2.0版本增加了spawn启动方式,可以更好地控制进程,在日志打印、训练退出时更友好。
```bash
# 启动train多进程训练,默认使用所有可见的GPU卡
if __name__ == '__main__':
dist.spawn(train)
# 启动train函数2个进程训练,默认使用当前可见的前2张卡
if __name__ == '__main__':
dist.spawn(train, nprocs=2)
# 启动train函数2个进程训练,默认使用第4号和第5号卡
if __name__ == '__main__':
dist.spawn(train, nprocs=2, selelcted_gpus='4,5')
```
### 模型保存
Paddle保存的模型有两种格式,一种是训练格式,保存模型参数和优化器相关的状态,可用于恢复训练;一种是预测格式,保存预测的静态图网络结构以及参数,用于预测部署。
#### 高层API场景
高层API下用于预测部署的模型保存方法为:
```python
model = paddle.Model(Mnist())
# 预测格式,保存的模型可用于预测部署
model.save('mnist', training=False)
# 保存后可以得到预测部署所需要的模型
```
#### 基础API场景
动态图训练的模型,可以通过动静转换功能,转换为可部署的静态图模型,具体做法如下:
```python
import paddle
from paddle.jit import to_static
from paddle.static import InputSpec
class SimpleNet(paddle.nn.Layer):
def __init__(self):
super(SimpleNet, self).__init__()
self.linear = paddle.nn.Linear(10, 3)
# 第1处改动
# 通过InputSpec指定输入数据的形状,None表示可变长
# 通过to_static装饰器将动态图转换为静态图Program
@to_static(input_spec=[InputSpec(shape=[None, 10], name='x'), InputSpec(shape=[3], name='y')])
def forward(self, x, y):
out = self.linear(x)
out = out + y
return out
paddle.disable_static()
net = SimpleNet()
# 第2处改动
# 保存静态图模型,可用于预测部署
paddle.jit.save(net, './simple_net')
```
### 推理
推理库Paddle Inference的API做了升级,简化了写法,以及去掉了历史上冗余的概念。API的变化为纯增,原有API保持不变,但推荐新的API体系,旧API在后续版本会逐步删除。
#### C++ API
重要变化:
- 命名空间从 `paddle` 变更为 `paddle_infer`
- `PaddleTensor`, `PaddleBuf` 等被废弃,`ZeroCopyTensor` 变为默认 Tensor 类型,并更名为 `Tensor`
- 新增 `PredictorPool` 工具类简化多线程 predictor 的创建,后续也会增加更多周边工具
- `CreatePredictor` (原 `CreatePaddlePredictor`) 的返回值由 `unique_ptr` 变为 `shared_ptr` 以避免 Clone 后析构顺序出错的问题
API 变更
| 原有命名 | 现有命名 | 行为变化 |
| ---------------------------- | ---------------------------- | ----------------------------- |
| 头文件 `paddle_infer.h` | 无变化 | 包含旧接口,保持向后兼容 |
| 无 | `paddle_inference_api.h` | 新API,可以与旧接口并存 |
| `CreatePaddlePredictor` | `CreatePredictor` | 返回值变为 shared_ptr |
| `ZeroCopyTensor` | `Tensor` | 无 |
| `AnalysisConfig` | `Config` | 无 |
| `TensorRTConfig` | 废弃 | |
| `PaddleTensor` + `PaddleBuf` | 废弃 | |
| `Predictor::GetInputTensor` | `Predictor::GetInputHandle` | 无 |
| `Predictor::GetOutputTensor` | `Predictor::GetOutputHandle` | 无 |
| | `PredictorPool` | 简化创建多个 predictor 的支持 |
使用新 C++ API 的流程与之前完全一致,只有命名变化
```c++
#include "paddle_infernce_api.h"
using namespace paddle_infer;
Config config;
config.SetModel("xxx_model_dir");
auto predictor = CreatePredictor(config);
// Get the handles for the inputs and outputs of the model
auto input0 = predictor->GetInputHandle("X");
auto output0 = predictor->GetOutputHandle("Out");
for (...) {
// Assign data to input0
MyServiceSetData(input0);
predictor->Run();
// get data from the output0 handle
MyServiceGetData(output0);
}
```
#### Python API
Python API 的变更与 C++ 基本对应,会在2.0RC版发布。
## 附录
### 2.0转换工具
为了降级代码升级的成本,我们提供了转换工具,可以帮助将Paddle 1.8版本开发的代码,升级为2.0-beta的API。由于相比于Paddle 1.8版本,2.0-beta版本的API进行了大量的升级,包括API名称,参数名称,行为等。转换工具当前还不能覆盖所有的API升级;对于无法转换的API,转换工具会报错,提示用户手动升级。
https://github.com/PaddlePaddle/paddle1to2
对于转换工具没有覆盖的API,请查看官网的API文档,手动升级代码的API。
### 2.0文档教程
以下提供了2.0版本的一些示例教程:
您可以在官网[应用实践](https://www.paddlepaddle.org.cn/documentation/docs/zh/2.0-beta/tutorial/index_cn.html)栏目内进行在线浏览,也可以下载在这里提供的源代码:
https://github.com/PaddlePaddle/book/tree/develop/paddle2.0_docs
### 2.0API升级列表
- [Release Note](https://github.com/PaddlePaddle/Paddle/releases/tag/v2.0.0-beta0#)
- [API新增列表](https://github.com/PaddlePaddle/Paddle/wiki/Paddle-2.0beta-New-API-List)
- [API升级列表](https://github.com/PaddlePaddle/Paddle/wiki/Paddle-2.0beta-Upgraded-API-List)
...@@ -34,7 +34,7 @@ ...@@ -34,7 +34,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 21, "execution_count": 1,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -43,7 +43,7 @@ ...@@ -43,7 +43,7 @@
"'2.0.0-beta0'" "'2.0.0-beta0'"
] ]
}, },
"execution_count": 21, "execution_count": 1,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
...@@ -58,6 +58,9 @@ ...@@ -58,6 +58,9 @@
"import paddle\n", "import paddle\n",
"from paddle.nn import functional as F\n", "from paddle.nn import functional as F\n",
"\n", "\n",
"device = paddle.set_device('gpu')\n",
"paddle.disable_static(device)\n",
"\n",
"paddle.__version__" "paddle.__version__"
] ]
}, },
...@@ -173,7 +176,7 @@ ...@@ -173,7 +176,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 22, "execution_count": 2,
"metadata": { "metadata": {
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/",
...@@ -235,7 +238,7 @@ ...@@ -235,7 +238,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 3,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -388,7 +391,7 @@ ...@@ -388,7 +391,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 4,
"metadata": { "metadata": {
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/",
...@@ -464,7 +467,7 @@ ...@@ -464,7 +467,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 25, "execution_count": 5,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -527,7 +530,7 @@ ...@@ -527,7 +530,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 26, "execution_count": 6,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -587,7 +590,7 @@ ...@@ -587,7 +590,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 27, "execution_count": 7,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -648,7 +651,7 @@ ...@@ -648,7 +651,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": 8,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -724,7 +727,7 @@ ...@@ -724,7 +727,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 31, "execution_count": 9,
"metadata": { "metadata": {
"colab": { "colab": {
"base_uri": "https://localhost:8080/", "base_uri": "https://localhost:8080/",
...@@ -743,28 +746,28 @@ ...@@ -743,28 +746,28 @@
"--------------------------------------------------------------------------------\n", "--------------------------------------------------------------------------------\n",
" Layer (type) Input Shape Output Shape Param #\n", " Layer (type) Input Shape Output Shape Param #\n",
"================================================================================\n", "================================================================================\n",
" Conv2d-38 [-1, 3, 160, 160] [-1, 32, 80, 80] 896\n", " Conv2d-1 [-1, 3, 160, 160] [-1, 32, 80, 80] 896\n",
" BatchNorm2d-14 [-1, 32, 80, 80] [-1, 32, 80, 80] 128\n", " BatchNorm2d-1 [-1, 32, 80, 80] [-1, 32, 80, 80] 128\n",
" ReLU-14 [-1, 32, 80, 80] [-1, 32, 80, 80] 0\n", " ReLU-1 [-1, 32, 80, 80] [-1, 32, 80, 80] 0\n",
" ReLU-17 [-1, 256, 20, 20] [-1, 256, 20, 20] 0\n", " ReLU-4 [-1, 256, 20, 20] [-1, 256, 20, 20] 0\n",
" Conv2d-49 [-1, 128, 20, 20] [-1, 128, 20, 20] 1,152\n", " Conv2d-12 [-1, 128, 20, 20] [-1, 128, 20, 20] 1,152\n",
" Conv2d-50 [-1, 128, 20, 20] [-1, 256, 20, 20] 33,024\n", " Conv2d-13 [-1, 128, 20, 20] [-1, 256, 20, 20] 33,024\n",
"SeparableConv2d-17 [-1, 128, 20, 20] [-1, 256, 20, 20] 0\n", "SeparableConv2d-5 [-1, 128, 20, 20] [-1, 256, 20, 20] 0\n",
" BatchNorm2d-17 [-1, 256, 20, 20] [-1, 256, 20, 20] 1,024\n", " BatchNorm2d-4 [-1, 256, 20, 20] [-1, 256, 20, 20] 1,024\n",
" Conv2d-51 [-1, 256, 20, 20] [-1, 256, 20, 20] 2,304\n", " Conv2d-14 [-1, 256, 20, 20] [-1, 256, 20, 20] 2,304\n",
" Conv2d-52 [-1, 256, 20, 20] [-1, 256, 20, 20] 65,792\n", " Conv2d-15 [-1, 256, 20, 20] [-1, 256, 20, 20] 65,792\n",
"SeparableConv2d-18 [-1, 256, 20, 20] [-1, 256, 20, 20] 0\n", "SeparableConv2d-6 [-1, 256, 20, 20] [-1, 256, 20, 20] 0\n",
" MaxPool2d-9 [-1, 256, 20, 20] [-1, 256, 10, 10] 0\n", " MaxPool2d-3 [-1, 256, 20, 20] [-1, 256, 10, 10] 0\n",
" Conv2d-53 [-1, 128, 20, 20] [-1, 256, 10, 10] 33,024\n", " Conv2d-16 [-1, 128, 20, 20] [-1, 256, 10, 10] 33,024\n",
" Encoder-9 [-1, 128, 20, 20] [-1, 256, 10, 10] 0\n", " Encoder-3 [-1, 128, 20, 20] [-1, 256, 10, 10] 0\n",
" ReLU-21 [-1, 32, 80, 80] [-1, 32, 80, 80] 0\n", " ReLU-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 0\n",
"ConvTranspose2d-17 [-1, 64, 80, 80] [-1, 32, 80, 80] 18,464\n", "ConvTranspose2d-7 [-1, 64, 80, 80] [-1, 32, 80, 80] 18,464\n",
" BatchNorm2d-21 [-1, 32, 80, 80] [-1, 32, 80, 80] 128\n", " BatchNorm2d-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 128\n",
"ConvTranspose2d-18 [-1, 32, 80, 80] [-1, 32, 80, 80] 9,248\n", "ConvTranspose2d-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 9,248\n",
" Upsample-8 [-1, 64, 80, 80] [-1, 64, 160, 160] 0\n", " Upsample-4 [-1, 64, 80, 80] [-1, 64, 160, 160] 0\n",
" Conv2d-57 [-1, 64, 160, 160] [-1, 32, 160, 160] 2,080\n", " Conv2d-20 [-1, 64, 160, 160] [-1, 32, 160, 160] 2,080\n",
" Decoder-9 [-1, 64, 80, 80] [-1, 32, 160, 160] 0\n", " Decoder-4 [-1, 64, 80, 80] [-1, 32, 160, 160] 0\n",
" Conv2d-58 [-1, 32, 160, 160] [-1, 4, 160, 160] 1,156\n", " Conv2d-21 [-1, 32, 160, 160] [-1, 4, 160, 160] 1,156\n",
"================================================================================\n", "================================================================================\n",
"Total params: 168,420\n", "Total params: 168,420\n",
"Trainable params: 167,140\n", "Trainable params: 167,140\n",
...@@ -784,7 +787,7 @@ ...@@ -784,7 +787,7 @@
"{'total_params': 168420, 'trainable_params': 167140}" "{'total_params': 168420, 'trainable_params': 167140}"
] ]
}, },
"execution_count": 31, "execution_count": 9,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
...@@ -808,34 +811,6 @@ ...@@ -808,34 +811,6 @@
"## 5.模型训练" "## 5.模型训练"
] ]
}, },
{
"cell_type": "markdown",
"metadata": {
"colab_type": "text",
"id": "8Sskbyz58X4J"
},
"source": [
"### 5.1 配置信息\n",
"\n",
"定义训练BATCH_SIZE、训练轮次和计算设备等信息。"
]
},
{
"cell_type": "code",
"execution_count": 18,
"metadata": {
"colab": {},
"colab_type": "code",
"id": "4fSkTiRB8OpP"
},
"outputs": [],
"source": [
"BATCH_SIZE = 32\n",
"EPOCHS = 15\n",
"device = paddle.set_device('gpu')\n",
"paddle.disable_static(device)"
]
},
{ {
"cell_type": "markdown", "cell_type": "markdown",
"metadata": { "metadata": {
...@@ -843,14 +818,14 @@ ...@@ -843,14 +818,14 @@
"id": "x_vaedRa8eoy" "id": "x_vaedRa8eoy"
}, },
"source": [ "source": [
"### 5.3 自定义Loss\n", "### 5.1 自定义Loss\n",
"\n", "\n",
"在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。" "在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 19, "execution_count": 10,
"metadata": { "metadata": {
"colab": {}, "colab": {},
"colab_type": "code", "colab_type": "code",
...@@ -877,7 +852,7 @@ ...@@ -877,7 +852,7 @@
"id": "rj6MPPMkJIdZ" "id": "rj6MPPMkJIdZ"
}, },
"source": [ "source": [
"### 5.4 启动模型训练\n", "### 5.2 启动模型训练\n",
"\n", "\n",
"使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。" "使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。"
] ]
...@@ -903,12 +878,12 @@ ...@@ -903,12 +878,12 @@
" epsilon=1e-07, \n", " epsilon=1e-07, \n",
" centered=False,\n", " centered=False,\n",
" parameters=model.parameters())\n", " parameters=model.parameters())\n",
"model = paddle.Model(PetModel(num_classes))\n", "model = paddle.Model(PetNet(num_classes))\n",
"model.prepare(optim, SoftmaxWithCrossEntropy())\n", "model.prepare(optim, SoftmaxWithCrossEntropy())\n",
"model.fit(train_dataset, \n", "model.fit(train_dataset, \n",
" val_dataset, \n", " val_dataset, \n",
" epochs=EPOCHS, \n", " epochs=15, \n",
" batch_size=BATCH_SIZE)" " batch_size=32)"
] ]
}, },
{ {
......
...@@ -26,6 +26,9 @@ ...@@ -26,6 +26,9 @@
import paddle import paddle
from paddle.nn import functional as F from paddle.nn import functional as F
device = paddle.set_device('gpu')
paddle.disable_static(device)
paddle.__version__ paddle.__version__
...@@ -326,7 +329,7 @@ DataLoader(多进程数据集加载)。 ...@@ -326,7 +329,7 @@ DataLoader(多进程数据集加载)。
.. image:: https://github.com/PaddlePaddle/FluidDoc/blob/develop/doc/paddle/tutorial/cv_case/image_segmentation/pets_image_segmentation_U_Net_like_files/pets_image_segmentation_U_Net_like_001.png?raw=true .. image:: https://raw.githubusercontent.com/PaddlePaddle/FluidDoc/develop/doc/paddle/tutorial/cv_case/image_segmentation/pets_image_segmentation_U_Net_like_files/pets_image_segmentation_U_Net_like_001.png
4.模型组网 4.模型组网
...@@ -551,28 +554,28 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C ...@@ -551,28 +554,28 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C
-------------------------------------------------------------------------------- --------------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param # Layer (type) Input Shape Output Shape Param #
================================================================================ ================================================================================
Conv2d-38 [-1, 3, 160, 160] [-1, 32, 80, 80] 896 Conv2d-1 [-1, 3, 160, 160] [-1, 32, 80, 80] 896
BatchNorm2d-14 [-1, 32, 80, 80] [-1, 32, 80, 80] 128 BatchNorm2d-1 [-1, 32, 80, 80] [-1, 32, 80, 80] 128
ReLU-14 [-1, 32, 80, 80] [-1, 32, 80, 80] 0 ReLU-1 [-1, 32, 80, 80] [-1, 32, 80, 80] 0
ReLU-17 [-1, 256, 20, 20] [-1, 256, 20, 20] 0 ReLU-4 [-1, 256, 20, 20] [-1, 256, 20, 20] 0
Conv2d-49 [-1, 128, 20, 20] [-1, 128, 20, 20] 1,152 Conv2d-12 [-1, 128, 20, 20] [-1, 128, 20, 20] 1,152
Conv2d-50 [-1, 128, 20, 20] [-1, 256, 20, 20] 33,024 Conv2d-13 [-1, 128, 20, 20] [-1, 256, 20, 20] 33,024
SeparableConv2d-17 [-1, 128, 20, 20] [-1, 256, 20, 20] 0 SeparableConv2d-5 [-1, 128, 20, 20] [-1, 256, 20, 20] 0
BatchNorm2d-17 [-1, 256, 20, 20] [-1, 256, 20, 20] 1,024 BatchNorm2d-4 [-1, 256, 20, 20] [-1, 256, 20, 20] 1,024
Conv2d-51 [-1, 256, 20, 20] [-1, 256, 20, 20] 2,304 Conv2d-14 [-1, 256, 20, 20] [-1, 256, 20, 20] 2,304
Conv2d-52 [-1, 256, 20, 20] [-1, 256, 20, 20] 65,792 Conv2d-15 [-1, 256, 20, 20] [-1, 256, 20, 20] 65,792
SeparableConv2d-18 [-1, 256, 20, 20] [-1, 256, 20, 20] 0 SeparableConv2d-6 [-1, 256, 20, 20] [-1, 256, 20, 20] 0
MaxPool2d-9 [-1, 256, 20, 20] [-1, 256, 10, 10] 0 MaxPool2d-3 [-1, 256, 20, 20] [-1, 256, 10, 10] 0
Conv2d-53 [-1, 128, 20, 20] [-1, 256, 10, 10] 33,024 Conv2d-16 [-1, 128, 20, 20] [-1, 256, 10, 10] 33,024
Encoder-9 [-1, 128, 20, 20] [-1, 256, 10, 10] 0 Encoder-3 [-1, 128, 20, 20] [-1, 256, 10, 10] 0
ReLU-21 [-1, 32, 80, 80] [-1, 32, 80, 80] 0 ReLU-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 0
ConvTranspose2d-17 [-1, 64, 80, 80] [-1, 32, 80, 80] 18,464 ConvTranspose2d-7 [-1, 64, 80, 80] [-1, 32, 80, 80] 18,464
BatchNorm2d-21 [-1, 32, 80, 80] [-1, 32, 80, 80] 128 BatchNorm2d-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 128
ConvTranspose2d-18 [-1, 32, 80, 80] [-1, 32, 80, 80] 9,248 ConvTranspose2d-8 [-1, 32, 80, 80] [-1, 32, 80, 80] 9,248
Upsample-8 [-1, 64, 80, 80] [-1, 64, 160, 160] 0 Upsample-4 [-1, 64, 80, 80] [-1, 64, 160, 160] 0
Conv2d-57 [-1, 64, 160, 160] [-1, 32, 160, 160] 2,080 Conv2d-20 [-1, 64, 160, 160] [-1, 32, 160, 160] 2,080
Decoder-9 [-1, 64, 80, 80] [-1, 32, 160, 160] 0 Decoder-4 [-1, 64, 80, 80] [-1, 32, 160, 160] 0
Conv2d-58 [-1, 32, 160, 160] [-1, 4, 160, 160] 1,156 Conv2d-21 [-1, 32, 160, 160] [-1, 4, 160, 160] 1,156
================================================================================ ================================================================================
Total params: 168,420 Total params: 168,420
Trainable params: 167,140 Trainable params: 167,140
...@@ -597,19 +600,7 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C ...@@ -597,19 +600,7 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C
5.模型训练 5.模型训练
---------- ----------
5.1 配置信息 5.1 自定义Loss
~~~~~~~~~~~~
定义训练BATCH_SIZE、训练轮次和计算设备等信息。
.. code:: ipython3
BATCH_SIZE = 32
EPOCHS = 15
device = paddle.set_device('gpu')
paddle.disable_static(device)
5.3 自定义Loss
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。 在这个任务中我们使用SoftmaxWithCrossEntropy损失函数来做计算,飞桨中有functional形式的API,这里我们做一个自定义操作,实现一个Class形式API放到模型训练中使用。没有直接使用CrossEntropyLoss的原因主要是对计算维度的自定义需求,本次需要进行softmax计算的维度是1,不是默认的最后一维,所以我们采用上面提到的损失函数,通过axis参数来指定softmax计算维度。
...@@ -627,7 +618,7 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C ...@@ -627,7 +618,7 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C
axis=1) axis=1)
return paddle.mean(loss) return paddle.mean(loss)
5.4 启动模型训练 5.2 启动模型训练
~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~
使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。 使用模型代码进行Model实例生成,使用prepare接口定义优化器、损失函数和评价指标等信息,用于后续训练使用。在所有初步配置完成后,调用fit接口开启训练执行过程,调用fit时只需要将前面定义好的训练数据集、测试数据集、训练轮次(Epoch)和批次大小(batch_size)配置好即可。
...@@ -640,12 +631,12 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C ...@@ -640,12 +631,12 @@ Layer类,整个过程是把\ ``filter_size * filter_size * num_filters``\ 的C
epsilon=1e-07, epsilon=1e-07,
centered=False, centered=False,
parameters=model.parameters()) parameters=model.parameters())
model = paddle.Model(PetModel(num_classes)) model = paddle.Model(PetNet(num_classes))
model.prepare(optim, SoftmaxWithCrossEntropy()) model.prepare(optim, SoftmaxWithCrossEntropy())
model.fit(train_dataset, model.fit(train_dataset,
val_dataset, val_dataset,
epochs=EPOCHS, epochs=15,
batch_size=BATCH_SIZE) batch_size=32)
6.模型预测 6.模型预测
---------- ----------
......
...@@ -31,24 +31,22 @@ ...@@ -31,24 +31,22 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 8,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
"data": { "name": "stdout",
"text/plain": [ "output_type": "stream",
"'2.0.0-beta0'" "text": [
] "2.0.0-beta0\n"
}, ]
"execution_count": 1,
"metadata": {},
"output_type": "execute_result"
} }
], ],
"source": [ "source": [
"import paddle\n", "import paddle\n",
"\n", "\n",
"paddle.__version__" "print(paddle.__version__)\n",
"paddle.disable_static()"
] ]
}, },
{ {
...@@ -71,7 +69,7 @@ ...@@ -71,7 +69,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 9,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -90,7 +88,7 @@ ...@@ -90,7 +88,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 35, "execution_count": 10,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -113,7 +111,7 @@ ...@@ -113,7 +111,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 36, "execution_count": 11,
"metadata": { "metadata": {
"scrolled": true "scrolled": true
}, },
...@@ -123,15 +121,15 @@ ...@@ -123,15 +121,15 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"Epoch 1/5\n", "Epoch 1/5\n",
"step 1875/1875 [==============================] - loss: 0.2571 - acc: 0.9037 - 10ms/step \n", "step 1875/1875 [==============================] - loss: 0.2250 - acc: 0.9025 - 9ms/step \n",
"Epoch 2/5\n", "Epoch 2/5\n",
"step 1875/1875 [==============================] - loss: 0.1880 - acc: 0.9458 - 14ms/step \n", "step 1875/1875 [==============================] - loss: 0.0969 - acc: 0.9462 - 13ms/step \n",
"Epoch 3/5\n", "Epoch 3/5\n",
"step 1875/1875 [==============================] - loss: 0.0279 - acc: 0.9549 - 11ms/step \n", "step 1875/1875 [==============================] - loss: 0.1035 - acc: 0.9550 - 12ms/step \n",
"Epoch 4/5\n", "Epoch 4/5\n",
"step 1875/1875 [==============================] - loss: 0.0505 - acc: 0.9608 - 13ms/step \n", "step 1875/1875 [==============================] - loss: 0.0316 - acc: 0.9603 - 12ms/step \n",
"Epoch 5/5\n", "Epoch 5/5\n",
"step 1875/1875 [==============================] - loss: 0.2253 - acc: 0.9646 - 12ms/step \n" "step 1875/1875 [==============================] - loss: 0.1771 - acc: 0.9637 - 12ms/step \n"
] ]
} }
], ],
...@@ -189,9 +187,7 @@ ...@@ -189,9 +187,7 @@
"source": [ "source": [
"那么初步训练得到的模型效果在97%附近,我们可以进一步通过调整其中的训练参数来提升我们的模型精度。\n", "那么初步训练得到的模型效果在97%附近,我们可以进一步通过调整其中的训练参数来提升我们的模型精度。\n",
"\n", "\n",
"至此我们可以知道如何通过飞桨的几个简单API来快速完成一个深度学习任务,大家可以针对自己的需求来更换其中的代码,如果需要使用自己的数据集,那么可以更换数据集加载部分程序,如果需要替换模型,那么可以更改模型代码实现等等。我们也为大家提供了很多其他场景的示例代码来教大家如何使用我们的飞桨API,大家可以查看下面的链接或通过页面导航来查看自己感兴趣的部分。\n", "至此我们可以知道如何通过飞桨的几个简单API来快速完成一个深度学习任务,大家可以针对自己的需求来更换其中的代码,如果需要使用自己的数据集,那么可以更换数据集加载部分程序,如果需要替换模型,那么可以更改模型代码实现等等。我们也为大家提供了很多其他场景的示例代码来教大家如何使用我们的飞桨API,大家可以查看下面的链接或通过页面导航来查看自己感兴趣的部分。"
"\n",
"TODO:补充其他示例教程的快速链接。"
] ]
} }
], ],
......
...@@ -19,15 +19,13 @@ ...@@ -19,15 +19,13 @@
import paddle import paddle
paddle.__version__ print(paddle.__version__)
paddle.disable_static()
.. parsed-literal:: .. parsed-literal::
'2.0.0-beta0' 2.0.0-beta0
3. 实践一个手写数字识别任务 3. 实践一个手写数字识别任务
...@@ -91,15 +89,15 @@ ...@@ -91,15 +89,15 @@
.. parsed-literal:: .. parsed-literal::
Epoch 1/5 Epoch 1/5
step 1875/1875 [==============================] - loss: 0.2571 - acc: 0.9037 - 10ms/step step 1875/1875 [==============================] - loss: 0.2250 - acc: 0.9025 - 9ms/step
Epoch 2/5 Epoch 2/5
step 1875/1875 [==============================] - loss: 0.1880 - acc: 0.9458 - 14ms/step step 1875/1875 [==============================] - loss: 0.0969 - acc: 0.9462 - 13ms/step
Epoch 3/5 Epoch 3/5
step 1875/1875 [==============================] - loss: 0.0279 - acc: 0.9549 - 11ms/step step 1875/1875 [==============================] - loss: 0.1035 - acc: 0.9550 - 12ms/step
Epoch 4/5 Epoch 4/5
step 1875/1875 [==============================] - loss: 0.0505 - acc: 0.9608 - 13ms/step step 1875/1875 [==============================] - loss: 0.0316 - acc: 0.9603 - 12ms/step
Epoch 5/5 Epoch 5/5
step 1875/1875 [==============================] - loss: 0.2253 - acc: 0.9646 - 12ms/step step 1875/1875 [==============================] - loss: 0.1771 - acc: 0.9637 - 12ms/step
3.4 模型评估 3.4 模型评估
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
"\n", "\n",
"## 1. 简介\n", "## 1. 简介\n",
"\n", "\n",
"飞桨2.0全新推出高层API,是对飞桨API的进一步封装与升级,提供了更加简洁易用的API,进一步提升了飞桨的易学易用性,并增强飞桨的功能。\n", "飞桨框架2.0全新推出高层API,是对飞桨API的进一步封装与升级,提供了更加简洁易用的API,进一步提升了飞桨的易学易用性,并增强飞桨的功能。\n",
"\n", "\n",
"飞桨高层API面向从深度学习小白到资深开发者的所有人群,对于AI初学者来说,使用高层API可以简单快速的构建深度学习项目,对于资深开发者来说,可以快速完成算法迭代。\n", "飞桨高层API面向从深度学习小白到资深开发者的所有人群,对于AI初学者来说,使用高层API可以简单快速的构建深度学习项目,对于资深开发者来说,可以快速完成算法迭代。\n",
"\n", "\n",
...@@ -36,7 +36,7 @@ ...@@ -36,7 +36,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 1, "execution_count": 2,
"metadata": {}, "metadata": {},
"outputs": [ "outputs": [
{ {
...@@ -45,7 +45,7 @@ ...@@ -45,7 +45,7 @@
"'2.0.0-beta0'" "'2.0.0-beta0'"
] ]
}, },
"execution_count": 1, "execution_count": 2,
"metadata": {}, "metadata": {},
"output_type": "execute_result" "output_type": "execute_result"
} }
...@@ -55,6 +55,9 @@ ...@@ -55,6 +55,9 @@
"import paddle.vision as vision\n", "import paddle.vision as vision\n",
"import paddle.text as text\n", "import paddle.text as text\n",
"\n", "\n",
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"\n",
"paddle.__version__" "paddle.__version__"
] ]
}, },
...@@ -90,7 +93,7 @@ ...@@ -90,7 +93,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 5, "execution_count": 3,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
...@@ -100,7 +103,7 @@ ...@@ -100,7 +103,7 @@
"output_type": "stream", "output_type": "stream",
"text": [ "text": [
"视觉相关数据集: ['DatasetFolder', 'ImageFolder', 'MNIST', 'Flowers', 'Cifar10', 'Cifar100', 'VOC2012']\n", "视觉相关数据集: ['DatasetFolder', 'ImageFolder', 'MNIST', 'Flowers', 'Cifar10', 'Cifar100', 'VOC2012']\n",
"自然语言相关数据集: ['Conll05st', 'Imdb', 'Imikolov', 'Movielens', 'MovieReviews', 'UCIHousing', 'WMT14', 'WMT16']\n" "自然语言相关数据集: ['Conll05st', 'Imdb', 'Imikolov', 'Movielens', 'UCIHousing', 'WMT14', 'WMT16']\n"
] ]
} }
], ],
...@@ -118,7 +121,7 @@ ...@@ -118,7 +121,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 24, "execution_count": 18,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -140,7 +143,7 @@ ...@@ -140,7 +143,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 23, "execution_count": 5,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
...@@ -207,8 +210,8 @@ ...@@ -207,8 +210,8 @@
" return len(self.data)\n", " return len(self.data)\n",
"\n", "\n",
"# 测试定义的数据集\n", "# 测试定义的数据集\n",
"train_dataset = MyDataset(mode='train')\n", "train_dataset_2 = MyDataset(mode='train')\n",
"val_dataset = MyDataset(mode='test')\n", "val_dataset_2 = MyDataset(mode='test')\n",
"\n", "\n",
"print('=============train dataset=============')\n", "print('=============train dataset=============')\n",
"for data, label in train_dataset:\n", "for data, label in train_dataset:\n",
...@@ -232,7 +235,7 @@ ...@@ -232,7 +235,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 6,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -243,7 +246,7 @@ ...@@ -243,7 +246,7 @@
"transform = Compose([ColorJitter(), Resize(size=100)])\n", "transform = Compose([ColorJitter(), Resize(size=100)])\n",
"\n", "\n",
"# 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用\n", "# 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用\n",
"train_dataset = vision.datasets.MNIST(mode='train', transform=transform)" "train_dataset_3 = vision.datasets.MNIST(mode='train', transform=transform)"
] ]
}, },
{ {
...@@ -257,7 +260,7 @@ ...@@ -257,7 +260,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 7,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -316,7 +319,7 @@ ...@@ -316,7 +319,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 28, "execution_count": 12,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -340,7 +343,7 @@ ...@@ -340,7 +343,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 31,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -364,7 +367,7 @@ ...@@ -364,7 +367,7 @@
"\n", "\n",
" return y\n", " return y\n",
"\n", "\n",
"mnist = Mnist()" "mnist_2 = Mnist()"
] ]
}, },
{ {
...@@ -380,14 +383,12 @@ ...@@ -380,14 +383,12 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 32,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"# 场景1:动态图模式\n", "# 场景1:动态图模式\n",
"\n", "\n",
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"# 使用GPU训练\n", "# 使用GPU训练\n",
"paddle.set_device('gpu')\n", "paddle.set_device('gpu')\n",
"# 模型封装\n", "# 模型封装\n",
...@@ -412,9 +413,45 @@ ...@@ -412,9 +413,45 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 33,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--------------------------------------------------------------------------------\n",
" Layer (type) Input Shape Output Shape Param #\n",
"================================================================================\n",
" Flatten-57509 [-1, 1, 28, 28] [-1, 784] 0\n",
" Linear-7 [-1, 784] [-1, 512] 401,920\n",
" ReLU-4 [-1, 512] [-1, 512] 0\n",
" Dropout-4 [-1, 512] [-1, 512] 0\n",
" Linear-8 [-1, 512] [-1, 10] 5,130\n",
"================================================================================\n",
"Total params: 407,050\n",
"Trainable params: 407,050\n",
"Non-trainable params: 0\n",
"--------------------------------------------------------------------------------\n",
"Input size (MB): 0.00\n",
"Forward/backward pass size (MB): 0.02\n",
"Params size (MB): 1.55\n",
"Estimated Total Size (MB): 1.57\n",
"--------------------------------------------------------------------------------\n",
"\n"
]
},
{
"data": {
"text/plain": [
"{'total_params': 407050, 'trainable_params': 407050}"
]
},
"execution_count": 33,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [ "source": [
"model.summary((1, 28, 28))" "model.summary((1, 28, 28))"
] ]
...@@ -428,9 +465,45 @@ ...@@ -428,9 +465,45 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 34,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"--------------------------------------------------------------------------------\n",
" Layer (type) Input Shape Output Shape Param #\n",
"================================================================================\n",
" Flatten-57508 [-1, 1, 28, 28] [-1, 784] 0\n",
" Linear-5 [-1, 784] [-1, 512] 401,920\n",
" ReLU-3 [-1, 512] [-1, 512] 0\n",
" Dropout-3 [-1, 512] [-1, 512] 0\n",
" Linear-6 [-1, 512] [-1, 10] 5,130\n",
"================================================================================\n",
"Total params: 407,050\n",
"Trainable params: 407,050\n",
"Non-trainable params: 0\n",
"--------------------------------------------------------------------------------\n",
"Input size (MB): 0.00\n",
"Forward/backward pass size (MB): 0.02\n",
"Params size (MB): 1.55\n",
"Estimated Total Size (MB): 1.57\n",
"--------------------------------------------------------------------------------\n",
"\n"
]
},
{
"data": {
"text/plain": [
"{'total_params': 407050, 'trainable_params': 407050}"
]
},
"execution_count": 34,
"metadata": {},
"output_type": "execute_result"
}
],
"source": [ "source": [
"paddle.summary(mnist, (1, 28, 28))" "paddle.summary(mnist, (1, 28, 28))"
] ]
...@@ -456,7 +529,7 @@ ...@@ -456,7 +529,7 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 35,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
...@@ -475,9 +548,36 @@ ...@@ -475,9 +548,36 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 36,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"step 1875/1875 [==============================] - loss: 0.1600 - acc: 0.9022 - 10ms/step \n",
"Epoch 2/10\n",
"step 1875/1875 [==============================] - loss: 0.0455 - acc: 0.9461 - 12ms/step \n",
"Epoch 3/10\n",
"step 1875/1875 [==============================] - loss: 0.1429 - acc: 0.9544 - 19ms/step \n",
"Epoch 4/10\n",
"step 1875/1875 [==============================] - loss: 0.0197 - acc: 0.9601 - 22ms/step \n",
"Epoch 5/10\n",
"step 1875/1875 [==============================] - loss: 0.1762 - acc: 0.9644 - 25ms/step \n",
"Epoch 6/10\n",
"step 1875/1875 [==============================] - loss: 0.1304 - acc: 0.9667 - 22ms/step \n",
"Epoch 7/10\n",
"step 1875/1875 [==============================] - loss: 0.0133 - acc: 0.9682 - 22ms/step \n",
"Epoch 8/10\n",
"step 1875/1875 [==============================] - loss: 0.0097 - acc: 0.9705 - 19ms/step \n",
"Epoch 9/10\n",
"step 1875/1875 [==============================] - loss: 3.1264e-04 - acc: 0.9716 - 23ms/step \n",
"Epoch 10/10\n",
"step 1875/1875 [==============================] - loss: 0.0767 - acc: 0.9729 - 13ms/step \n"
]
}
],
"source": [ "source": [
"# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式\n", "# 启动模型训练,指定训练数据集,设置训练轮次,设置每次数据集计算的批次大小,设置日志格式\n",
"model.fit(train_dataset, \n", "model.fit(train_dataset, \n",
...@@ -497,14 +597,39 @@ ...@@ -497,14 +597,39 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": 30, "execution_count": 20,
"metadata": { "metadata": {
"tags": [] "tags": []
}, },
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Epoch 1/10\n",
"step 1875/1875 [==============================] - loss: 0.0490 - acc: 0.9741 - 6ms/step \n",
"Epoch 2/10\n",
"step 1875/1875 [==============================] - loss: 0.1384 - acc: 0.9760 - 7ms/step \n",
"Epoch 3/10\n",
"step 1875/1875 [==============================] - loss: 0.0929 - acc: 0.9767 - 7ms/step \n",
"Epoch 4/10\n",
"step 1875/1875 [==============================] - loss: 0.0190 - acc: 0.9772 - 6ms/step \n",
"Epoch 5/10\n",
"step 1875/1875 [==============================] - loss: 0.0862 - acc: 0.9774 - 7ms/step \n",
"Epoch 6/10\n",
"step 1875/1875 [==============================] - loss: 0.0748 - acc: 0.9785 - 8ms/step \n",
"Epoch 7/10\n",
"step 1875/1875 [==============================] - loss: 0.0039 - acc: 0.9798 - 17ms/step \n",
"Epoch 8/10\n",
"step 1875/1875 [==============================] - loss: 0.0037 - acc: 0.9808 - 11ms/step \n",
"Epoch 9/10\n",
"step 1875/1875 [==============================] - loss: 0.0013 - acc: 0.9800 - 8ms/step \n",
"Epoch 10/10\n",
"step 1875/1875 [==============================] - loss: 0.0376 - acc: 0.9810 - 8ms/step \n"
]
}
],
"source": [ "source": [
"# 启动动态图训练模式\n",
"paddle.disable_static()\n",
"\n", "\n",
"# 使用GPU训练\n", "# 使用GPU训练\n",
"paddle.set_device('gpu')\n", "paddle.set_device('gpu')\n",
...@@ -530,17 +655,13 @@ ...@@ -530,17 +655,13 @@
"source": [ "source": [
"### 5.2 单机多卡\n", "### 5.2 单机多卡\n",
"\n", "\n",
"对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用`paddle.distributed.launch`启动单机单卡的程序即可。" "对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用`paddle.distributed.launch`启动单机单卡的程序即可。\n",
] "\n",
}, "```bash\n",
{ "$ python -m paddle.distributed.launch train.py\n",
"cell_type": "code", "```\n",
"execution_count": null, "\n",
"metadata": {}, "train.py里面包含的就是单机单卡代码"
"outputs": [],
"source": [
"# train.py里面包含的就是单机单卡代码\n",
"python -m paddle.distributed.launch train.py"
] ]
}, },
{ {
...@@ -810,9 +931,19 @@ ...@@ -810,9 +931,19 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 21,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Eval begin...\n",
"step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9801 - 2ms/step \n",
"Eval samples: 10000\n"
]
}
],
"source": [ "source": [
"result = model.evaluate(val_dataset, verbose=1)" "result = model.evaluate(val_dataset, verbose=1)"
] ]
...@@ -834,9 +965,19 @@ ...@@ -834,9 +965,19 @@
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 22,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [
{
"name": "stdout",
"output_type": "stream",
"text": [
"Predict begin...\n",
"step 10000/10000 [==============================] - 4ms/step \n",
"Predict samples: 10000\n"
]
}
],
"source": [ "source": [
"pred_result = model.predict(val_dataset)" "pred_result = model.predict(val_dataset)"
] ]
...@@ -866,17 +1007,40 @@ ...@@ -866,17 +1007,40 @@
"\n", "\n",
"### 8.1 模型存储\n", "### 8.1 模型存储\n",
"\n", "\n",
"模型训练和验证达到我们的预期后,可以使用`save`接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。" "模型训练和验证达到我们的预期后,可以使用`save`接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。\n",
"\n",
"需要注意的是,在动态图模式训练时保存推理模型的参数文件和模型文件,需要在forward成员函数上添加@paddle.jit.to_static装饰器,参考下面的例子:\n",
"\n",
"```python\n",
"class Mnist(paddle.nn.Layer):\n",
" def __init__(self):\n",
" super(Mnist, self).__init__()\n",
"\n",
" self.flatten = paddle.nn.Flatten()\n",
" self.linear_1 = paddle.nn.Linear(784, 512)\n",
" self.linear_2 = paddle.nn.Linear(512, 10)\n",
" self.relu = paddle.nn.ReLU()\n",
" self.dropout = paddle.nn.Dropout(0.2)\n",
"\n",
" @paddle.jit.to_static\n",
" def forward(self, inputs):\n",
" y = self.flatten(inputs)\n",
" y = self.linear_1(y)\n",
" y = self.relu(y)\n",
" y = self.dropout(y)\n",
" y = self.linear_2(y)\n",
"\n",
" return y\n",
"```"
] ]
}, },
{ {
"cell_type": "code", "cell_type": "code",
"execution_count": null, "execution_count": 24,
"metadata": {}, "metadata": {},
"outputs": [], "outputs": [],
"source": [ "source": [
"# 保存用于推理部署的模型(training=False)\n", "model.save('~/model/mnist')"
"model.save('~/model/mnist', training=False)"
] ]
}, },
{ {
......
...@@ -38,6 +38,9 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -38,6 +38,9 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
import paddle.vision as vision import paddle.vision as vision
import paddle.text as text import paddle.text as text
# 启动动态图训练模式
paddle.disable_static()
paddle.__version__ paddle.__version__
...@@ -81,7 +84,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -81,7 +84,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
.. parsed-literal:: .. parsed-literal::
视觉相关数据集: ['DatasetFolder', 'ImageFolder', 'MNIST', 'Flowers', 'Cifar10', 'Cifar100', 'VOC2012'] 视觉相关数据集: ['DatasetFolder', 'ImageFolder', 'MNIST', 'Flowers', 'Cifar10', 'Cifar100', 'VOC2012']
自然语言相关数据集: ['Conll05st', 'Imdb', 'Imikolov', 'Movielens', 'MovieReviews', 'UCIHousing', 'WMT14', 'WMT16'] 自然语言相关数据集: ['Conll05st', 'Imdb', 'Imikolov', 'Movielens', 'UCIHousing', 'WMT14', 'WMT16']
这里我们是加载一个手写数字识别的数据集,用\ ``mode``\ 来标识是训练数据还是测试数据集。数据集接口会自动从远端下载数据集到本机缓存目录\ ``~/.cache/paddle/dataset``\ 这里我们是加载一个手写数字识别的数据集,用\ ``mode``\ 来标识是训练数据还是测试数据集。数据集接口会自动从远端下载数据集到本机缓存目录\ ``~/.cache/paddle/dataset``\
...@@ -145,8 +148,8 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -145,8 +148,8 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
return len(self.data) return len(self.data)
# 测试定义的数据集 # 测试定义的数据集
train_dataset = MyDataset(mode='train') train_dataset_2 = MyDataset(mode='train')
val_dataset = MyDataset(mode='test') val_dataset_2 = MyDataset(mode='test')
print('=============train dataset=============') print('=============train dataset=============')
for data, label in train_dataset: for data, label in train_dataset:
...@@ -188,7 +191,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -188,7 +191,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
transform = Compose([ColorJitter(), Resize(size=100)]) transform = Compose([ColorJitter(), Resize(size=100)])
# 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用 # 通过transform参数传递定义好的数据增项方法即可完成对自带数据集的应用
train_dataset = vision.datasets.MNIST(mode='train', transform=transform) train_dataset_3 = vision.datasets.MNIST(mode='train', transform=transform)
3.3.2 自定义数据集 3.3.2 自定义数据集
^^^^^^^^^^^^^^^^^^ ^^^^^^^^^^^^^^^^^^
...@@ -284,7 +287,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -284,7 +287,7 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
return y return y
mnist = Mnist() mnist_2 = Mnist()
4.3 模型封装 4.3 模型封装
~~~~~~~~~~~~ ~~~~~~~~~~~~
...@@ -297,8 +300,6 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -297,8 +300,6 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
# 场景1:动态图模式 # 场景1:动态图模式
# 启动动态图训练模式
paddle.disable_static()
# 使用GPU训练 # 使用GPU训练
paddle.set_device('gpu') paddle.set_device('gpu')
# 模型封装 # 模型封装
...@@ -320,12 +321,76 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -320,12 +321,76 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
model.summary((1, 28, 28)) model.summary((1, 28, 28))
.. parsed-literal::
--------------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
================================================================================
Flatten-57509 [-1, 1, 28, 28] [-1, 784] 0
Linear-7 [-1, 784] [-1, 512] 401,920
ReLU-4 [-1, 512] [-1, 512] 0
Dropout-4 [-1, 512] [-1, 512] 0
Linear-8 [-1, 512] [-1, 10] 5,130
================================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
--------------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.02
Params size (MB): 1.55
Estimated Total Size (MB): 1.57
--------------------------------------------------------------------------------
.. parsed-literal::
{'total_params': 407050, 'trainable_params': 407050}
另外,summary接口有两种使用方式,下面我们通过两个示例来做展示,除了\ ``Model.summary``\ 这种配套\ ``paddle.Model``\ 封装使用的接口外,还有一套配合没有经过\ ``paddle.Model``\ 封装的方式来使用。可以直接将实例化好的Layer子类放到\ ``paddle.summary``\ 接口中进行可视化呈现。 另外,summary接口有两种使用方式,下面我们通过两个示例来做展示,除了\ ``Model.summary``\ 这种配套\ ``paddle.Model``\ 封装使用的接口外,还有一套配合没有经过\ ``paddle.Model``\ 封装的方式来使用。可以直接将实例化好的Layer子类放到\ ``paddle.summary``\ 接口中进行可视化呈现。
.. code:: ipython3 .. code:: ipython3
paddle.summary(mnist, (1, 28, 28)) paddle.summary(mnist, (1, 28, 28))
.. parsed-literal::
--------------------------------------------------------------------------------
Layer (type) Input Shape Output Shape Param #
================================================================================
Flatten-57508 [-1, 1, 28, 28] [-1, 784] 0
Linear-5 [-1, 784] [-1, 512] 401,920
ReLU-3 [-1, 512] [-1, 512] 0
Dropout-3 [-1, 512] [-1, 512] 0
Linear-6 [-1, 512] [-1, 10] 5,130
================================================================================
Total params: 407,050
Trainable params: 407,050
Non-trainable params: 0
--------------------------------------------------------------------------------
Input size (MB): 0.00
Forward/backward pass size (MB): 0.02
Params size (MB): 1.55
Estimated Total Size (MB): 1.57
--------------------------------------------------------------------------------
.. parsed-literal::
{'total_params': 407050, 'trainable_params': 407050}
这里面有一个注意的点,有的用户可能会疑惑为什么要传递\ ``(1, 28, 28)``\ 这个input_size参数,因为在动态图中,网络定义阶段是还没有得到输入数据的形状信息,我们想要做网络结构的呈现就无从下手,那么我们通过告知接口网络结构的输入数据形状,这样网络可以通过逐层的计算推导得到完整的网络结构信息进行呈现。如果是动态图运行模式,那么就不需要给summary接口传递输入数据形状这个值了,因为在Model封装的时候我们已经定义好了InputSpec,其中包含了输入数据的形状格式。 这里面有一个注意的点,有的用户可能会疑惑为什么要传递\ ``(1, 28, 28)``\ 这个input_size参数,因为在动态图中,网络定义阶段是还没有得到输入数据的形状信息,我们想要做网络结构的呈现就无从下手,那么我们通过告知接口网络结构的输入数据形状,这样网络可以通过逐层的计算推导得到完整的网络结构信息进行呈现。如果是动态图运行模式,那么就不需要给summary接口传递输入数据形状这个值了,因为在Model封装的时候我们已经定义好了InputSpec,其中包含了输入数据的形状格式。
5. 模型训练 5. 模型训练
...@@ -352,6 +417,31 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -352,6 +417,31 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
batch_size=32, batch_size=32,
verbose=1) verbose=1)
.. parsed-literal::
Epoch 1/10
step 1875/1875 [==============================] - loss: 0.1600 - acc: 0.9022 - 10ms/step
Epoch 2/10
step 1875/1875 [==============================] - loss: 0.0455 - acc: 0.9461 - 12ms/step
Epoch 3/10
step 1875/1875 [==============================] - loss: 0.1429 - acc: 0.9544 - 19ms/step
Epoch 4/10
step 1875/1875 [==============================] - loss: 0.0197 - acc: 0.9601 - 22ms/step
Epoch 5/10
step 1875/1875 [==============================] - loss: 0.1762 - acc: 0.9644 - 25ms/step
Epoch 6/10
step 1875/1875 [==============================] - loss: 0.1304 - acc: 0.9667 - 22ms/step
Epoch 7/10
step 1875/1875 [==============================] - loss: 0.0133 - acc: 0.9682 - 22ms/step
Epoch 8/10
step 1875/1875 [==============================] - loss: 0.0097 - acc: 0.9705 - 19ms/step
Epoch 9/10
step 1875/1875 [==============================] - loss: 3.1264e-04 - acc: 0.9716 - 23ms/step
Epoch 10/10
step 1875/1875 [==============================] - loss: 0.0767 - acc: 0.9729 - 13ms/step
5.1 单机单卡 5.1 单机单卡
~~~~~~~~~~~~ ~~~~~~~~~~~~
...@@ -359,8 +449,6 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -359,8 +449,6 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
.. code:: ipython3 .. code:: ipython3
# 启动动态图训练模式
paddle.disable_static()
# 使用GPU训练 # 使用GPU训练
paddle.set_device('gpu') paddle.set_device('gpu')
...@@ -379,15 +467,41 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -379,15 +467,41 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
batch_size=32, batch_size=32,
verbose=1) verbose=1)
.. parsed-literal::
Epoch 1/10
step 1875/1875 [==============================] - loss: 0.0490 - acc: 0.9741 - 6ms/step
Epoch 2/10
step 1875/1875 [==============================] - loss: 0.1384 - acc: 0.9760 - 7ms/step
Epoch 3/10
step 1875/1875 [==============================] - loss: 0.0929 - acc: 0.9767 - 7ms/step
Epoch 4/10
step 1875/1875 [==============================] - loss: 0.0190 - acc: 0.9772 - 6ms/step
Epoch 5/10
step 1875/1875 [==============================] - loss: 0.0862 - acc: 0.9774 - 7ms/step
Epoch 6/10
step 1875/1875 [==============================] - loss: 0.0748 - acc: 0.9785 - 8ms/step
Epoch 7/10
step 1875/1875 [==============================] - loss: 0.0039 - acc: 0.9798 - 17ms/step
Epoch 8/10
step 1875/1875 [==============================] - loss: 0.0037 - acc: 0.9808 - 11ms/step
Epoch 9/10
step 1875/1875 [==============================] - loss: 0.0013 - acc: 0.9800 - 8ms/step
Epoch 10/10
step 1875/1875 [==============================] - loss: 0.0376 - acc: 0.9810 - 8ms/step
5.2 单机多卡 5.2 单机多卡
~~~~~~~~~~~~ ~~~~~~~~~~~~
对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用\ ``paddle.distributed.launch``\ 启动单机单卡的程序即可。 对于高层API来实现单机多卡非常简单,整个训练代码和单机单卡没有差异。直接使用\ ``paddle.distributed.launch``\ 启动单机单卡的程序即可。
.. code:: ipython3 .. code:: bash
$ python -m paddle.distributed.launch train.py
# train.py里面包含的就是单机单卡代码 train.py里面包含的就是单机单卡代码
python -m paddle.distributed.launch train.py
5.3 自定义Loss 5.3 自定义Loss
~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~
...@@ -640,6 +754,14 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi ...@@ -640,6 +754,14 @@ paddle即可使用相关高层API,如:paddle.Model、视觉领域paddle.visi
result = model.evaluate(val_dataset, verbose=1) result = model.evaluate(val_dataset, verbose=1)
.. parsed-literal::
Eval begin...
step 10000/10000 [==============================] - loss: 0.0000e+00 - acc: 0.9801 - 2ms/step
Eval samples: 10000
7. 模型预测 7. 模型预测
----------- -----------
...@@ -657,6 +779,14 @@ numpy_ndarray_n是对应原始数据经过模型计算后得到的预测数据 ...@@ -657,6 +779,14 @@ numpy_ndarray_n是对应原始数据经过模型计算后得到的预测数据
pred_result = model.predict(val_dataset) pred_result = model.predict(val_dataset)
.. parsed-literal::
Predict begin...
step 10000/10000 [==============================] - 4ms/step
Predict samples: 10000
7.1 使用多卡进行预测 7.1 使用多卡进行预测
~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~
...@@ -678,10 +808,33 @@ infer.py里面就是包含model.predict的代码程序。 ...@@ -678,10 +808,33 @@ infer.py里面就是包含model.predict的代码程序。
模型训练和验证达到我们的预期后,可以使用\ ``save``\ 接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。 模型训练和验证达到我们的预期后,可以使用\ ``save``\ 接口来将我们的模型保存下来,用于后续模型的Fine-tuning(接口参数training=True)或推理部署(接口参数training=False)。
需要注意的是,在动态图模式训练时保存推理模型的参数文件和模型文件,需要在forward成员函数上添加@paddle.jit.to_static装饰器,参考下面的例子:
.. code:: python
class Mnist(paddle.nn.Layer):
def __init__(self):
super(Mnist, self).__init__()
self.flatten = paddle.nn.Flatten()
self.linear_1 = paddle.nn.Linear(784, 512)
self.linear_2 = paddle.nn.Linear(512, 10)
self.relu = paddle.nn.ReLU()
self.dropout = paddle.nn.Dropout(0.2)
@paddle.jit.to_static
def forward(self, inputs):
y = self.flatten(inputs)
y = self.linear_1(y)
y = self.relu(y)
y = self.dropout(y)
y = self.linear_2(y)
return y
.. code:: ipython3 .. code:: ipython3
# 保存用于推理部署的模型(training=False model.save('~/model/mnist')
model.save('~/model/mnist', training=False)
8.2 预测部署 8.2 预测部署
~~~~~~~~~~~~ ~~~~~~~~~~~~
......
...@@ -173,8 +173,8 @@ ...@@ -173,8 +173,8 @@
"#### paddle 基础框架-动态图-模型参数保存 \n", "#### paddle 基础框架-动态图-模型参数保存 \n",
" * paddle.save\n", " * paddle.save\n",
"#### paddle 基础框架-静态图-模型参数保存 \n", "#### paddle 基础框架-静态图-模型参数保存 \n",
" * paddle.io.save\n", " * paddle.static.save\n",
" * paddle.io.save_inference_model\n", " * paddle.static.save_inference_model\n",
"\n", "\n",
"下面将基于高阶API对模型保存与加载的方法进行讲解。" "下面将基于高阶API对模型保存与加载的方法进行讲解。"
] ]
...@@ -230,8 +230,8 @@ ...@@ -230,8 +230,8 @@
"#### paddle 基础框架-动态图-模型参数加载\n", "#### paddle 基础框架-动态图-模型参数加载\n",
" * paddle.load\n", " * paddle.load\n",
"#### paddle 基础框架-静态图-模型参数加载\n", "#### paddle 基础框架-静态图-模型参数加载\n",
" * paddle.io.load \n", " * paddle.static.load \n",
" * paddle.io.load_inference_model" " * paddle.static.load_inference_model"
] ]
}, },
{ {
......
...@@ -127,8 +127,8 @@ import MNIST 引入即可。 ...@@ -127,8 +127,8 @@ import MNIST 引入即可。
目前Paddle框架有三种保存模型参数的体系,分别是: #### paddle 目前Paddle框架有三种保存模型参数的体系,分别是: #### paddle
高阶API-模型参数保存 \* paddle.Model.fit \* paddle.Model.save #### 高阶API-模型参数保存 \* paddle.Model.fit \* paddle.Model.save ####
paddle 基础框架-动态图-模型参数保存 \* paddle.save #### paddle paddle 基础框架-动态图-模型参数保存 \* paddle.save #### paddle
基础框架-静态图-模型参数保存 \* paddle.io.save \* 基础框架-静态图-模型参数保存 \* paddle.static.save \*
paddle.io.save_inference_model paddle.static.save_inference_model
下面将基于高阶API对模型保存与加载的方法进行讲解。 下面将基于高阶API对模型保存与加载的方法进行讲解。
...@@ -168,8 +168,8 @@ paddle.io.save_inference_model ...@@ -168,8 +168,8 @@ paddle.io.save_inference_model
当恢复训练状态时,需要加载模型数据,此时我们可以使用加载函数从存储模型状态和优化器状态的文件中载入模型参数和优化器参数,如果不需要恢复优化器,则不必使用优化器状态文件。 当恢复训练状态时,需要加载模型数据,此时我们可以使用加载函数从存储模型状态和优化器状态的文件中载入模型参数和优化器参数,如果不需要恢复优化器,则不必使用优化器状态文件。
#### 高阶API-模型参数加载 \* paddle.Model.load #### paddle #### 高阶API-模型参数加载 \* paddle.Model.load #### paddle
基础框架-动态图-模型参数加载 \* paddle.load #### paddle 基础框架-动态图-模型参数加载 \* paddle.load #### paddle
基础框架-静态图-模型参数加载 \* paddle.io.load \* 基础框架-静态图-模型参数加载 \* paddle.static.load \*
paddle.io.load_inference_model paddle.static.load_inference_model
下面将对高阶API的模型参数加载方法进行讲解 \* model.load(self, path, 下面将对高阶API的模型参数加载方法进行讲解 \* model.load(self, path,
skip_mismatch=False, reset_optimizer=False) skip_mismatch=False, reset_optimizer=False)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册