From 78693ca6b19ee96d1a8a518843b08e8079df3f8a Mon Sep 17 00:00:00 2001 From: junjun315 Date: Mon, 22 Apr 2019 14:19:34 +0000 Subject: [PATCH] update dygraph models:mnist, move resnet, test=develop --- dygraph/mnist/README_cn.md | 42 +++- .../mnist/image/infer_3.png | Bin dygraph/mnist/mnist_dygraph.py | 120 ++++++++--- {fluid/dygraph => dygraph}/resnet/README.md | 0 {fluid/dygraph => dygraph}/resnet/train.py | 0 fluid/dygraph/mnist/README_cn.md | 62 ------ fluid/dygraph/mnist/mnist_dygraph.py | 202 ------------------ 7 files changed, 132 insertions(+), 294 deletions(-) rename {fluid/dygraph => dygraph}/mnist/image/infer_3.png (100%) rename {fluid/dygraph => dygraph}/resnet/README.md (100%) rename {fluid/dygraph => dygraph}/resnet/train.py (100%) delete mode 100644 fluid/dygraph/mnist/README_cn.md delete mode 100644 fluid/dygraph/mnist/mnist_dygraph.py diff --git a/dygraph/mnist/README_cn.md b/dygraph/mnist/README_cn.md index fe28a394..867f7518 100644 --- a/dygraph/mnist/README_cn.md +++ b/dygraph/mnist/README_cn.md @@ -1,6 +1,6 @@ # MNIST 当我们学习编程的时候,编写的第一个程序一般是实现打印"Hello World"。而机器学习(或深度学习)的入门教程,一般都是 MNIST 数据库上的手写识别问题。原因是手写识别属于典型的图像分类问题,比较简单,同时MNIST数据集也很完备。 -本页将介绍如何使用PaddlePaddle在DyGraph模式下实现MNIST,包括[安装](#installation)、[训练](#training-a-model)、[输出](#log)。 +本页将介绍如何使用PaddlePaddle在DyGraph模式下实现MNIST,包括[安装](#installation)、[训练](#training-a-model)、[输出](#log)、[参数保存](#save)、[模型评估](#evaluation)。 --- ## 内容 @@ -21,8 +21,42 @@ env CUDA_VISIBLE_DEVICES=0 python mnist_dygraph.py ## 输出 执行训练开始后,将得到类似如下的输出。 ``` -batch_id 0,loss 2.1786134243 -batch_id 10,loss 0.898496925831 -batch_id 20,loss 1.32524681091 +Loss at epoch 0 step 0: [2.3043773] +Loss at epoch 0 step 100: [0.20764539] +Loss at epoch 0 step 200: [0.18648806] +Loss at epoch 0 step 300: [0.10279777] +Loss at epoch 0 step 400: [0.03940877] ... ``` + +## 参数保存 +调用`fluid.dygraph.save_persistables()`接口可以把模型的参数进行保存。 +```python +fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir") +``` + +## 测试 +执行`mnist.eval()`可以切换至评估状态,即不更新只使用参数进行训练,通过这种方式进行测试或者评估。 +```python +mnist.eval() +``` + +## 模型评估 +我们使用手写数据集中的一张图片来进行评估。为了区别训练模型,我们使用`with fluid.dygraph.guard()`来切换到一个新的参数空间,然后构建一个用于评估的网络`mnist_infer`,并通过`mnist_infer.load_dict()`来加载使用`fluid.dygraph.load_persistables`读取的参数。然后用`mnist_infer.eval()`切换到评估。 +```python +with fluid.dygraph.guard(): + + mnist_infer = MNIST("mnist") + # load checkpoint + mnist_infer.load_dict( + fluid.dygraph.load_persistables("save_dir")) + + # start evaluate mode + mnist_infer.eval() +``` +如果无意外,将可以看到预测的结果: +```text +Inference result of image/infer_3.png is: 3 +``` + + diff --git a/fluid/dygraph/mnist/image/infer_3.png b/dygraph/mnist/image/infer_3.png similarity index 100% rename from fluid/dygraph/mnist/image/infer_3.png rename to dygraph/mnist/image/infer_3.png diff --git a/dygraph/mnist/mnist_dygraph.py b/dygraph/mnist/mnist_dygraph.py index 0d471102..ed1a0824 100644 --- a/dygraph/mnist/mnist_dygraph.py +++ b/dygraph/mnist/mnist_dygraph.py @@ -1,20 +1,30 @@ +# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + from __future__ import print_function -import contextlib import numpy as np -import six - +from PIL import Image +import os import paddle import paddle.fluid as fluid -from paddle.fluid.optimizer import SGDOptimizer +from paddle.fluid.optimizer import AdamOptimizer from paddle.fluid.dygraph.nn import Conv2D, Pool2D, FC from paddle.fluid.dygraph.base import to_variable class SimpleImgConvPool(fluid.dygraph.Layer): - """ - Conv Pool Layer - """ def __init__(self, name_scope, num_channels, @@ -64,9 +74,6 @@ class SimpleImgConvPool(fluid.dygraph.Layer): class MNIST(fluid.dygraph.Layer): - """ - MNIST model - """ def __init__(self, name_scope): super(MNIST, self).__init__(name_scope) @@ -86,49 +93,110 @@ class MNIST(fluid.dygraph.Layer): loc=0.0, scale=scale)), act="softmax") - def forward(self, inputs): + def forward(self, inputs, label=None): x = self._simple_img_conv_pool_1(inputs) x = self._simple_img_conv_pool_2(x) x = self._fc(x) - return x + if label is not None: + acc = fluid.layers.accuracy(input=x, label=label) + return x, acc + else: + return x + + +def test_train(reader, model, batch_size): + acc_set = [] + avg_loss_set = [] + for batch_id, data in enumerate(reader()): + dy_x_data = np.array( + [x[0].reshape(1, 28, 28) + for x in data]).astype('float32') + y_data = np.array( + [x[1] for x in data]).astype('int64').reshape(batch_size, 1) + + img = to_variable(dy_x_data) + label = to_variable(y_data) + label.stop_gradient = True + prediction, acc = model(img, label) + loss = fluid.layers.cross_entropy(input=prediction, label=label) + avg_loss = fluid.layers.mean(loss) + acc_set.append(float(acc.numpy())) + avg_loss_set.append(float(avg_loss.numpy())) + + # get test acc and loss + acc_val_mean = np.array(acc_set).mean() + avg_loss_val_mean = np.array(avg_loss_set).mean() + + return avg_loss_val_mean, acc_val_mean def train_mnist(): - seed = 90 - epoch_num = 10 - + epoch_num = 5 + BATCH_SIZE = 64 with fluid.dygraph.guard(): - fluid.default_startup_program().random_seed = seed - fluid.default_main_program().random_seed = seed mnist = MNIST("mnist") - sgd = SGDOptimizer(learning_rate=1e-3) + adam = AdamOptimizer(learning_rate=0.001) train_reader = paddle.batch( - paddle.dataset.mnist.train(), batch_size=128, drop_last=True) - + paddle.dataset.mnist.train(), batch_size=BATCH_SIZE, drop_last=True) + test_reader = paddle.batch( + paddle.dataset.mnist.test(), batch_size=BATCH_SIZE, drop_last=True) for epoch in range(epoch_num): for batch_id, data in enumerate(train_reader()): dy_x_data = np.array( [x[0].reshape(1, 28, 28) for x in data]).astype('float32') y_data = np.array( - [x[1] for x in data]).astype('int64').reshape(128, 1) + [x[1] for x in data]).astype('int64').reshape(BATCH_SIZE, 1) img = to_variable(dy_x_data) label = to_variable(y_data) label.stop_gradient = True - cost = mnist(img) + cost, acc = mnist(img, label) + loss = fluid.layers.cross_entropy(cost, label) avg_loss = fluid.layers.mean(loss) avg_loss.backward() - sgd.minimize(avg_loss) + adam.minimize(avg_loss) + # save checkpoint mnist.clear_gradients() + if batch_id % 100 == 0: + print("Loss at epoch {} step {}: {:}".format(epoch, batch_id, avg_loss.numpy())) + + mnist.eval() + test_cost, test_acc = test_train(test_reader, mnist, BATCH_SIZE) + mnist.train() + print("Loss at epoch {} , Test avg_loss is: {}, acc is: {}".format(epoch, test_cost, test_acc)) - dy_out = avg_loss.numpy() - print("batch id %d, loss %f" % (batch_id, dy_out)) + fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir") + print("checkpoint saved") + + with fluid.dygraph.guard(): + + mnist_infer = MNIST("mnist") + # load checkpoint + mnist_infer.load_dict( + fluid.dygraph.load_persistables("save_dir")) + print("checkpoint loaded") + + # start evaluate mode + mnist_infer.eval() + + def load_image(file): + im = Image.open(file).convert('L') + im = im.resize((28, 28), Image.ANTIALIAS) + im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32) + im = im / 255.0 * 2.0 - 1.0 + return im + + cur_dir = os.path.dirname(os.path.realpath(__file__)) + tensor_img = load_image(cur_dir + '/image/infer_3.png') + + results = mnist_infer(to_variable(tensor_img)) + lab = np.argsort(results.numpy()) + print("Inference result of image/infer_3.png is: %d" % lab[0][-1]) if __name__ == '__main__': train_mnist() - diff --git a/fluid/dygraph/resnet/README.md b/dygraph/resnet/README.md similarity index 100% rename from fluid/dygraph/resnet/README.md rename to dygraph/resnet/README.md diff --git a/fluid/dygraph/resnet/train.py b/dygraph/resnet/train.py similarity index 100% rename from fluid/dygraph/resnet/train.py rename to dygraph/resnet/train.py diff --git a/fluid/dygraph/mnist/README_cn.md b/fluid/dygraph/mnist/README_cn.md deleted file mode 100644 index 867f7518..00000000 --- a/fluid/dygraph/mnist/README_cn.md +++ /dev/null @@ -1,62 +0,0 @@ -# MNIST -当我们学习编程的时候,编写的第一个程序一般是实现打印"Hello World"。而机器学习(或深度学习)的入门教程,一般都是 MNIST 数据库上的手写识别问题。原因是手写识别属于典型的图像分类问题,比较简单,同时MNIST数据集也很完备。 -本页将介绍如何使用PaddlePaddle在DyGraph模式下实现MNIST,包括[安装](#installation)、[训练](#training-a-model)、[输出](#log)、[参数保存](#save)、[模型评估](#evaluation)。 - ---- -## 内容 -- [安装](#installation) -- [训练](#training-a-model) -- [输出](#log) - -## 安装 - -在当前目录下运行样例代码需要PadddlePaddle Fluid的v1.4.0或以上的版本。如果你的运行环境中的PaddlePaddle低于此版本,请根据安装文档中的说明来更新PaddlePaddle。 - -## 训练 -教程中使用`paddle.dataset.mnist`数据集作为训练数据,可以通过如下的方式启动训练: -``` -env CUDA_VISIBLE_DEVICES=0 python mnist_dygraph.py -``` - -## 输出 -执行训练开始后,将得到类似如下的输出。 -``` -Loss at epoch 0 step 0: [2.3043773] -Loss at epoch 0 step 100: [0.20764539] -Loss at epoch 0 step 200: [0.18648806] -Loss at epoch 0 step 300: [0.10279777] -Loss at epoch 0 step 400: [0.03940877] -... -``` - -## 参数保存 -调用`fluid.dygraph.save_persistables()`接口可以把模型的参数进行保存。 -```python -fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir") -``` - -## 测试 -执行`mnist.eval()`可以切换至评估状态,即不更新只使用参数进行训练,通过这种方式进行测试或者评估。 -```python -mnist.eval() -``` - -## 模型评估 -我们使用手写数据集中的一张图片来进行评估。为了区别训练模型,我们使用`with fluid.dygraph.guard()`来切换到一个新的参数空间,然后构建一个用于评估的网络`mnist_infer`,并通过`mnist_infer.load_dict()`来加载使用`fluid.dygraph.load_persistables`读取的参数。然后用`mnist_infer.eval()`切换到评估。 -```python -with fluid.dygraph.guard(): - - mnist_infer = MNIST("mnist") - # load checkpoint - mnist_infer.load_dict( - fluid.dygraph.load_persistables("save_dir")) - - # start evaluate mode - mnist_infer.eval() -``` -如果无意外,将可以看到预测的结果: -```text -Inference result of image/infer_3.png is: 3 -``` - - diff --git a/fluid/dygraph/mnist/mnist_dygraph.py b/fluid/dygraph/mnist/mnist_dygraph.py deleted file mode 100644 index ed1a0824..00000000 --- a/fluid/dygraph/mnist/mnist_dygraph.py +++ /dev/null @@ -1,202 +0,0 @@ -# Copyright (c) 2018 PaddlePaddle Authors. All Rights Reserved. -# -# Licensed under the Apache License, Version 2.0 (the "License"); -# you may not use this file except in compliance with the License. -# You may obtain a copy of the License at -# -# http://www.apache.org/licenses/LICENSE-2.0 -# -# Unless required by applicable law or agreed to in writing, software -# distributed under the License is distributed on an "AS IS" BASIS, -# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -# See the License for the specific language governing permissions and -# limitations under the License. - -from __future__ import print_function - -import numpy as np -from PIL import Image -import os -import paddle -import paddle.fluid as fluid -from paddle.fluid.optimizer import AdamOptimizer -from paddle.fluid.dygraph.nn import Conv2D, Pool2D, FC -from paddle.fluid.dygraph.base import to_variable - - -class SimpleImgConvPool(fluid.dygraph.Layer): - def __init__(self, - name_scope, - num_channels, - num_filters, - filter_size, - pool_size, - pool_stride, - pool_padding=0, - pool_type='max', - global_pooling=False, - conv_stride=1, - conv_padding=0, - conv_dilation=1, - conv_groups=1, - act=None, - use_cudnn=False, - param_attr=None, - bias_attr=None): - super(SimpleImgConvPool, self).__init__(name_scope) - - self._conv2d = Conv2D( - self.full_name(), - num_channels=num_channels, - num_filters=num_filters, - filter_size=filter_size, - stride=conv_stride, - padding=conv_padding, - dilation=conv_dilation, - groups=conv_groups, - param_attr=None, - bias_attr=None, - use_cudnn=use_cudnn) - - self._pool2d = Pool2D( - self.full_name(), - pool_size=pool_size, - pool_type=pool_type, - pool_stride=pool_stride, - pool_padding=pool_padding, - global_pooling=global_pooling, - use_cudnn=use_cudnn) - - def forward(self, inputs): - x = self._conv2d(inputs) - x = self._pool2d(x) - return x - - -class MNIST(fluid.dygraph.Layer): - def __init__(self, name_scope): - super(MNIST, self).__init__(name_scope) - - self._simple_img_conv_pool_1 = SimpleImgConvPool( - self.full_name(), 1, 20, 5, 2, 2, act="relu") - - self._simple_img_conv_pool_2 = SimpleImgConvPool( - self.full_name(), 20, 50, 5, 2, 2, act="relu") - - pool_2_shape = 50 * 4 * 4 - SIZE = 10 - scale = (2.0 / (pool_2_shape**2 * SIZE))**0.5 - self._fc = FC(self.full_name(), - 10, - param_attr=fluid.param_attr.ParamAttr( - initializer=fluid.initializer.NormalInitializer( - loc=0.0, scale=scale)), - act="softmax") - - def forward(self, inputs, label=None): - x = self._simple_img_conv_pool_1(inputs) - x = self._simple_img_conv_pool_2(x) - x = self._fc(x) - if label is not None: - acc = fluid.layers.accuracy(input=x, label=label) - return x, acc - else: - return x - - -def test_train(reader, model, batch_size): - acc_set = [] - avg_loss_set = [] - for batch_id, data in enumerate(reader()): - dy_x_data = np.array( - [x[0].reshape(1, 28, 28) - for x in data]).astype('float32') - y_data = np.array( - [x[1] for x in data]).astype('int64').reshape(batch_size, 1) - - img = to_variable(dy_x_data) - label = to_variable(y_data) - label.stop_gradient = True - prediction, acc = model(img, label) - loss = fluid.layers.cross_entropy(input=prediction, label=label) - avg_loss = fluid.layers.mean(loss) - acc_set.append(float(acc.numpy())) - avg_loss_set.append(float(avg_loss.numpy())) - - # get test acc and loss - acc_val_mean = np.array(acc_set).mean() - avg_loss_val_mean = np.array(avg_loss_set).mean() - - return avg_loss_val_mean, acc_val_mean - - -def train_mnist(): - epoch_num = 5 - BATCH_SIZE = 64 - with fluid.dygraph.guard(): - - mnist = MNIST("mnist") - adam = AdamOptimizer(learning_rate=0.001) - train_reader = paddle.batch( - paddle.dataset.mnist.train(), batch_size=BATCH_SIZE, drop_last=True) - test_reader = paddle.batch( - paddle.dataset.mnist.test(), batch_size=BATCH_SIZE, drop_last=True) - for epoch in range(epoch_num): - for batch_id, data in enumerate(train_reader()): - dy_x_data = np.array( - [x[0].reshape(1, 28, 28) - for x in data]).astype('float32') - y_data = np.array( - [x[1] for x in data]).astype('int64').reshape(BATCH_SIZE, 1) - - img = to_variable(dy_x_data) - label = to_variable(y_data) - label.stop_gradient = True - - cost, acc = mnist(img, label) - - loss = fluid.layers.cross_entropy(cost, label) - avg_loss = fluid.layers.mean(loss) - avg_loss.backward() - adam.minimize(avg_loss) - # save checkpoint - mnist.clear_gradients() - if batch_id % 100 == 0: - print("Loss at epoch {} step {}: {:}".format(epoch, batch_id, avg_loss.numpy())) - - mnist.eval() - test_cost, test_acc = test_train(test_reader, mnist, BATCH_SIZE) - mnist.train() - print("Loss at epoch {} , Test avg_loss is: {}, acc is: {}".format(epoch, test_cost, test_acc)) - - fluid.dygraph.save_persistables(mnist.state_dict(), "save_dir") - print("checkpoint saved") - - with fluid.dygraph.guard(): - - mnist_infer = MNIST("mnist") - # load checkpoint - mnist_infer.load_dict( - fluid.dygraph.load_persistables("save_dir")) - print("checkpoint loaded") - - # start evaluate mode - mnist_infer.eval() - - def load_image(file): - im = Image.open(file).convert('L') - im = im.resize((28, 28), Image.ANTIALIAS) - im = np.array(im).reshape(1, 1, 28, 28).astype(np.float32) - im = im / 255.0 * 2.0 - 1.0 - return im - - cur_dir = os.path.dirname(os.path.realpath(__file__)) - tensor_img = load_image(cur_dir + '/image/infer_3.png') - - results = mnist_infer(to_variable(tensor_img)) - lab = np.argsort(results.numpy()) - print("Inference result of image/infer_3.png is: %d" % lab[0][-1]) - - -if __name__ == '__main__': - train_mnist() -- GitLab