Skip to content
体验新版
项目
组织
正在加载...
登录
切换导航
打开侧边栏
PaddlePaddle
FluidDoc
提交
0a19499e
F
FluidDoc
项目概览
PaddlePaddle
/
FluidDoc
通知
5
Star
2
Fork
0
代码
文件
提交
分支
Tags
贡献者
分支图
Diff
Issue
23
列表
看板
标记
里程碑
合并请求
111
Wiki
0
Wiki
分析
仓库
DevOps
项目成员
Pages
F
FluidDoc
项目概览
项目概览
详情
发布
仓库
仓库
文件
提交
分支
标签
贡献者
分支图
比较
Issue
23
Issue
23
列表
看板
标记
里程碑
合并请求
111
合并请求
111
Pages
分析
分析
仓库分析
DevOps
Wiki
0
Wiki
成员
成员
收起侧边栏
关闭侧边栏
动态
分支图
创建新Issue
提交
Issue看板
提交
0a19499e
编写于
6月 25, 2018
作者:
Y
Yang Yaming
浏览文件
操作
浏览文件
下载
电子邮件补丁
差异文件
Polish the doc and add link to parent index page.
上级
28817f9a
变更
2
显示空白变更内容
内联
并排
Showing
2 changed file
with
27 addition
and
118 deletion
+27
-118
source/user_guides/howto/configure_simple_model/index.rst
source/user_guides/howto/configure_simple_model/index.rst
+24
-94
source/user_guides/howto/index.rst
source/user_guides/howto/index.rst
+3
-24
未找到文件。
source/user_guides/howto/configure_simple_model/index.rst
浏览文件 @
0a19499e
前言
########
.. _user_guide_configure_simple_model:
在解决实际问题时,可以先从逻辑层面对问题进行建模,明确模型所需要的**输入数据类型**,**计算逻辑**,**求解目标**以及**优化算法**.模型定义清晰后,可以使用PaddlePaddle提供的丰富算子来搭建模型并使用训练数据进行训练.完整流程如下图所示:
##############
配置简单的网络
##############
下面举例说明如何使用PaddlePaddle解决一个简单的问题. 该例子完整代码参见*ref fit_a_line*.
前言
####
在解决实际问题时,可以先从逻辑层面对问题进行建模,明确模型所需要的 **输入数据类型**、**计算逻辑**、**求解目标** 以及 **优化算法**。模型定义清晰后,可以使用PaddlePaddle提供的丰富算子来实现模型逻辑。下面以一个简单回归任务举例说明如何使用PaddlePaddle构建模型。该例子完整代码参见 `fit_a_line <https://github.com/PaddlePaddle/Paddle/blob/develop/python/paddle/fluid/tests/book/test_fit_a_line.py>`_。
问题描述及定义
##############
问题描述: 给定一组数据
<X, Y>,求解出函数f,使得y=f(x),其中X属于R13,每维代表房屋的一个特征,y属于R表示该房屋的房价.考虑到输入样本为一个13维的实数向量,输出为一个实数值, 可以尝试用回归模型来对问题建模.回归模型的求解目标函数有很多,这里使用均方误差作为损失函数,确定了损失函数后,需要对f的复杂度进行判断,这里假定f为简单的线性变换函数. 除了明确模型的输入格式,求解目标以及模型结构外,还需要选择合适的优化方法,这里选用随机梯度下降算法来求解模型.
问题描述: 给定一组数据
:math:`<X, Y>`,求解出函数 :math:`f`,使得 :math:`y=f(x)`,其中 :math:`x\subset X` 表示一条样本的特征,为 :math:`13` 维的实数向量;:math:`y\subset Y` 为一实数表示该样本对应的值。可以尝试用回归模型来对问题建模,回归问题的损失函数有很多,这里选择常用的均方误差。为简化问题,这里假定 :math:`f` 为简单的线性变换函数。除了明确模型的输入格式、求解目标以及模型结构外,还需要选择合适的优化方法,这里选用随机梯度下降算法来求解模型。
使用PaddlePadle建模
###################
上一节从逻辑层面明确了输入数据格式,模型结构,损失函数以及优化算法,下面需要使用PaddlePaddle提供的算子来实现模型.模型实现后,需要使用训练数据对模型参数求解,训练完成后,需要提供模型推断功能,即加载训练好的模型,预测样本x的输出值.
从逻辑层面明确了输入数据格式、模型结构、损失函数以及优化算法后,需要使用PaddlePaddle提供的API及算子来实现模型逻辑。一个典型的模型主要包含4个部分,分别是:输入数据格式定义,模型前向计算逻辑,损失函数以及优化算法。
数据层
------
-
------
PaddlePaddle提供了data算子来描述输入数据的格式
,data算子的输出是一个tensor,tensor可以表示具有多个维度的数据,比较重要的参数包括shape和type.训练神经网络时一般会使用mini-batch的方式喂入数据,而batch size在训练过程中可能不固定,data算子会依据喂入的数据来推断batch size,所以这里定义shape时不用关心batch size的大小,只需关心一条样本的shape即可.从上可知,x为13维的实数向量,y为实数,可使用下面代码定义数据层:
PaddlePaddle提供了data算子来描述输入数据的格式
。data算子的输出是一个Tensor,Tensor具有强大的表征能力,可以表示多维数据。为了精确描述数据结构,通常需要指定数据shape以及数值类型type。其中shape为一个整数向量,type则包括'float32'、'int32'和'int64'等。模型训练一般会使用batch的方式读取数据,而batch的size在训练过程中可能不固定,data算子会依据实际数据来推断batch size,所以这里提供shape时不用关心batch size,只需关心一条样本的shape即可。从上知,:math:`x` 为 :math:`13` 维的实数向量,:math:`y` 为实数,可使用下面代码定义数据层:
.. code-block:: python
x = fluid.layers.data(name='x', shape=[13], dtype='float32')
y = fluid.layers.data(name='y', shape=[1], dtype='float32')
PaddlePaddle还提供了效率更高的方式来喂入数据,不需要先转成python numpy的中间表示,直接从文件中读取,这种方式可以减少数据i/o的时间消耗,具体可以参考*ref data provider*
该模型使用的数据比较简单,事实上data算子还可以描述变长的、嵌套的序列数据,更详细的文档可参照 `layers.data <http://www.paddlepaddle.org/docs/develop/api/fluid/en/layers.html#permalink-33-data>`_。
计算逻辑
---------
前向
计算逻辑
---------
---
模型结构里面最重要的部分是计算逻辑的定义,比如图像相关任务中会使用较多的卷积算子,序列任务中会使用LSTM/GRU等算子.一个算子通常对应一种或一组变换逻辑,算子输出即为对输入数据执行变换后的结果.复杂模型通常会组合多种算子,以完成复杂的变换,PaddlePaddle提供了非常自然的方式来组合算子,一般地可以使用下面的方式:
实现一个模型最重要的部分是实现计算逻辑,PaddlePaddle提供了丰富的算子,这些算子的封装粒度不同,通常对应一种或一组变换逻辑,算子输出即为对输入数据执行变换后的结果。可以灵活使用算子来完成复杂的模型逻辑,比如图像相关任务中会使用较多的卷积算子,序列任务中会使用LSTM/GRU等算子。复杂模型通常会组合多种算子,以完成复杂的变换,PaddlePaddle提供了非常自然的方式来组合算子,一般地可以使用下面的方式:
.. code-block:: python
...
...
@@ -38,108 +42,34 @@ PaddlePaddle还提供了效率更高的方式来喂入数据,不需要先转成p
op_2_out = fluid.layers.op_2(input=op_1_out, ...)
...
其中op_1和op_2表示算子
,可以是fc来执行线性变化,可以是conv来执行卷积变换.更复杂的模型可能需要使用控制流算子,依据输入数据来动态执行相关逻辑,针对这种情况,PaddlePaddle提供了IfElseOp和WhileOp,有关算子的文档可参考*ref op doc*. 具体到这个任务, 我们使用一个fc算子:
其中op_1和op_2表示算子
类型,可以是fc来执行线性变换,也可以是conv来执行卷积变换等。通过算子的输入输出的连接来定义算子的计算顺序以及数据流方向,上面的例子中,op_1的输出是op_2的输入,那么在执行计算时,会先计算op_1,然后计算op_2。更复杂的模型可能需要使用控制流算子,依据输入数据来动态执行,针对这种情况,PaddlePaddle提供了IfElseOp和WhileOp等,算子的文档可参考 `layers <http://www.paddlepaddle.org/docs/develop/api/fluid/en/layers.html>`_。具体到这个任务, 我们使用一个fc算子:
.. code-block:: python
y_predict = fluid.layers.fc(input=x, size=1, act=None)
损失函数
--------
--
--------
损失函数对应求解目标
,模型通过最小化损失来求解模型参数.大多数模型会使用平均损失作为最终的loss,所以在PaddlePaddle中一般会在损失算子后面接mean算子来求平均.模型在一次前向迭代后会得到一个损失值,框架会依据该值计算梯度,然后自动执行链式求导法则计算模型里面每个参数对应的梯度值.这里使用均方误差损失:
损失函数对应求解目标
,可以通过最小化损失来求解模型。大多数模型使用的损失函数,输出是一个实数值,但是PaddlePaddle提供的损失算子一般是针对一条样本计算,当输入一个batch的数据时,损失算子的输出有多个值,每个值对应一条样本的损失,所以通常会在损失算子后面使用mean等算子,来对损失做归约。模型在一次前向迭代后会得到一个损失值,PaddlePaddle依据该值计算梯度,然后自动执行链式求导法则计算模型里面每个参数对应的梯度值。这里使用均方误差损失:
.. code-block:: python
cost = fluid.layers.square_error_cost(input=y_predict, label=y)
avg_cost = fluid.layers.mean(cost)
更多损失函数算子可以参考*ref loss op*.
优化方法
--------
--
--------
确定损失函数后
,可以通过前向计算得到损失值,然后通过链式求导法则得到参数的梯度值.获取梯度值后需要更新参数,最简单的sgd,*sgd 公式*,但是sgd有一些缺点,比如收敛不稳定等,为了改善模型的训练速度以及效果,先后提出了很多优化算子,包括momentum/autograd/rmsprop/adam等,这些优化算法采用不同的策略来更新模型参数,可以针对不同任务尝试不同的优化方法,同时需要对一些超参数进行实验调参.一般来讲learning rate是优化算子中的一个重要参数,需要仔细调整,这里采用sgd优化算法:
确定损失函数后
,可以通过前向计算得到损失值,然后通过链式求导法则得到参数的梯度值。获取梯度值后需要更新参数,最简单的算法是随机梯度下降法::math:`w=w + \eta \cdot g`,但是随机梯度下降算法存在一些问题,比如收敛不稳定等,为了改善模型的训练速度以及效果,学术界先后提出了很多优化算法,包括:Momentum、RMSProp、Adam等,这些优化算法采用不同的策略来更新模型参数,一般可以针对具体任务和具体模型来选择优化算法。不管使用何种优化算法,学习率一般是一个需要指定的比较重要的超参数,需要通过实验仔细调整,这里采用随机梯度下降算法:
.. code-block:: python
sgd_optimizer = fluid.optimizer.SGD(learning_rate=0.001)
更多优化算子可以参考*ref opt op*.
模型训练
----------
至此,模型已经实现完成,下面需要在训练数据上训练模型的参数.首先需要实现一个reader以batch的方式提供数据,PaddlePaddle提供了易用的封装,可以使用`paddle.batch`来实现一个batch data迭代器,通常在训练阶段对数据打乱可以增强模型的效果,在paddle.batch里面嵌套'paddle.reader.shuffle'即可.接下来需要定义执行器,通过`fluid.Executor`来定义一个执行器,执行器文档可参考'executor doc'. 最后可以循环来不断迭代训练模型,通过执行器中的`run`函数来完成一次迭代.在训练过程中,可以通过调用'fluid.io.save_inference_model'来保存中间的模型.完整代码:
.. code-block:: python
BATCH_SIZE = 20
train_reader = paddle.batch(
paddle.reader.shuffle(
paddle.dataset.uci_housing.train(), buf_size=500),
batch_size=BATCH_SIZE)
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
exe = fluid.Executor(place)
def train_loop(main_program):
feeder = fluid.DataFeeder(place=place, feed_list=[x, y])
exe.run(fluid.default_startup_program())
PASS_NUM = 100
for pass_id in range(PASS_NUM):
for data in train_reader():
avg_loss_value, = exe.run(main_program,
feed=feeder.feed(data),
fetch_list=[avg_cost])
print(avg_loss_value)
if avg_loss_value[0] < 10.0:
if save_dirname is not None:
fluid.io.save_inference_model(save_dirname, ['x'],
[y_predict], exe)
return
if math.isnan(float(avg_loss_value)):
sys.exit("got NaN loss, training failed.")
raise AssertionError("Fit a line cost is too large, {0:2.2}".format(
avg_loss_value[0]))
模型推断
----------
模型训练完成后,需要提供预测功能,给定x后,可以预测对应的y值.与训练阶段一样,需要首先定义一个执行器,然后调用'fluid.io.load_inference_model'来加载保存的模型,最后调用'exe.run'来执行预测. 完整代码见:
.. code-block:: python
def infer(use_cuda, save_dirname=None):
if save_dirname is None:
return
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
exe = fluid.Executor(place)
inference_scope = fluid.core.Scope()
with fluid.scope_guard(inference_scope):
# Use fluid.io.load_inference_model to obtain the inference program desc,
# the feed_target_names (the names of variables that will be feeded
# data using feed operators), and the fetch_targets (variables that
# we want to obtain data from using fetch operators).
[inference_program, feed_target_names,
fetch_targets] = fluid.io.load_inference_model(save_dirname, exe)
# The input's dimension should be 2-D and the second dim is 13
# The input data should be >= 0
batch_size = 10
tensor_x = numpy.random.uniform(0, 10,
[batch_size, 13]).astype("float32")
assert feed_target_names[0] == 'x'
results = exe.run(inference_program,
feed={feed_target_names[0]: tensor_x},
fetch_list=fetch_targets)
print("infer shape: ", results[0].shape)
print("infer results: ", results[0])
更多优化算子可以参考 `optimizer <http://www.paddlepaddle.org/docs/develop/api/fluid/en/optimizer.html>`_。
总结
####
#
####
使用PaddlePaddle实现模型时需要关注 **数据层**、**前向计算逻辑**、**损失函数** 和 **优化方法**,不同的任务需要的数据格式不同,涉及的计算逻辑不同,需要特定的损失函数,适用的优化方法也有所差别。PaddlePaddle提供了丰富的模型示例,可以以这些示例为参考来构建自己的模型结构。可以访问 `模型库 <https://github.com/PaddlePaddle/models/tree/develop/fluid>`_ 查看官方提供的示例。
source/user_guides/howto/index.rst
浏览文件 @
0a19499e
...
...
@@ -2,28 +2,7 @@
如何使用PaddlePaddle
####################
.. toctree::
:maxdepth: 2
概述
####
数据预处理
##########
配置简单的网络
##############
训练
####
调试
####
模型评估
########
configure_simple_model/index
编辑
预览
Markdown
is supported
0%
请重试
或
添加新附件
.
添加附件
取消
You are about to add
0
people
to the discussion. Proceed with caution.
先完成此消息的编辑!
取消
想要评论请
注册
或
登录