From 593995dc35439c5cc6fa22300f044917aa4dc0d3 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 15:28:38 +0800 Subject: [PATCH 1/7] demo mxnet --- demo/mxnet/TUTORIAL_CN.md | 60 +++++++++++++++++++++++ demo/mxnet/epoch2_small.png | Bin 0 -> 30633 bytes demo/mxnet/mxnet_demo.py | 92 ++++++++++++++++++++++++++++++++++++ 3 files changed, 152 insertions(+) create mode 100644 demo/mxnet/TUTORIAL_CN.md create mode 100644 demo/mxnet/epoch2_small.png create mode 100644 demo/mxnet/mxnet_demo.py diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md new file mode 100644 index 000000000..4d9014024 --- /dev/null +++ b/demo/mxnet/TUTORIAL_CN.md @@ -0,0 +1,60 @@ +# 在MXNet中使用VisualDL + +下面我们演示一下如何在MXNet中使用VisualDL,从而可以把MXNet的训练过程以及最后的模型可视化出来。我们将以MXNet用卷积神经网络(CNN, Convolutional Neural Network)来训练[MNIST](http://yann.lecun.com/exdb/mnist/)数据集作为例子。 + +- [安装MXNet](#安装MXNet) +- [安装VisualDL](#安装VisualDL) +- [开始编写训练MNIST的程序](#开始编写训练MNIST的程序) + +## 安装MXNet +请按照MXNet的[官方网站](https://mxnet.incubator.apache.org/get_started/install.html)来安装MXNet,并验证安装成功。 + + + >>> import mxnet as mx + >>> a = mx.nd.ones((2, 3)) + >>> b = a * 2 + 1 + >>> b.asnumpy() + array([[ 3., 3., 3.], + [ 3., 3., 3.]], dtype=float32) + +## 安装VisualDL +VisualDL的安装很简单。请按照VisualDL的[官方网站](https://github.com/PaddlePaddle/VisualDL)进行安装。具体只需要两步 + +``` +python setup.py bdist_wheel +pip install --upgrade dist/visualdl-0.0.1-py2-none-any.whl +``` + +## 开始编写训练MNIST的程序 + +我们为您提供了一个演示程序 [mxnet_demo.py](https://github.com/PaddlePaddle/VisualDL/blob/mxnet_demo/demo/mxnet/mxnet_demo.py)。里面展示了如何下载MNIST数据集以及编写MXNet程序来进行CNN的训练。MXNet的部分借鉴了MXNet[官方入门文件](https://mxnet.incubator.apache.org/tutorials/python/mnist.html) +为了嵌入VisualDL程序,以便在MXNet训练时进行检测,我们需要声明一个logger实例: + +``` +logger = LogWriter(logdir, sync_cycle=10) +``` + +logger实例里面包含VisualDL的四个功能模块 Scalar, Image, Graph 以及 Histogram。这里我们使用 Scalar 模块: + +``` +scalar0 = logger.scalar("scalars/scalar0") +``` + +模块的命名可以有 '/', 以便对于复杂模型创建不同的命名空间。 + +MXNet在fit函数中提供了很多[API](https://mxnet.incubator.apache.org/api/python/index.html)。我们把自己编写好的回调函数 add_scalar 插入到相应的 API中 + +``` +lenet_model.fit(train_iter, + eval_data=val_iter, + optimizer='sgd', + optimizer_params={'learning_rate':0.1}, + eval_metric='acc', + # 在此嵌入我们自定义的回调函数 + batch_end_callback=[add_scalar()], + num_epoch=2) +``` + +这样就好了。在MXNet的训练过程中,每一个批次(batch)训练完后,都会调用我们的回调函数来对准确率进行记录。如您所料,随着训练的进行,准确率会不断上升直到95%以上。以下是两个epoch训练过后的准确率走向: + +

diff --git a/demo/mxnet/epoch2_small.png b/demo/mxnet/epoch2_small.png new file mode 100644 index 0000000000000000000000000000000000000000..0779166af4e0467e9131451f01e344129b9e629e GIT binary patch literal 30633 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 Yzj36*>Pdq=NV((EMe_@V=dOqS2MADq>Hq)$ literal 0 HcmV?d00001 diff --git a/demo/mxnet/mxnet_demo.py b/demo/mxnet/mxnet_demo.py new file mode 100644 index 000000000..437d4926b --- /dev/null +++ b/demo/mxnet/mxnet_demo.py @@ -0,0 +1,92 @@ +import mxnet as mx +import numpy + +# 引入VisualDL +from visualdl import LogWriter + +# 下载MNIST数据集 +mnist = mx.test_utils.get_mnist() +batch_size = 100 + + +# 给VisualDL指定一个文件夹,用来存储日志,模型,图片等数据,供可视化使用 +logdir = "./tmp" + +# 创建一个logger实例,sync_cycle是读取内存的频率,意思是每十次内存操作,会读取一次数据 +logger = LogWriter(logdir, sync_cycle=10) + +# mark the components with 'train' label. +with logger.mode("train"): + # 这里scalar0 用来记录MXNet训练过程中的数值信息。我们将记录随着训练的进行,我们的准确率会不断降低 + scalar0 = logger.scalar("scalars/scalar0") + +# 记录训练步数 +cnt_step = 0 + + +# MXNet提供了许多回调函数的接口,这里我们定义我们自己的回调函数,在每个训练批次(batch)结束时调用 +# https://mxnet.incubator.apache.org/api/python/callback/callback.html +def add_scalar(): + def _callback(param): + with logger.mode("train"): + global cnt_step + # 这里的value是我们要记录的准确率accuracy + # https://mxnet.incubator.apache.org/_modules/mxnet/callback.html + name_value = param.eval_metric.get_name_value() + for name, value in name_value: + scalar0.add_record(cnt_step, value) + cnt_step += 1 + return _callback + + +# 开始用MXNet建立CNN,训练MNIST数据集,详情请参见MXNet官方网站 +# https://mxnet.incubator.apache.org/tutorials/python/mnist.html + +import logging +logging.getLogger().setLevel(logging.DEBUG) # logging to stdout + +train_iter = mx.io.NDArrayIter(mnist['train_data'], mnist['train_label'], batch_size, shuffle=True) +val_iter = mx.io.NDArrayIter(mnist['test_data'], mnist['test_label'], batch_size) + +data = mx.sym.var('data') +# first conv layer +conv1 = mx.sym.Convolution(data=data, kernel=(5,5), num_filter=20) +tanh1 = mx.sym.Activation(data=conv1, act_type="tanh") +pool1 = mx.sym.Pooling(data=tanh1, pool_type="max", kernel=(2,2), stride=(2,2)) +# second conv layer +conv2 = mx.sym.Convolution(data=pool1, kernel=(5,5), num_filter=50) +tanh2 = mx.sym.Activation(data=conv2, act_type="tanh") +pool2 = mx.sym.Pooling(data=tanh2, pool_type="max", kernel=(2,2), stride=(2,2)) +# first fullc layer +flatten = mx.sym.flatten(data=pool2) +fc1 = mx.symbol.FullyConnected(data=flatten, num_hidden=500) +tanh3 = mx.sym.Activation(data=fc1, act_type="tanh") +# second fullc +fc2 = mx.sym.FullyConnected(data=tanh3, num_hidden=10) +# softmax loss +lenet = mx.sym.SoftmaxOutput(data=fc2, name='softmax') + +# create a trainable module on GPU 0 +lenet_model = mx.mod.Module(symbol=lenet, context=mx.cpu()) + + +# train with the same +lenet_model.fit(train_iter, + eval_data=val_iter, + optimizer='sgd', + optimizer_params={'learning_rate':0.1}, + eval_metric='acc', + # 在此嵌入我们自定义的回调函数 + batch_end_callback=[add_scalar()], + num_epoch=2) + +test_iter = mx.io.NDArrayIter(mnist['test_data'], None, batch_size) +prob = lenet_model.predict(test_iter) +test_iter = mx.io.NDArrayIter(mnist['test_data'], mnist['test_label'], batch_size) + +# predict accuracy for lenet +acc = mx.metric.Accuracy() +lenet_model.score(test_iter, acc) +print(acc) + + From 6cc02c47440e52077fe95ca679efadd037a703f2 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 15:40:21 +0800 Subject: [PATCH 2/7] test refer local file --- demo/mxnet/TUTORIAL_CN.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md index 4d9014024..00e3d6cd7 100644 --- a/demo/mxnet/TUTORIAL_CN.md +++ b/demo/mxnet/TUTORIAL_CN.md @@ -27,7 +27,7 @@ pip install --upgrade dist/visualdl-0.0.1-py2-none-any.whl ## 开始编写训练MNIST的程序 -我们为您提供了一个演示程序 [mxnet_demo.py](https://github.com/PaddlePaddle/VisualDL/blob/mxnet_demo/demo/mxnet/mxnet_demo.py)。里面展示了如何下载MNIST数据集以及编写MXNet程序来进行CNN的训练。MXNet的部分借鉴了MXNet[官方入门文件](https://mxnet.incubator.apache.org/tutorials/python/mnist.html) +我们为您提供了一个演示程序 [mxnet_demo.py](./mxnet_demo.py)。里面展示了如何下载MNIST数据集以及编写MXNet程序来进行CNN的训练。MXNet的部分借鉴了MXNet[官方入门文件](https://mxnet.incubator.apache.org/tutorials/python/mnist.html) 为了嵌入VisualDL程序,以便在MXNet训练时进行检测,我们需要声明一个logger实例: ``` From 600951c0d191db360d4b1ac992bf6a453f581f7f Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 15:56:13 +0800 Subject: [PATCH 3/7] to english --- demo/mxnet/mxnet_demo.py | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/demo/mxnet/mxnet_demo.py b/demo/mxnet/mxnet_demo.py index 437d4926b..3cab742c2 100644 --- a/demo/mxnet/mxnet_demo.py +++ b/demo/mxnet/mxnet_demo.py @@ -1,36 +1,39 @@ import mxnet as mx -import numpy -# 引入VisualDL +# Here we import LogWriter so that we can write log data while MXNet is training from visualdl import LogWriter -# 下载MNIST数据集 +# Download MNIST data mnist = mx.test_utils.get_mnist() batch_size = 100 -# 给VisualDL指定一个文件夹,用来存储日志,模型,图片等数据,供可视化使用 +# Provide a folder to store data for log, model, image, etc. VisualDL's visualization will be +# based on this folder. logdir = "./tmp" -# 创建一个logger实例,sync_cycle是读取内存的频率,意思是每十次内存操作,会读取一次数据 +# Initialize a logger instance. Parameter 'sync_cycle' means write a log every 10 operations on +# memory. logger = LogWriter(logdir, sync_cycle=10) # mark the components with 'train' label. with logger.mode("train"): - # 这里scalar0 用来记录MXNet训练过程中的数值信息。我们将记录随着训练的进行,我们的准确率会不断降低 + # scalar0 is used to record scalar metrics while MXNet is training. We will record accuracy. + # In the visualization, we can see the accuracy is increasing as more training steps happen. scalar0 = logger.scalar("scalars/scalar0") -# 记录训练步数 +# Record training steps cnt_step = 0 -# MXNet提供了许多回调函数的接口,这里我们定义我们自己的回调函数,在每个训练批次(batch)结束时调用 +# MXNet provides many callback interface. Here we define our own callback method and it is called +# after every batch. # https://mxnet.incubator.apache.org/api/python/callback/callback.html def add_scalar(): def _callback(param): with logger.mode("train"): global cnt_step - # 这里的value是我们要记录的准确率accuracy + # Here the value is the accuracy we want to record # https://mxnet.incubator.apache.org/_modules/mxnet/callback.html name_value = param.eval_metric.get_name_value() for name, value in name_value: @@ -39,7 +42,7 @@ def _callback(param): return _callback -# 开始用MXNet建立CNN,训练MNIST数据集,详情请参见MXNet官方网站 +# Start to build CNN in MXNet, train MNIST dataset. For more info, check MXNet's official website: # https://mxnet.incubator.apache.org/tutorials/python/mnist.html import logging @@ -76,7 +79,7 @@ def _callback(param): optimizer='sgd', optimizer_params={'learning_rate':0.1}, eval_metric='acc', - # 在此嵌入我们自定义的回调函数 + # integrate our customized callback method batch_end_callback=[add_scalar()], num_epoch=2) From e4481d7fd5d8ac286ab3ae754e5afdf10c0342b0 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 16:05:21 +0800 Subject: [PATCH 4/7] link anchor --- demo/mxnet/TUTORIAL_CN.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md index 00e3d6cd7..28294a427 100644 --- a/demo/mxnet/TUTORIAL_CN.md +++ b/demo/mxnet/TUTORIAL_CN.md @@ -2,11 +2,11 @@ 下面我们演示一下如何在MXNet中使用VisualDL,从而可以把MXNet的训练过程以及最后的模型可视化出来。我们将以MXNet用卷积神经网络(CNN, Convolutional Neural Network)来训练[MNIST](http://yann.lecun.com/exdb/mnist/)数据集作为例子。 -- [安装MXNet](#安装MXNet) +- [安装MXNet](#install-mxnet) - [安装VisualDL](#安装VisualDL) - [开始编写训练MNIST的程序](#开始编写训练MNIST的程序) -## 安装MXNet +## 安装MXNet {#install-mxnet} 请按照MXNet的[官方网站](https://mxnet.incubator.apache.org/get_started/install.html)来安装MXNet,并验证安装成功。 @@ -17,7 +17,7 @@ array([[ 3., 3., 3.], [ 3., 3., 3.]], dtype=float32) -## 安装VisualDL +## 安装VisualDL {#mht} VisualDL的安装很简单。请按照VisualDL的[官方网站](https://github.com/PaddlePaddle/VisualDL)进行安装。具体只需要两步 ``` From 56847533704dba8e2d0c1023d7dfbc0c0eb5b1b9 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 16:09:10 +0800 Subject: [PATCH 5/7] anchor should work --- demo/mxnet/TUTORIAL_CN.md | 10 +++++----- demo/mxnet/mxnet_demo.py | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md index 28294a427..0cce9ae4f 100644 --- a/demo/mxnet/TUTORIAL_CN.md +++ b/demo/mxnet/TUTORIAL_CN.md @@ -2,11 +2,11 @@ 下面我们演示一下如何在MXNet中使用VisualDL,从而可以把MXNet的训练过程以及最后的模型可视化出来。我们将以MXNet用卷积神经网络(CNN, Convolutional Neural Network)来训练[MNIST](http://yann.lecun.com/exdb/mnist/)数据集作为例子。 -- [安装MXNet](#install-mxnet) -- [安装VisualDL](#安装VisualDL) -- [开始编写训练MNIST的程序](#开始编写训练MNIST的程序) +- [安装MXNet](#%E5%AE%89%E8%A3%85MXNet) +- [安装VisualDL](#%E5%AE%89%E8%A3%85VisualDL) +- [开始编写训练MNIST的程序](#%E5%BC%80%E5%A7%8B%E7%BC%96%E5%86%99%E8%AE%AD%E7%BB%83MNIST%E7%9A%84%E7%A8%8B%E5%BA%8F) -## 安装MXNet {#install-mxnet} +## 安装MXNet 请按照MXNet的[官方网站](https://mxnet.incubator.apache.org/get_started/install.html)来安装MXNet,并验证安装成功。 @@ -17,7 +17,7 @@ array([[ 3., 3., 3.], [ 3., 3., 3.]], dtype=float32) -## 安装VisualDL {#mht} +## 安装VisualDL VisualDL的安装很简单。请按照VisualDL的[官方网站](https://github.com/PaddlePaddle/VisualDL)进行安装。具体只需要两步 ``` diff --git a/demo/mxnet/mxnet_demo.py b/demo/mxnet/mxnet_demo.py index 3cab742c2..5c429db28 100644 --- a/demo/mxnet/mxnet_demo.py +++ b/demo/mxnet/mxnet_demo.py @@ -69,7 +69,7 @@ def _callback(param): # softmax loss lenet = mx.sym.SoftmaxOutput(data=fc2, name='softmax') -# create a trainable module on GPU 0 +# create a trainable module on CPU lenet_model = mx.mod.Module(symbol=lenet, context=mx.cpu()) From cb14a2f8941a8b97dbeefdc54a0d673439055b98 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 16:14:54 +0800 Subject: [PATCH 6/7] anchor to lower case --- demo/mxnet/TUTORIAL_CN.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md index 0cce9ae4f..70de9ad21 100644 --- a/demo/mxnet/TUTORIAL_CN.md +++ b/demo/mxnet/TUTORIAL_CN.md @@ -2,9 +2,9 @@ 下面我们演示一下如何在MXNet中使用VisualDL,从而可以把MXNet的训练过程以及最后的模型可视化出来。我们将以MXNet用卷积神经网络(CNN, Convolutional Neural Network)来训练[MNIST](http://yann.lecun.com/exdb/mnist/)数据集作为例子。 -- [安装MXNet](#%E5%AE%89%E8%A3%85MXNet) -- [安装VisualDL](#%E5%AE%89%E8%A3%85VisualDL) -- [开始编写训练MNIST的程序](#%E5%BC%80%E5%A7%8B%E7%BC%96%E5%86%99%E8%AE%AD%E7%BB%83MNIST%E7%9A%84%E7%A8%8B%E5%BA%8F) +- [安装MXNet](#%E5%AE%89%E8%A3%85mxnet) +- [安装VisualDL](#%E5%AE%89%E8%A3%85visualdl) +- [开始编写训练MNIST的程序](#%E5%BC%80%E5%A7%8B%E7%BC%96%E5%86%99%E8%AE%AD%E7%BB%83mnist%E7%9A%84%E7%A8%8B%E5%BA%8F) ## 安装MXNet 请按照MXNet的[官方网站](https://mxnet.incubator.apache.org/get_started/install.html)来安装MXNet,并验证安装成功。 From d6e555af8b1da06f311c8f5440ce382fa58eb3d6 Mon Sep 17 00:00:00 2001 From: daming-lu Date: Sat, 13 Jan 2018 16:55:43 +0800 Subject: [PATCH 7/7] pylint --- demo/mxnet/TUTORIAL_CN.md | 4 ++-- demo/mxnet/mxnet_demo.py | 12 +++++------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/demo/mxnet/TUTORIAL_CN.md b/demo/mxnet/TUTORIAL_CN.md index 70de9ad21..9eb8f952a 100644 --- a/demo/mxnet/TUTORIAL_CN.md +++ b/demo/mxnet/TUTORIAL_CN.md @@ -28,13 +28,13 @@ pip install --upgrade dist/visualdl-0.0.1-py2-none-any.whl ## 开始编写训练MNIST的程序 我们为您提供了一个演示程序 [mxnet_demo.py](./mxnet_demo.py)。里面展示了如何下载MNIST数据集以及编写MXNet程序来进行CNN的训练。MXNet的部分借鉴了MXNet[官方入门文件](https://mxnet.incubator.apache.org/tutorials/python/mnist.html) -为了嵌入VisualDL程序,以便在MXNet训练时进行检测,我们需要声明一个logger实例: +为了嵌入VisualDL程序,以便在MXNet训练时进行检测,我们需要声明一个LogWriter实例: ``` logger = LogWriter(logdir, sync_cycle=10) ``` -logger实例里面包含VisualDL的四个功能模块 Scalar, Image, Graph 以及 Histogram。这里我们使用 Scalar 模块: +logger实例里面包含VisualDL的四个功能模块 Scalar, Image 以及 Histogram。这里我们使用 Scalar 模块: ``` scalar0 = logger.scalar("scalars/scalar0") diff --git a/demo/mxnet/mxnet_demo.py b/demo/mxnet/mxnet_demo.py index 5c429db28..dc35bda89 100644 --- a/demo/mxnet/mxnet_demo.py +++ b/demo/mxnet/mxnet_demo.py @@ -53,13 +53,13 @@ def _callback(param): data = mx.sym.var('data') # first conv layer -conv1 = mx.sym.Convolution(data=data, kernel=(5,5), num_filter=20) +conv1 = mx.sym.Convolution(data=data, kernel=(5, 5), num_filter=20) tanh1 = mx.sym.Activation(data=conv1, act_type="tanh") -pool1 = mx.sym.Pooling(data=tanh1, pool_type="max", kernel=(2,2), stride=(2,2)) +pool1 = mx.sym.Pooling(data=tanh1, pool_type="max", kernel=(2, 2), stride=(2, 2)) # second conv layer -conv2 = mx.sym.Convolution(data=pool1, kernel=(5,5), num_filter=50) +conv2 = mx.sym.Convolution(data=pool1, kernel=(5, 5), num_filter=50) tanh2 = mx.sym.Activation(data=conv2, act_type="tanh") -pool2 = mx.sym.Pooling(data=tanh2, pool_type="max", kernel=(2,2), stride=(2,2)) +pool2 = mx.sym.Pooling(data=tanh2, pool_type="max", kernel=(2, 2), stride=(2, 2)) # first fullc layer flatten = mx.sym.flatten(data=pool2) fc1 = mx.symbol.FullyConnected(data=flatten, num_hidden=500) @@ -77,7 +77,7 @@ def _callback(param): lenet_model.fit(train_iter, eval_data=val_iter, optimizer='sgd', - optimizer_params={'learning_rate':0.1}, + optimizer_params={'learning_rate': 0.1}, eval_metric='acc', # integrate our customized callback method batch_end_callback=[add_scalar()], @@ -91,5 +91,3 @@ def _callback(param): acc = mx.metric.Accuracy() lenet_model.score(test_iter, acc) print(acc) - -