未验证 提交 ebe54c6c 编写于 作者: J Jeff Wang 提交者: GitHub

Merge pull request #528 from jetfuel/recognize_digits_new_api

Recognize digits new api first draft
...@@ -129,17 +129,18 @@ PaddlePaddle在API中提供了自动加载[MNIST](http://yann.lecun.com/exdb/mni ...@@ -129,17 +129,18 @@ PaddlePaddle在API中提供了自动加载[MNIST](http://yann.lecun.com/exdb/mni
## 配置说明 ## 配置说明
首先,加载PaddlePaddle的V2 api包。 首先,加载PaddlePaddle的fluid api包。
```python ```python
import paddle.v2 as paddle import paddle.fluid as fluid
``` ```
其次,定义三个不同的分类器: 其次,定义三个不同的分类器:
- Softmax回归:只通过一层简单的以softmax为激活函数的全连接层,就可以得到分类的结果。 - Softmax回归:只通过一层简单的以softmax为激活函数的全连接层,就可以得到分类的结果。
```python ```python
def softmax_regression(img): def softmax_regression():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
predict = paddle.layer.fc(input=img, predict = paddle.layer.fc(input=img,
size=10, size=10,
act=paddle.activation.Softmax()) act=paddle.activation.Softmax())
...@@ -148,64 +149,59 @@ def softmax_regression(img): ...@@ -148,64 +149,59 @@ def softmax_regression(img):
- 多层感知器:下面代码实现了一个含有两个隐藏层(即全连接层)的多层感知器。其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax。 - 多层感知器:下面代码实现了一个含有两个隐藏层(即全连接层)的多层感知器。其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax。
```python ```python
def multilayer_perceptron(img): def multilayer_perceptron():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
# 第一个全连接层,激活函数为ReLU # 第一个全连接层,激活函数为ReLU
hidden1 = paddle.layer.fc(input=img, size=128, act=paddle.activation.Relu()) hidden = fluid.layers.fc(input=img, size=200, act='relu')
# 第二个全连接层,激活函数为ReLU # 第二个全连接层,激活函数为ReLU
hidden2 = paddle.layer.fc(input=hidden1, hidden = fluid.layers.fc(input=hidden, size=200, act='relu')
size=64,
act=paddle.activation.Relu())
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10 # 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=hidden2, prediction = fluid.layers.fc(input=hidden, size=10, act='softmax')
size=10, return prediction
act=paddle.activation.Softmax())
return predict
``` ```
- 卷积神经网络LeNet-5: 输入的二维图像,首先经过两次卷积层到池化层,再经过全连接层,最后使用以softmax为激活函数的全连接层作为输出层。 - 卷积神经网络LeNet-5: 输入的二维图像,首先经过两次卷积层到池化层,再经过全连接层,最后使用以softmax为激活函数的全连接层作为输出层。
```python ```python
def convolutional_neural_network(img): def convolutional_neural_network():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
# 第一个卷积-池化层 # 第一个卷积-池化层
conv_pool_1 = paddle.networks.simple_img_conv_pool( conv_pool_1 = fluid.nets.simple_img_conv_pool(
input=img, input=img,
filter_size=5, filter_size=5,
num_filters=20, num_filters=20,
num_channel=1,
pool_size=2, pool_size=2,
pool_stride=2, pool_stride=2,
act=paddle.activation.Relu()) act="relu")
conv_pool_1 = fluid.layers.batch_norm(conv_pool_1)
# 第二个卷积-池化层 # 第二个卷积-池化层
conv_pool_2 = paddle.networks.simple_img_conv_pool( conv_pool_2 = fluid.nets.simple_img_conv_pool(
input=conv_pool_1, input=conv_pool_1,
filter_size=5, filter_size=5,
num_filters=50, num_filters=50,
num_channel=20,
pool_size=2, pool_size=2,
pool_stride=2, pool_stride=2,
act=paddle.activation.Relu()) act="relu")
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10 # 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=conv_pool_2, prediction = fluid.layers.fc(input=conv_pool_2, size=10, act='softmax')
size=10, return prediction
act=paddle.activation.Softmax())
return predict
``` ```
接着,通过`layer.data`调用来获取数据,然后调用分类器(这里我们提供了三个不同的分类器)得到分类结果。训练时,对该结果计算其损失函数,分类问题常常选择交叉熵损失函数。 接着,通过`layer.data`调用来获取数据,然后调用分类器(这里我们提供了三个不同的分类器)得到分类结果。训练时,对该结果计算其损失函数,分类问题常常选择交叉熵损失函数。
```python ```python
# 该模型运行在单个CPU上 def train_program():
paddle.init(use_gpu=False, trainer_count=1) label = fluid.layers.data(name='label', shape=[1], dtype='int64')
images = paddle.layer.data( # predict = softmax_regression(images) # uncomment for Softmax回归
name='pixel', type=paddle.data_type.dense_vector(784)) # predict = multilayer_perceptron() # uncomment for 多层感知器
label = paddle.layer.data( predict = convolutional_neural_network() # uncomment for LeNet5卷积神经网络
name='label', type=paddle.data_type.integer_value(10)) cost = fluid.layers.cross_entropy(input=predict, label=label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=predict, label=label)
return [avg_cost, acc]
# predict = softmax_regression(images) # Softmax回归
# predict = multilayer_perceptron(images) #多层感知器
predict = convolutional_neural_network(images) #LeNet5卷积神经网络
cost = paddle.layer.classification_cost(input=predict, label=label) # 该模型运行在单个CPU上
``` ```
然后,指定训练相关的参数。 然后,指定训练相关的参数。
...@@ -214,16 +210,16 @@ cost = paddle.layer.classification_cost(input=predict, label=label) ...@@ -214,16 +210,16 @@ cost = paddle.layer.classification_cost(input=predict, label=label)
- 正则化(regularization): 是防止网络过拟合的一种手段,此处采用L2正则化。 - 正则化(regularization): 是防止网络过拟合的一种手段,此处采用L2正则化。
```python ```python
parameters = paddle.parameters.create(cost) # 该模型运行在单个CPU上
use_cude = False # set to True if training with GPU
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
optimizer = paddle.optimizer.Momentum( optimizer = paddle.optimizer.Momentum(
learning_rate=0.1 / 128.0, learning_rate=0.1 / 128.0,
momentum=0.9, momentum=0.9,
regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128)) regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128))
trainer = paddle.trainer.SGD(cost=cost, trainer = fluid.Trainer(
parameters=parameters, train_func=train_program, place=place, optimizer=optimizer)
update_equation=optimizer)
``` ```
下一步,我们开始训练过程。`paddle.dataset.movielens.train()``paddle.dataset.movielens.test()`分别做训练和测试数据集。这两个函数各自返回一个reader——PaddlePaddle中的reader是一个Python函数,每次调用的时候返回一个Python yield generator。 下一步,我们开始训练过程。`paddle.dataset.movielens.train()``paddle.dataset.movielens.test()`分别做训练和测试数据集。这两个函数各自返回一个reader——PaddlePaddle中的reader是一个Python函数,每次调用的时候返回一个Python yield generator。
...@@ -232,38 +228,18 @@ trainer = paddle.trainer.SGD(cost=cost, ...@@ -232,38 +228,18 @@ trainer = paddle.trainer.SGD(cost=cost,
`batch`是一个特殊的decorator,它的输入是一个reader,输出是一个batched reader —— 在PaddlePaddle里,一个reader每次yield一条训练数据,而一个batched reader每次yield一个minibatch。 `batch`是一个特殊的decorator,它的输入是一个reader,输出是一个batched reader —— 在PaddlePaddle里,一个reader每次yield一条训练数据,而一个batched reader每次yield一个minibatch。
`event_handler_plot`可以用来在训练过程中画图如下:
![png](./image/train_and_test.png)
```python ```python
from paddle.v2.plot import Ploter train_reader = paddle.batch(
paddle.reader.shuffle(
train_title = "Train cost" paddle.dataset.mnist.train(), buf_size=500),
test_title = "Test cost" batch_size=64)
cost_ploter = Ploter(train_title, test_title)
step = 0
# event_handler to plot a figure
def event_handler_plot(event):
global step
if isinstance(event, paddle.event.EndIteration):
if step % 100 == 0:
cost_ploter.append(train_title, step, event.cost)
cost_ploter.plot()
step += 1
if isinstance(event, paddle.event.EndPass):
# save parameters
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
trainer.save_parameter_to_tar(f)
result = trainer.test(reader=paddle.batch( test_reader = paddle.batch(
paddle.dataset.mnist.test(), batch_size=128)) paddle.dataset.mnist.test(), batch_size=64)
cost_ploter.append(test_title, step, result.cost)
``` ```
`event_handler` 用来在训练过程中输出训练结果 `event_handler` 用来在训练过程中输出训练结果
```python ```python
lists = [] lists = []
...@@ -285,14 +261,14 @@ def event_handler(event): ...@@ -285,14 +261,14 @@ def event_handler(event):
result.metrics['classification_error_evaluator'])) result.metrics['classification_error_evaluator']))
``` ```
Now that we setup the event_handler and the reader, we can start training the model. `feed_order` is used to map the data dict to the train_program
```python ```python
trainer.train( trainer.train(
reader=paddle.batch( num_epochs=1,
paddle.reader.shuffle( event_handler=event_handler,
paddle.dataset.mnist.train(), buf_size=8192), reader=train_reader,
batch_size=128), feed_order=['img', 'label'])
event_handler=event_handler_plot,
num_passes=5)
``` ```
训练过程是完全自动的,event_handler里打印的日志类似如下所示: 训练过程是完全自动的,event_handler里打印的日志类似如下所示:
...@@ -311,27 +287,25 @@ trainer.train( ...@@ -311,27 +287,25 @@ trainer.train(
## 应用模型 ## 应用模型
可以使用训练好的模型对手写体数字图片进行分类,下面程序展示了如何使用paddle.infer接口进行推断。 可以使用训练好的模型对手写体数字图片进行分类,下面程序展示了如何使用 `fluid.Inferencer` 接口进行推断。
```python ```python
from PIL import Image inferencer = fluid.Inferencer(
import numpy as np # infer_func=softmax_regression, # uncomment for softmax regression
import os # infer_func=multilayer_perceptron, # uncomment for MLP
def load_image(file): infer_func=convolutional_neural_network, # uncomment for LeNet5
im = Image.open(file).convert('L') param_path=params_dirname,
im = im.resize((28, 28), Image.ANTIALIAS) place=place)
im = np.array(im).astype(np.float32).flatten()
im = im / 255.0 * 2.0 - 1.0 batch_size = 1
return im import numpy
tensor_img = numpy.random.uniform(-1.0, 1.0,
test_data = [] [batch_size, 1, 28, 28]).astype("float32")
cur_dir = os.getcwd()
test_data.append((load_image(cur_dir + '/image/infer_3.png'),)) results = inferencer.infer({'img': tensor_img})
probs = paddle.infer( print("infer results: ", results[0])
output_layer=predict, parameters=parameters, input=test_data)
lab = np.argsort(-probs) # probs and lab are the results of one batch data
print "Label of image/infer_3.png is: %d" % lab[0][0]
``` ```
## 总结 ## 总结
......
此差异已折叠。
...@@ -171,17 +171,18 @@ PaddlePaddle在API中提供了自动加载[MNIST](http://yann.lecun.com/exdb/mni ...@@ -171,17 +171,18 @@ PaddlePaddle在API中提供了自动加载[MNIST](http://yann.lecun.com/exdb/mni
## 配置说明 ## 配置说明
首先,加载PaddlePaddle的V2 api包。 首先,加载PaddlePaddle的fluid api包。
```python ```python
import paddle.v2 as paddle import paddle.fluid as fluid
``` ```
其次,定义三个不同的分类器: 其次,定义三个不同的分类器:
- Softmax回归:只通过一层简单的以softmax为激活函数的全连接层,就可以得到分类的结果。 - Softmax回归:只通过一层简单的以softmax为激活函数的全连接层,就可以得到分类的结果。
```python ```python
def softmax_regression(img): def softmax_regression():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
predict = paddle.layer.fc(input=img, predict = paddle.layer.fc(input=img,
size=10, size=10,
act=paddle.activation.Softmax()) act=paddle.activation.Softmax())
...@@ -190,64 +191,59 @@ def softmax_regression(img): ...@@ -190,64 +191,59 @@ def softmax_regression(img):
- 多层感知器:下面代码实现了一个含有两个隐藏层(即全连接层)的多层感知器。其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax。 - 多层感知器:下面代码实现了一个含有两个隐藏层(即全连接层)的多层感知器。其中两个隐藏层的激活函数均采用ReLU,输出层的激活函数用Softmax。
```python ```python
def multilayer_perceptron(img): def multilayer_perceptron():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
# 第一个全连接层,激活函数为ReLU # 第一个全连接层,激活函数为ReLU
hidden1 = paddle.layer.fc(input=img, size=128, act=paddle.activation.Relu()) hidden = fluid.layers.fc(input=img, size=200, act='relu')
# 第二个全连接层,激活函数为ReLU # 第二个全连接层,激活函数为ReLU
hidden2 = paddle.layer.fc(input=hidden1, hidden = fluid.layers.fc(input=hidden, size=200, act='relu')
size=64,
act=paddle.activation.Relu())
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10 # 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=hidden2, prediction = fluid.layers.fc(input=hidden, size=10, act='softmax')
size=10, return prediction
act=paddle.activation.Softmax())
return predict
``` ```
- 卷积神经网络LeNet-5: 输入的二维图像,首先经过两次卷积层到池化层,再经过全连接层,最后使用以softmax为激活函数的全连接层作为输出层。 - 卷积神经网络LeNet-5: 输入的二维图像,首先经过两次卷积层到池化层,再经过全连接层,最后使用以softmax为激活函数的全连接层作为输出层。
```python ```python
def convolutional_neural_network(img): def convolutional_neural_network():
img = fluid.layers.data(name='img', shape=[1, 28, 28], dtype='float32')
# 第一个卷积-池化层 # 第一个卷积-池化层
conv_pool_1 = paddle.networks.simple_img_conv_pool( conv_pool_1 = fluid.nets.simple_img_conv_pool(
input=img, input=img,
filter_size=5, filter_size=5,
num_filters=20, num_filters=20,
num_channel=1,
pool_size=2, pool_size=2,
pool_stride=2, pool_stride=2,
act=paddle.activation.Relu()) act="relu")
conv_pool_1 = fluid.layers.batch_norm(conv_pool_1)
# 第二个卷积-池化层 # 第二个卷积-池化层
conv_pool_2 = paddle.networks.simple_img_conv_pool( conv_pool_2 = fluid.nets.simple_img_conv_pool(
input=conv_pool_1, input=conv_pool_1,
filter_size=5, filter_size=5,
num_filters=50, num_filters=50,
num_channel=20,
pool_size=2, pool_size=2,
pool_stride=2, pool_stride=2,
act=paddle.activation.Relu()) act="relu")
# 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10 # 以softmax为激活函数的全连接输出层,输出层的大小必须为数字的个数10
predict = paddle.layer.fc(input=conv_pool_2, prediction = fluid.layers.fc(input=conv_pool_2, size=10, act='softmax')
size=10, return prediction
act=paddle.activation.Softmax())
return predict
``` ```
接着,通过`layer.data`调用来获取数据,然后调用分类器(这里我们提供了三个不同的分类器)得到分类结果。训练时,对该结果计算其损失函数,分类问题常常选择交叉熵损失函数。 接着,通过`layer.data`调用来获取数据,然后调用分类器(这里我们提供了三个不同的分类器)得到分类结果。训练时,对该结果计算其损失函数,分类问题常常选择交叉熵损失函数。
```python ```python
# 该模型运行在单个CPU上 def train_program():
paddle.init(use_gpu=False, trainer_count=1) label = fluid.layers.data(name='label', shape=[1], dtype='int64')
images = paddle.layer.data( # predict = softmax_regression(images) # uncomment for Softmax回归
name='pixel', type=paddle.data_type.dense_vector(784)) # predict = multilayer_perceptron() # uncomment for 多层感知器
label = paddle.layer.data( predict = convolutional_neural_network() # uncomment for LeNet5卷积神经网络
name='label', type=paddle.data_type.integer_value(10)) cost = fluid.layers.cross_entropy(input=predict, label=label)
avg_cost = fluid.layers.mean(cost)
acc = fluid.layers.accuracy(input=predict, label=label)
return [avg_cost, acc]
# predict = softmax_regression(images) # Softmax回归
# predict = multilayer_perceptron(images) #多层感知器
predict = convolutional_neural_network(images) #LeNet5卷积神经网络
cost = paddle.layer.classification_cost(input=predict, label=label) # 该模型运行在单个CPU上
``` ```
然后,指定训练相关的参数。 然后,指定训练相关的参数。
...@@ -256,16 +252,16 @@ cost = paddle.layer.classification_cost(input=predict, label=label) ...@@ -256,16 +252,16 @@ cost = paddle.layer.classification_cost(input=predict, label=label)
- 正则化(regularization): 是防止网络过拟合的一种手段,此处采用L2正则化。 - 正则化(regularization): 是防止网络过拟合的一种手段,此处采用L2正则化。
```python ```python
parameters = paddle.parameters.create(cost) # 该模型运行在单个CPU上
use_cude = False # set to True if training with GPU
place = fluid.CUDAPlace(0) if use_cuda else fluid.CPUPlace()
optimizer = paddle.optimizer.Momentum( optimizer = paddle.optimizer.Momentum(
learning_rate=0.1 / 128.0, learning_rate=0.1 / 128.0,
momentum=0.9, momentum=0.9,
regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128)) regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128))
trainer = paddle.trainer.SGD(cost=cost, trainer = fluid.Trainer(
parameters=parameters, train_func=train_program, place=place, optimizer=optimizer)
update_equation=optimizer)
``` ```
下一步,我们开始训练过程。`paddle.dataset.movielens.train()`和`paddle.dataset.movielens.test()`分别做训练和测试数据集。这两个函数各自返回一个reader——PaddlePaddle中的reader是一个Python函数,每次调用的时候返回一个Python yield generator。 下一步,我们开始训练过程。`paddle.dataset.movielens.train()`和`paddle.dataset.movielens.test()`分别做训练和测试数据集。这两个函数各自返回一个reader——PaddlePaddle中的reader是一个Python函数,每次调用的时候返回一个Python yield generator。
...@@ -274,38 +270,18 @@ trainer = paddle.trainer.SGD(cost=cost, ...@@ -274,38 +270,18 @@ trainer = paddle.trainer.SGD(cost=cost,
`batch`是一个特殊的decorator,它的输入是一个reader,输出是一个batched reader —— 在PaddlePaddle里,一个reader每次yield一条训练数据,而一个batched reader每次yield一个minibatch。 `batch`是一个特殊的decorator,它的输入是一个reader,输出是一个batched reader —— 在PaddlePaddle里,一个reader每次yield一条训练数据,而一个batched reader每次yield一个minibatch。
`event_handler_plot`可以用来在训练过程中画图如下:
![png](./image/train_and_test.png)
```python ```python
from paddle.v2.plot import Ploter train_reader = paddle.batch(
paddle.reader.shuffle(
train_title = "Train cost" paddle.dataset.mnist.train(), buf_size=500),
test_title = "Test cost" batch_size=64)
cost_ploter = Ploter(train_title, test_title)
step = 0
# event_handler to plot a figure
def event_handler_plot(event):
global step
if isinstance(event, paddle.event.EndIteration):
if step % 100 == 0:
cost_ploter.append(train_title, step, event.cost)
cost_ploter.plot()
step += 1
if isinstance(event, paddle.event.EndPass):
# save parameters
with open('params_pass_%d.tar' % event.pass_id, 'w') as f:
trainer.save_parameter_to_tar(f)
result = trainer.test(reader=paddle.batch( test_reader = paddle.batch(
paddle.dataset.mnist.test(), batch_size=128)) paddle.dataset.mnist.test(), batch_size=64)
cost_ploter.append(test_title, step, result.cost)
``` ```
`event_handler` 用来在训练过程中输出训练结果 `event_handler` 用来在训练过程中输出训练结果
```python ```python
lists = [] lists = []
...@@ -327,14 +303,14 @@ def event_handler(event): ...@@ -327,14 +303,14 @@ def event_handler(event):
result.metrics['classification_error_evaluator'])) result.metrics['classification_error_evaluator']))
``` ```
Now that we setup the event_handler and the reader, we can start training the model. `feed_order` is used to map the data dict to the train_program
```python ```python
trainer.train( trainer.train(
reader=paddle.batch( num_epochs=1,
paddle.reader.shuffle( event_handler=event_handler,
paddle.dataset.mnist.train(), buf_size=8192), reader=train_reader,
batch_size=128), feed_order=['img', 'label'])
event_handler=event_handler_plot,
num_passes=5)
``` ```
训练过程是完全自动的,event_handler里打印的日志类似如下所示: 训练过程是完全自动的,event_handler里打印的日志类似如下所示:
...@@ -353,27 +329,25 @@ trainer.train( ...@@ -353,27 +329,25 @@ trainer.train(
## 应用模型 ## 应用模型
可以使用训练好的模型对手写体数字图片进行分类,下面程序展示了如何使用paddle.infer接口进行推断。 可以使用训练好的模型对手写体数字图片进行分类,下面程序展示了如何使用 `fluid.Inferencer` 接口进行推断。
```python ```python
from PIL import Image inferencer = fluid.Inferencer(
import numpy as np # infer_func=softmax_regression, # uncomment for softmax regression
import os # infer_func=multilayer_perceptron, # uncomment for MLP
def load_image(file): infer_func=convolutional_neural_network, # uncomment for LeNet5
im = Image.open(file).convert('L') param_path=params_dirname,
im = im.resize((28, 28), Image.ANTIALIAS) place=place)
im = np.array(im).astype(np.float32).flatten()
im = im / 255.0 * 2.0 - 1.0 batch_size = 1
return im import numpy
tensor_img = numpy.random.uniform(-1.0, 1.0,
test_data = [] [batch_size, 1, 28, 28]).astype("float32")
cur_dir = os.getcwd()
test_data.append((load_image(cur_dir + '/image/infer_3.png'),)) results = inferencer.infer({'img': tensor_img})
probs = paddle.infer( print("infer results: ", results[0])
output_layer=predict, parameters=parameters, input=test_data)
lab = np.argsort(-probs) # probs and lab are the results of one batch data
print "Label of image/infer_3.png is: %d" % lab[0][0]
``` ```
## 总结 ## 总结
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册