提交 8b3729fb 编写于 作者: R RaindragonD 提交者: Cheerego

Revert dygraph (#918)

* revert dygraph

* revert dygraph
上级 2c5edc9b
# 动态图机制-DyGraph # DyGraph
PaddlePaddle的DyGraph模式是一种动态的图执行机制,可以立即执行结果,无需构建整个图。同时,和以往静态的执行计算图不同,DyGraph模式下您的所有操作可以立即获得执行结果,而不必等待所构建的计算图全部执行完成,这样可以让您更加直观地构建PaddlePaddle下的深度学习任务,以及进行模型的调试,同时还减少了大量用于构建静态计算图的代码,使得您编写、调试网络的过程变得更加便捷。
PaddlePaddle的DyGraph模式是一种动态的图执行机制,可以立即执行结果,无需构建整个图。同时,和以往静态的执行计算图不同,DyGraph模式下您的所有操作可以立即获得执行结果,而不是构建固定的计算图来执行,这样可以让您更加直观的构建PaddlePaddle下的深度学习任务并调试模型,同时还减少了大量用于构建静态计算图的代码,使得您编写网络的过程变得更加便捷,更加容易调试。
PaddlePaddle DyGraph是一个更加灵活易用的模式,可提供: PaddlePaddle DyGraph是一个更加灵活易用的模式,可提供:
* 更加灵活便捷的代码组织结构: 使用python的执行控制流程和面向对象的模型设计 * 更加灵活便捷的代码组织结构: 使用python的执行控制流程和面向对象的模型设计
* 更加便捷的调试功能: 直接调用操作从而检查正在运行的模型并且测试更改 * 更加便捷的调试功能: 直接调用操作从而检查正在运行的模型并且测试更改
* 和静态执行图通用的模型代码:同样的模型代码可以使用更加便捷的DyGraph调试,执行,同时也支持使用原有的静态图模式执行 * 和静态执行图通用的模型代码:同样的模型代码可以使用更加便捷的DyGraph调试,执行,同时也支持使用原有的静态图模式执行
* 支持纯python和numpy语法实现的layer: 支持使用numpy相关操作直接搭建模型计算部分
* 支持纯Python和Numpy语法实现的layer: 支持使用Numpy相关操作直接搭建模型计算部分
## 设置和基本用法 ## 设置和基本用法
1. 升级到最新的PaddlePaddle 1.4: 1. 升级到最新的PaddlePaddle 1.4:
```
pip install -q --upgrade paddlepaddle==1.4 pip install -q --upgrade paddlepaddle==1.4
```
2. 使用`fluid.dygraph.guard(place=None)` 上下文: 2. 使用`fluid.dygraph.guard(place=None)` 上下文:
```python
import paddle.fluid as fluid import paddle.fluid as fluid
with fluid.dygraph.guard(): with fluid.dygraph.guard():
# write your executable dygraph code here # write your executable dygraph code here
```
现在您就可以在`fluid.dygraph.guard()`上下文环境中使用DyGraph的模式运行网络了,DyGraph将改变以往PaddlePaddle的执行方式: 现在他们将会立即执行,并且将计算结果返回给Python。 现在您就可以在`fluid.dygraph.guard()`上下文环境中使用DyGraph的模式运行网络了,DyGraph将改变以往PaddlePaddle的执行方式: 现在他们将会立即执行,并且将计算结果返回给Python。
Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variable(x)`将会将ndarray转换为`fluid.Variable`,而使用`fluid.Variable.numpy()`将可以把任意时刻获取到的计算结果转换为Numpy`ndarray` Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variable(x)`将会将ndarray转换为`fluid.Variable`,而使用`fluid.Variable.numpy()`将可以把任意时刻获取到的计算结果转换为Numpy`ndarray`:
```python
x = np.ones([2, 2], np.float32) x = np.ones([2, 2], np.float32)
with fluid.dygraph.guard(): with fluid.dygraph.guard():
inputs = [] inputs = []
...@@ -48,39 +33,29 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -48,39 +33,29 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
inputs.append(fluid.dygraph.base.to_variable(x)) inputs.append(fluid.dygraph.base.to_variable(x))
ret = fluid.layers.sums(inputs) ret = fluid.layers.sums(inputs)
print(ret.numpy()) print(ret.numpy())
```
得到输出 :
```
[[10. 10.] [[10. 10.]
[10. 10.]] [10. 10.]]
Process finished with exit code 0 Process finished with exit code 0
```
> 这里创建了一系列`ndarray`的输入,执行了一个`sum`操作之后,我们可以直接将运行的结果打印出来
然后通过调用`reduce_sum`后使用`Variable.backward()`方法执行反向,使用`Variable.gradient()`方法即可获得反向网络执行完成后的梯度值的`ndarray`形式: > 这里创建了一系列`ndarray`的输入,执行了一个`sum`操作之后,我们可以直接将运行的结果打印出来
然后通过调用`reduce_sum`后使用`Variable.backward()`方法执行反向,使用`Variable.gradient()`方法即可获得反向网络执行完成后的梯度值的`ndarray`形式:
```python
loss = fluid.layers.reduce_sum(ret) loss = fluid.layers.reduce_sum(ret)
loss.backward() loss.backward()
print(loss.gradient()) print(loss.gradient())
```
得到输出 :
```
[1.] [1.]
Process finished with exit code 0 Process finished with exit code 0
```
<!--3. 使用Python和Numpy的操作来构建一个网络: <!--3. 使用Python和Numpy的操作来构建一个网络:
...@@ -126,61 +101,44 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -126,61 +101,44 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
1. 建立一个可以在DyGraph模式中执行的,Object-Oriented的网络,需要继承自`fluid.Layer`,其中需要调用基类的`__init__`方法,并且实现带有参数`name_scope`(用来标识本层的名字)的`__init__`构造函数,在构造函数中,我们通常会执行一些例如参数初始化,子网络初始化的操作,执行这些操作时不依赖于输入的动态信息: 1. 建立一个可以在DyGraph模式中执行的,Object-Oriented的网络,需要继承自`fluid.Layer`,其中需要调用基类的`__init__`方法,并且实现带有参数`name_scope`(用来标识本层的名字)的`__init__`构造函数,在构造函数中,我们通常会执行一些例如参数初始化,子网络初始化的操作,执行这些操作时不依赖于输入的动态信息:
```python
class MyLayer(fluid.Layer): class MyLayer(fluid.Layer):
def __init__(self, name_scope): def __init__(self, name_scope):
super(MyLayer, self).__init__(name_scope) super(MyLayer, self).__init__(name_scope)
```
2. 实现一个`forward(self, *inputs)`的执行函数,该函数将负责执行实际运行时网络的执行逻辑, 该函数将会在每一轮训练/预测中被调用,这里我们将执行一个简单的`relu` -> `elementwise add` -> `reduce sum`:
2. 实现一个`forward(self, *inputs)`的执行函数,该函数将负责执行,实际运行时网络的执行逻辑, 该函数将会在每一轮训练/预测中被调用,这里我们将执行一个简单的`relu` -> `elementwise add` -> `reduce sum`:
```python
def forward(self, inputs): def forward(self, inputs):
x = fluid.layers.relu(inputs) x = fluid.layers.relu(inputs)
self._x_for_debug = x self._x_for_debug = x
x = fluid.layers.elementwise_mul(x, x) x = fluid.layers.elementwise_mul(x, x)
x = fluid.layers.reduce_sum(x) x = fluid.layers.reduce_sum(x)
return [x] return [x]
```
3. (可选)实现一个`build_once(self, *inputs)` 方法,该方法将作为一个单次执行的函数,用于初始化一些依赖于输入信息的参数和网络信息, 例如在`FC`(fully connected layer)当中, 需要依赖输入的`shape`初始化参数, 这里我们并不需要这样的操作,仅仅为了展示,因此这个方法可以直接跳过:
3. (optional)实现一个`build_once(self, *inputs)` 方法,该方法将作为一个单次执行的函数,用于初始化一些依赖于输入信息的参数和网络信息, 例如在`FC`(fully connected layer)当中, 需要依赖输入的`shape`初始化参数, 这里我们并不需要这样的操作,仅仅为了展示,因此这个方法可以直接跳过:
```python
def build_once(self, input): def build_once(self, input):
pass pass
```
2.`fluid.dygraph.guard()`中执行: 2.`fluid.dygraph.guard()`中执行:
1. 使用Numpy构建输入: 1. 使用Numpy构建输入:
```python
np_inp = np.array([1.0, 2.0, -1.0], dtype=np.float32) np_inp = np.array([1.0, 2.0, -1.0], dtype=np.float32)
```
2. 输入转换并执行前向网络获取返回值: 使用`fluid.dygraph.base.to_variable(np_inp)`转换Numpy输入为DyGraph接收的输入,然后使用`l(var_inp)[0]`调用callable object并且获取了`x`作为返回值,利用`x.numpy()`方法直接获取了执行得到的`x`的`ndarray`返回值。 2. 输入转换并执行前向网络获取返回值: 使用`fluid.dygraph.base.to_variable(np_inp)`转换Numpy输入为DyGraph接收的输入,然后使用`l(var_inp)[0]`调用callable object并且获取了`x`作为返回值,利用`x.numpy()`方法直接获取了执行得到的`x`的`ndarray`返回值。
```python
with fluid.dygraph.guard(): with fluid.dygraph.guard():
var_inp = fluid.dygraph.base.to_variable(np_inp) var_inp = fluid.dygraph.base.to_variable(np_inp)
l = MyLayer("my_layer") l = MyLayer("my_layer")
x = l(var_inp)[0] x = l(var_inp)[0]
dy_out = x.numpy() dy_out = x.numpy()
```
3. 计算梯度:自动微分对于实现机器学习算法(例如用于训练神经网络的反向传播)来说很有用, 使用`x.backward()`方法可以从某个`fluid.Varaible`开始执行反向网络,同时利用`l._x_for_debug.gradient()`获取了网络中`x`梯度的`ndarray` 返回值: 3. 计算梯度:自动微分对于实现机器学习算法(例如用于训练神经网络的反向传播)来说很有用, 使用`x.backward()`方法可以从某个`fluid.Varaible`开始执行反向网络,同时利用`l._x_for_debug.gradient()`获取了网络中`x`梯度的`ndarray` 返回值:
```python
x.backward() x.backward()
dy_grad = l._x_for_debug.gradient() dy_grad = l._x_for_debug.gradient()
```
## 使用DyGraph训练模型 ## 使用DyGraph训练模型
...@@ -192,14 +150,11 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -192,14 +150,11 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
1. 准备数据,我们使用`paddle.dataset.mnist`作为训练所需要的数据集: 1. 准备数据,我们使用`paddle.dataset.mnist`作为训练所需要的数据集:
```python
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)
```
2. 构建网络,虽然您可以根据之前的介绍自己定义所有的网络结构,但是您也可以直接使用`fluid.Layer.nn`当中我们为您定制好的一些基础网络结构,这里我们利用`fluid.Layer.nn.Conv2d`以及`fluid.Layer.nn.Pool2d`构建了基础的`SimpleImgConvPool` 2. 构建网络,虽然您可以根据之前的介绍自己定义所有的网络结构,但是您也可以直接使用`fluid.Layer.nn`当中我们为您定制好的一些基础网络结构,这里我们利用`fluid.Layer.nn.Conv2d`以及`fluid.Layer.nn.Pool2d`构建了基础的`SimpleImgConvPool`
```python
class SimpleImgConvPool(fluid.dygraph.Layer): class SimpleImgConvPool(fluid.dygraph.Layer):
def __init__(self, def __init__(self,
name_scope, name_scope,
...@@ -247,7 +202,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -247,7 +202,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
x = self._conv2d(inputs) x = self._conv2d(inputs)
x = self._pool2d(x) x = self._pool2d(x)
return x return x
```
> 注意: 构建网络时子网络的定义和使用请在`__init__`中进行, 而子网络的调用则在`forward`函数中调用 > 注意: 构建网络时子网络的定义和使用请在`__init__`中进行, 而子网络的调用则在`forward`函数中调用
...@@ -257,7 +212,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -257,7 +212,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
3. 利用已经构建好的`SimpleImgConvPool`组成最终的`MNIST`网络: 3. 利用已经构建好的`SimpleImgConvPool`组成最终的`MNIST`网络:
```python
class MNIST(fluid.dygraph.Layer): class MNIST(fluid.dygraph.Layer):
def __init__(self, name_scope): def __init__(self, name_scope):
super(MNIST, self).__init__(name_scope) super(MNIST, self).__init__(name_scope)
...@@ -283,13 +237,12 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -283,13 +237,12 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
x = self._simple_img_conv_pool_2(x) x = self._simple_img_conv_pool_2(x)
x = self._fc(x) x = self._fc(x)
return x return x
```
4.`fluid.dygraph.guard()`中定义配置好的`MNIST`网络结构,此时即使没有训练也可以在`fluid.dygraph.guard()`中调用模型并且检查输出: 4.`fluid.dygraph.guard()`中定义配置好的`MNIST`网络结构,此时即使没有训练也可以在`fluid.dygraph.guard()`中调用模型并且检查输出:
```python
with fluid.dygraph.guard(): with fluid.dygraph.guard():
mnist = MNIST("mnist") mnist = MNIST("mnist")
id, data = list(enumerate(train_reader()))[0] id, data = list(enumerate(train_reader()))[0]
...@@ -298,11 +251,9 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -298,11 +251,9 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
for x in data]).astype('float32') for x in data]).astype('float32')
img = to_variable(dy_x_data) img = to_variable(dy_x_data)
print("cost is: {}".format(mnist(img).numpy())) print("cost is: {}".format(mnist(img).numpy()))
```
得到输出:
```
cost is: [[0.10135901 0.1051138 0.1027941 ... 0.0972859 0.10221873 0.10165327] cost is: [[0.10135901 0.1051138 0.1027941 ... 0.0972859 0.10221873 0.10165327]
[0.09735426 0.09970362 0.10198303 ... 0.10134517 0.10179105 0.10025002] [0.09735426 0.09970362 0.10198303 ... 0.10134517 0.10179105 0.10025002]
[0.09539858 0.10213123 0.09543551 ... 0.10613529 0.10535969 0.097991 ] [0.09539858 0.10213123 0.09543551 ... 0.10613529 0.10535969 0.097991 ]
...@@ -312,11 +263,9 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -312,11 +263,9 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
[0.09097178 0.10078511 0.10198414 ... 0.10317434 0.10087223 0.09816764]] [0.09097178 0.10078511 0.10198414 ... 0.10317434 0.10087223 0.09816764]]
Process finished with exit code 0 Process finished with exit code 0
```
5. 构建训练循环,在每一轮参数更新完成后我们调用`mnist.clear_gradients()`来重置梯度: 5. 构建训练循环,在每一轮参数更新完成后我们调用`mnist.clear_gradients()`来重置梯度:
```python
for epoch in range(epoch_num): for epoch in range(epoch_num):
for batch_id, data in enumerate(train_reader()): for batch_id, data in enumerate(train_reader()):
dy_x_data = np.array( dy_x_data = np.array(
...@@ -337,7 +286,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -337,7 +286,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
avg_loss.backward() avg_loss.backward()
sgd.minimize(avg_loss) sgd.minimize(avg_loss)
mnist.clear_gradients() mnist.clear_gradients()
```
...@@ -347,7 +296,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -347,7 +296,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
反向运行后调用之前定义的`SGD`优化器对象的`minimize`方法进行参数更新: 反向运行后调用之前定义的`SGD`优化器对象的`minimize`方法进行参数更新:
```python
with fluid.dygraph.guard(): with fluid.dygraph.guard():
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
...@@ -357,6 +305,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -357,6 +305,7 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
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)
dy_param_init_value = {}
np.set_printoptions(precision=3, suppress=True) np.set_printoptions(precision=3, suppress=True)
for epoch in range(epoch_num): for epoch in range(epoch_num):
for batch_id, data in enumerate(train_reader()): for batch_id, data in enumerate(train_reader()):
...@@ -376,6 +325,10 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -376,6 +325,10 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
dy_out = avg_loss.numpy() dy_out = avg_loss.numpy()
if epoch == 0 and batch_id == 0:
for param in mnist.parameters():
dy_param_init_value[param.name] = param.numpy()
avg_loss.backward() avg_loss.backward()
sgd.minimize(avg_loss) sgd.minimize(avg_loss)
mnist.clear_gradients() mnist.clear_gradients()
...@@ -389,13 +342,10 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -389,13 +342,10 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
print("Final loss: {:.7}".format(avg_loss.numpy())) print("Final loss: {:.7}".format(avg_loss.numpy()))
print("_simple_img_conv_pool_1_conv2d W's mean is: {}".format(mnist._simple_img_conv_pool_1._conv2d._filter_param.numpy().mean())) print("_simple_img_conv_pool_1_conv2d W's mean is: {}".format(mnist._simple_img_conv_pool_1._conv2d._filter_param.numpy().mean()))
print("_simple_img_conv_pool_1_conv2d Bias's mean is: {}".format(mnist._simple_img_conv_pool_1._conv2d._bias_param.numpy().mean())) print("_simple_img_conv_pool_1_conv2d Bias's mean is: {}".format(mnist._simple_img_conv_pool_1._conv2d._bias_param.numpy().mean()))
```
得到输出:
```
Loss at step 0: [2.302] Loss at step 0: [2.302]
Loss at step 20: [1.616] Loss at step 20: [1.616]
Loss at step 40: [1.244] Loss at step 40: [1.244]
...@@ -423,26 +373,20 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -423,26 +373,20 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
Final loss: [0.164] Final loss: [0.164]
_simple_img_conv_pool_1_conv2d W's mean is: 0.00606656912714 _simple_img_conv_pool_1_conv2d W's mean is: 0.00606656912714
_simple_img_conv_pool_1_conv2d Bias's mean is: -3.4576318285e-05 _simple_img_conv_pool_1_conv2d Bias's mean is: -3.4576318285e-05
```
7. 性能 7. 性能
在使用`fluid.dygraph.guard()`可以通过传入`fluid.CUDAPlace(0)`或者`fluid.CPUPlace()`来选择执行DyGraph的设备,通常如果不做任何处理将会自动适配您的设备。 在使用`fluid.dygraph.guard()`可以通过传入`fluid.CUDAPlace(0)`或者`fluid.CPUPlace()`来选择执行DyGraph的设备,通常如果不做任何处理将会自动适配您的设备。
## 模型参数的保存 ## 模型参数的保存

在模型训练中可以使用` fluid.dygraph.save_persistables(your_model_object.state_dict(), "save_dir")`来保存`your_model_object`中所有的模型参数。也可以自定义需要保存的“参数名” - “参数对象”的Python Dictionary传入。
同样可以使用`your_modle_object.load_dict(fluid.dygraph.load_persistables("save_dir"))`接口来恢复保存的模型参数从而达到继续训练的目的 
在模型训练中可以使用` fluid.dygraph.save_persistables(your_model_object.state_dict(), "save_dir")`来保存`your_model_object`中所有的模型参数。也可以自定义需要保存的“参数名” - “参数对象”的Python Dictionary传入
同样可以使用`your_modle_object.load_dict(
fluid.dygraph.load_persistables(your_model_object.state_dict(), "save_dir"))`接口来恢复保存的模型参数从而达到继续训练的目的。
下面的代码展示了如何在“手写数字识别”任务中保存参数并且读取已经保存的参数来继续训练。
下面的代码展示了如何在“手写数字识别”任务中保存参数并且读取已经保存的参数来继续训练。
```python
dy_param_init_value={}
for epoch in range(epoch_num): for epoch in range(epoch_num):
for batch_id, data in enumerate(train_reader()): for batch_id, data in enumerate(train_reader()):
dy_x_data = np.array( dy_x_data = np.array(
...@@ -468,7 +412,8 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -468,7 +412,8 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
for param in mnist.parameters(): for param in mnist.parameters():
dy_param_init_value[param.name] = param.numpy() dy_param_init_value[param.name] = param.numpy()
mnist.load_dict(fluid.dygraph.load_persistables("save_dir"))
mnist.load_dict(fluid.dygraph.load_persistables(mnist.state_dict(), "save_dir"))
restore = mnist.parameters() restore = mnist.parameters()
# check save and load # check save and load
success = True success = True
...@@ -476,7 +421,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -476,7 +421,6 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
if (not np.allclose(value.numpy(), dy_param_init_value[value.name])) or (not np.isfinite(value.numpy().all())) or (np.isnan(value.numpy().any())): if (not np.allclose(value.numpy(), dy_param_init_value[value.name])) or (not np.isfinite(value.numpy().all())) or (np.isnan(value.numpy().any())):
success = False success = False
print("model save and load success? {}".format(success)) print("model save and load success? {}".format(success))
```
...@@ -487,12 +431,11 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab ...@@ -487,12 +431,11 @@ Dygraph将非常适合和Numpy一起使用,使用`fluid.dygraph.base.to_variab
下面的代码展示了如何使用DyGraph模式训练一个用于执行“手写数字识别”任务的模型并保存,并且利用已经保存好的模型进行预测。 下面的代码展示了如何使用DyGraph模式训练一个用于执行“手写数字识别”任务的模型并保存,并且利用已经保存好的模型进行预测。
我们在第一个`fluid.dygraph.guard()`上下文中进行了模型的保存和训练,值得注意的是,当我们需要在训练的过程中进行预测时需要使用`YourModel.eval()`切换到预测模式,并且在预测完成后使用`YourModel.train()`切换回训练模式继续训练 我们在第一个`fluid.dygraph.guard()`上下文中进行了模型的保存和训练,值得注意的是,当我们需要在训练的过程中进行预测时需要使用`YourModel.eval()`切换到预测模式,并且在预测完成后使用`YourModel.train()`切换回训练模式继续训练
我们在第二个`fluid.dygraph.guard()`上下文中利用之前保存的`checkpoint`进行预测,同样的在执行预测前需要使用`YourModel.eval()`来切换的预测模式 我们在第二个`fluid.dygraph.guard()`上下文中利用之前保存的`checkpoint`进行预测,同样的在执行预测前需要使用`YourModel.eval()`来切换的预测模式
```python with fluid.dygraph.guard():
with fluid.dygraph.guard():
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
...@@ -532,14 +475,14 @@ with fluid.dygraph.guard(): ...@@ -532,14 +475,14 @@ with fluid.dygraph.guard():
fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir") fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir")
print("checkpoint saved") print("checkpoint saved")
with fluid.dygraph.guard(): with fluid.dygraph.guard():
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
mnist_infer = MNIST("mnist") mnist_infer = MNIST("mnist")
# load checkpoint # load checkpoint
mnist_infer.load_dict( mnist_infer.load_dict(
fluid.dygraph.load_persistables("save_dir")) fluid.dygraph.load_persistables(mnist.state_dict(), "save_dir"))
print("checkpoint loaded") print("checkpoint loaded")
# start evaluate mode # start evaluate mode
...@@ -556,59 +499,65 @@ with fluid.dygraph.guard(): ...@@ -556,59 +499,65 @@ with fluid.dygraph.guard():
results = mnist_infer(to_variable(tensor_img)) results = mnist_infer(to_variable(tensor_img))
lab = np.argsort(results.numpy()) lab = np.argsort(results.numpy())
print("Inference result of image/infer_3.png is: %d" % lab[0][-1]) print("Inference result of image/infer_3.png is: %d" % lab[0][0])
```
得到输出:
```
Loss at epoch 3 , Test avg_loss is: 0.0721620170576, acc is: 0.97796474359
Loss at epoch 4 step 0: [0.01078923]
Loss at epoch 4 step 100: [0.10447877]
Loss at epoch 4 step 200: [0.05149534]
Loss at epoch 4 step 300: [0.0122997]
Loss at epoch 4 step 400: [0.0281883]
Loss at epoch 4 step 500: [0.10709661]
Loss at epoch 4 step 600: [0.1306036]
Loss at epoch 4 step 700: [0.01628026]
Loss at epoch 4 step 800: [0.07947419]
Loss at epoch 4 step 900: [0.02067161]
Loss at epoch 4 , Test avg_loss is: 0.0802323290939, acc is: 0.976963141026
checkpoint saved
checkpoint loaded
Loss at epoch 3 , Test avg_loss is: 0.0721620170576, acc is: 0.97796474359
Loss at epoch 4 step 0: [0.01078923]
Loss at epoch 4 step 100: [0.10447877]
Loss at epoch 4 step 200: [0.05149534]
Loss at epoch 4 step 300: [0.0122997]
Loss at epoch 4 step 400: [0.0281883]
Loss at epoch 4 step 500: [0.10709661]
Loss at epoch 4 step 600: [0.1306036]
Loss at epoch 4 step 700: [0.01628026]
Loss at epoch 4 step 800: [0.07947419]
Loss at epoch 4 step 900: [0.02067161]
Loss at epoch 4 , Test avg_loss is: 0.0802323290939, acc is: 0.976963141026
checkpoint saved
checkpoint loaded
Ran 1 test in 208.017s
Inference result of image/infer_3.png is: 3 Ran 1 test in 208.017s
```
Inference result of image/infer_3.png is: 3
## 编写兼容的模型 ## 编写兼容的模型
以上一步中手写数字识别的例子为例,相同的模型代码可以直接在PaddlePaddle的`Executor`中执行: 以上一步中手写数字识别的例子为例,相同的模型代码可以直接在PaddlePaddle的`Executor`中执行:
```python exe = fluid.Executor(fluid.CPUPlace(
exe = fluid.Executor(fluid.CPUPlace( ) if not core.is_compiled_with_cuda() else fluid.CUDAPlace(0))
) if not core.is_compiled_with_cuda() else fluid.CUDAPlace(0))
mnist = MNIST("mnist") mnist = MNIST("mnist")
sgd = SGDOptimizer(learning_rate=1e-3) sgd = SGDOptimizer(learning_rate=1e-3)
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)
img = fluid.layers.data( img = fluid.layers.data(
name='pixel', shape=[1, 28, 28], dtype='float32') name='pixel', shape=[1, 28, 28], dtype='float32')
label = fluid.layers.data(name='label', shape=[1], dtype='int64') label = fluid.layers.data(name='label', shape=[1], dtype='int64')
cost = mnist(img) cost = mnist(img)
loss = fluid.layers.cross_entropy(cost, label) loss = fluid.layers.cross_entropy(cost, label)
avg_loss = fluid.layers.mean(loss) avg_loss = fluid.layers.mean(loss)
sgd.minimize(avg_loss) sgd.minimize(avg_loss)
# initialize params and fetch them
static_param_init_value = {}
static_param_name_list = []
for param in mnist.parameters():
static_param_name_list.append(param.name)
out = exe.run(fluid.default_startup_program(),
fetch_list=static_param_name_list)
out = exe.run(fluid.default_startup_program()) for i in range(len(static_param_name_list)):
static_param_init_value[static_param_name_list[i]] = out[i]
for epoch in range(epoch_num): for epoch in range(epoch_num):
for batch_id, data in enumerate(train_reader()): for batch_id, data in enumerate(train_reader()):
static_x_data = np.array( static_x_data = np.array(
[x[0].reshape(1, 28, 28) [x[0].reshape(1, 28, 28)
...@@ -617,14 +566,18 @@ for epoch in range(epoch_num): ...@@ -617,14 +566,18 @@ for epoch in range(epoch_num):
[x[1] for x in data]).astype('int64').reshape([BATCH_SIZE, 1]) [x[1] for x in data]).astype('int64').reshape([BATCH_SIZE, 1])
fetch_list = [avg_loss.name] fetch_list = [avg_loss.name]
fetch_list.extend(static_param_name_list)
out = exe.run( out = exe.run(
fluid.default_main_program(), fluid.default_main_program(),
feed={"pixel": static_x_data, feed={"pixel": static_x_data,
"label": y_data}, "label": y_data},
fetch_list=fetch_list) fetch_list=fetch_list)
static_param_value = {}
static_out = out[0] static_out = out[0]
``` for i in range(1, len(out)):
static_param_value[static_param_name_list[i - 1]] = out[
i]
\ No newline at end of file
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册