上周在搜索关于深度学习分布式运行方式的资料时,无意间搜到了paddlepaddle,发现这个框架的分布式训练方案做的还挺不错的,想跟大家分享一下。不过呢,这块内容太复杂了,所以就简单的介绍一下paddlepaddle的第一个“hello word”程序----mnist手写数字识别。下一次再介绍用PaddlePaddle做分布式训练的方案。其实之前也写过一篇用CNN识别手写数字集的文章(链接戳这里~),是用keras实现的,这次用了paddlepaddle后,正好可以简单对比一下两个框架的优劣。

什么是PaddlePaddle?

PaddlePaddle是百度推出的一个深度学习框架,可能大多数人平常用的比较多的一般是tensorflow,caffe,mxnet等,但其实PaddlePaddle也是一个非常不错的框架(据说以前叫Paddle,现在改名叫PaddlePaddle,不知道为啥总觉得有股莫名的萌点)

PaddlePaddle能做什么?

传统的基本都能做,尤其对NLP的支持很好,譬如情感分析,word embedding,语言模型等,反正你想得到的,常见的都可以用它来试一试~

PaddlePaddle的安装

不得不吐槽一下PaddlePaddle的安装,官网上说“PaddlePaddle目前唯一官方支持的运行的方式是Docker容器”,而docker其实在国内还并不是特别的流行,之前遇到的所有的框架,都有很多种安装方式,非常方便,所以这个唯一支持docker让人觉得非常诡异 = =!不过偶然试了一下,居然可以用pip install,不过为啥官网上没有写呢?所以,对于新手来说,最简单的安装方式就是:

  • CPU版本安装

pip install paddlepaddle

  • GPU版本安装

pip install paddlepaddle-gpu

用PaddlePaddle实现手写数字识别

训练步骤

传统的方式这次就不展开讲了,为了对比我们还是用CNN来进行训练。PaddlePaddle训练一次模型完整的过程可以如下几个步骤:

导入数据---->定义网络结构---->训练模型---->保存模型---->测试结果

下面,我直接用代码来展示训练的过程(以后代码都会放在github里):

#coding:utf-8import osfrom PIL import Imageimport numpy as npimport paddle.v2 as paddle# 设置是否用gpu,0为否,1为是with_gpu = os.getenv('WITH_GPU', '0') != '1'# 定义网络结构def convolutional_neural_network_org(img): # 第一层卷积层 conv_pool_1 = paddle.networks.simple_img_conv_pool( input=img, filter_size=5, num_filters=20, num_channel=1, pool_size=2, pool_stride=2, act=paddle.activation.Relu()) # 第二层卷积层 conv_pool_2 = paddle.networks.simple_img_conv_pool( input=conv_pool_1, filter_size=5, num_filters=50, num_channel=20, pool_size=2, pool_stride=2, act=paddle.activation.Relu()) # 全连接层 predict = paddle.layer.fc( input=conv_pool_2, size=10, act=paddle.activation.Softmax()) return predictdef main(): # 初始化定义跑模型的设备 paddle.init(use_gpu=with_gpu, trainer_count=1) # 读取数据 images = paddle.layer.data( name='pixel', type=paddle.data_type.dense_vector(784)) label = paddle.layer.data( name='label', type=paddle.data_type.integer_value(10)) # 调用之前定义的网络结构 predict = convolutional_neural_network_org(images) # 定义损失函数 cost = paddle.layer.classification_cost(input=predict, label=label) # 指定训练相关的参数 parameters = paddle.parameters.create(cost) # 定义训练方法 optimizer = paddle.optimizer.Momentum( learning_rate=0.1 / 128.0, momentum=0.9, regularization=paddle.optimizer.L2Regularization(rate=0.0005 * 128)) # 训练模型 trainer = paddle.trainer.SGD( cost=cost, parameters=parameters, update_equation=optimizer) lists = [] # 定义event_handler,输出训练过程中的结果 def event_handler(event): if isinstance(event, paddle.event.EndIteration): if event.batch_id % 100 == 0: print "Pass %d, Batch %d, Cost %f, %s" % ( event.pass_id, event.batch_id, event.cost, event.metrics) if isinstance(event, paddle.event.EndPass): # 保存参数 with open('params_pass_%d.tar' % event.pass_id, 'w') as f: parameters.to_tar(f) result = trainer.test(reader=paddle.batch( paddle.dataset.mnist.test(), batch_size=128)) print "Test with Pass %d, Cost %f, %s" % ( event.pass_id, result.cost, result.metrics) lists.append((event.pass_id, result.cost, result.metrics['classification_error_evaluator'])) trainer.train( reader=paddle.batch( paddle.reader.shuffle(paddle.dataset.mnist.train(), buf_size=8192), batch_size=128), event_handler=event_handler, num_passes=10) # 找到训练误差最小的一次结果 best = sorted(lists, key=lambda list: float(list[1]))[0] print 'Best pass is %s, testing Avgcost is %s' % (best[0], best[1]) print 'The classification accuracy is %.2f%%' % (100 - float(best[2]) * 100) # 加载数据  def load_image(file): im = Image.open(file).convert('L') im = im.resize((28, 28), Image.ANTIALIAS) im = np.array(im).astype(np.float32).flatten() im = im / 255.0 return im # 测试结果 test_data = [] cur_dir = os.path.dirname(os.path.realpath(__file__)) test_data.append((load_image(cur_dir + '/image/infer_3.png'), )) probs = paddle.infer( 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]if __name__ == '__main__': main()

上面的代码看起来很长,但结构还是很清楚的。下面我们用实际数据测试一下,看一下效果到底怎么样~


BaseLine版本

首先我用了官网给出的例子,直接用最基本的CNN网络结构训练了一下,代码如下: 

 1 def convolutional_neural_network_org(img): 2 # 第一层卷积层 3 conv_pool_1 = paddle.networks.simple_img_conv_pool( 4 input=img, 5 filter_size=5, 6 num_filters=20, 7 num_channel=1, 8 pool_size=2, 9 pool_stride=2,10 act=paddle.activation.Relu())11 # 第二层卷积层12 conv_pool_2 = paddle.networks.simple_img_conv_pool(13 input=conv_pool_1,14 filter_size=5,15 num_filters=50,16 num_channel=20,17 pool_size=2,18 pool_stride=2,19 act=paddle.activation.Relu())20 # 全连接层21 predict = paddle.layer.fc(22 input=conv_pool_2, size=10, act=paddle.activation.Softmax())23 return predict

 输出结果如下:

I1023 13:45:46.519075 34144 Util.cpp:166] commandline: --use_gpu=True --trainer_count=1[INFO 2017-10-23 13:45:52,667 layers.py:2539] output for __conv_pool_0___conv: c = 20, h = 24, w = 24, size = 11520[INFO 2017-10-23 13:45:52,667 layers.py:2667] output for __conv_pool_0___pool: c = 20, h = 12, w = 12, size = 2880[INFO 2017-10-23 13:45:52,668 layers.py:2539] output for __conv_pool_1___conv: c = 50, h = 8, w = 8, size = 3200[INFO 2017-10-23 13:45:52,669 layers.py:2667] output for __conv_pool_1___pool: c = 50, h = 4, w = 4, size = 800I1023 13:45:52.675750 34144 GradientMachine.cpp:85] Initing parameters..I1023 13:45:52.686153 34144 GradientMachine.cpp:92] Init parameters done.Pass 0, Batch 0, Cost 3.048408, {'classification_error_evaluator': 0.890625}Pass 0, Batch 100, Cost 0.188828, {'classification_error_evaluator': 0.0546875}Pass 0, Batch 200, Cost 0.075183, {'classification_error_evaluator': 0.015625}Pass 0, Batch 300, Cost 0.070798, {'classification_error_evaluator': 0.015625}Pass 0, Batch 400, Cost 0.079673, {'classification_error_evaluator': 0.046875}Test with Pass 0, Cost 0.074587, {'classification_error_evaluator': 0.023800000548362732}`````````Pass 4, Batch 0, Cost 0.032454, {'classification_error_evaluator': 0.015625}Pass 4, Batch 100, Cost 0.021028, {'classification_error_evaluator': 0.0078125}Pass 4, Batch 200, Cost 0.020458, {'classification_error_evaluator': 0.0}Pass 4, Batch 300, Cost 0.046728, {'classification_error_evaluator': 0.015625}Pass 4, Batch 400, Cost 0.030264, {'classification_error_evaluator': 0.015625}Test with Pass 4, Cost 0.035841, {'classification_error_evaluator': 0.01209999993443489}Best pass is 4, testing Avgcost is 0.0358410408473The classification accuracy is 98.79%Label of image/infer_3.png is: 3real 0m31.565suser 0m20.996ssys 0m15.891s

可以看到,第一行输出选择的设备是否是gpu,这里我选择的是gpu,所以等于1,如果是cpu,就是0。接下来四行输出的是网络结构,然后开始输出训练结果,训练结束,我们把这几次迭代中误差最小的结果输出来,98.79%,效果还是很不错的,毕竟只迭代了5次。最后看一下输出时间,非常快,约31秒。然而这个结果我并不是特别满意,因为之前用keras做的时候调整的网络模型训练往后准确率能够达到99.72%,不过速度非常慢,迭代69次大概需要30分钟左右,所以我觉得这个网络结构还是可以改进一下的,所以我对这个网络结构改进了一下,请看改进版


改进版 

def convolutional_neural_network(img): # 第一层卷积层 conv_pool_1 = paddle.networks.simple_img_conv_pool( input=img, filter_size=5, num_filters=20, num_channel=1, pool_size=2, pool_stride=2, act=paddle.activation.Relu()) # 加一层dropout层 drop_1 = paddle.layer.dropout(input=conv_pool_1, dropout_rate=0.2) # 第二层卷积层 conv_pool_2 = paddle.networks.simple_img_conv_pool( input=drop_1, filter_size=5, num_filters=50, num_channel=20, pool_size=2, pool_stride=2, act=paddle.activation.Relu()) # 加一层dropout层 drop_2 = paddle.layer.dropout(input=conv_pool_2, dropout_rate=0.5) # 全连接层 fc1 = paddle.layer.fc(input=drop_2, size=10, act=paddle.activation.Linear()) bn = paddle.layer.batch_norm(input=fc1,act=paddle.activation.Relu(), layer_attr=paddle.attr.Extra(drop_rate=0.2)) predict = paddle.layer.fc(input=bn, size=10, act=paddle.activation.Softmax()) return predict

在改进版里我们加了一些dropout层来避免过拟合。分别在第一层卷积层和第二层卷积层后加了dropout,阈值设为0.5。改变网络结构也非常简单,直接在定义的网络结构函数里对模型进行修改即可,这一点其实和keras的网络结构定义方式还是挺像的,易用性很高。下面来看看效果:

I1023 14:01:51.653827 34244 Util.cpp:166] commandline: --use_gpu=True --trainer_count=1[INFO 2017-10-23 14:01:57,830 layers.py:2539] output for __conv_pool_0___conv: c = 20, h = 24, w = 24, size = 11520[INFO 2017-10-23 14:01:57,831 layers.py:2667] output for __conv_pool_0___pool: c = 20, h = 12, w = 12, size = 2880[INFO 2017-10-23 14:01:57,832 layers.py:2539] output for __conv_pool_1___conv: c = 50, h = 8, w = 8, size = 3200[INFO 2017-10-23 14:01:57,833 layers.py:2667] output for __conv_pool_1___pool: c = 50, h = 4, w = 4, size = 800I1023 14:01:57.842871 34244 GradientMachine.cpp:85] Initing parameters..I1023 14:01:57.854014 34244 GradientMachine.cpp:92] Init parameters done.Pass 0, Batch 0, Cost 2.536199, {'classification_error_evaluator': 0.875}Pass 0, Batch 100, Cost 1.668236, {'classification_error_evaluator': 0.515625}Pass 0, Batch 200, Cost 1.024846, {'classification_error_evaluator': 0.375}Pass 0, Batch 300, Cost 1.086315, {'classification_error_evaluator': 0.46875}Pass 0, Batch 400, Cost 0.767804, {'classification_error_evaluator': 0.25}Pass 0, Batch 500, Cost 0.545784, {'classification_error_evaluator': 0.1875}Pass 0, Batch 600, Cost 0.731662, {'classification_error_evaluator': 0.328125}`````````Pass 49, Batch 0, Cost 0.415184, {'classification_error_evaluator': 0.09375}Pass 49, Batch 100, Cost 0.067616, {'classification_error_evaluator': 0.0}Pass 49, Batch 200, Cost 0.161415, {'classification_error_evaluator': 0.046875}Pass 49, Batch 300, Cost 0.202667, {'classification_error_evaluator': 0.046875}Pass 49, Batch 400, Cost 0.336043, {'classification_error_evaluator': 0.140625}Pass 49, Batch 500, Cost 0.290948, {'classification_error_evaluator': 0.125}Pass 49, Batch 600, Cost 0.223433, {'classification_error_evaluator': 0.109375}Pass 49, Batch 700, Cost 0.217345, {'classification_error_evaluator': 0.0625}Pass 49, Batch 800, Cost 0.163140, {'classification_error_evaluator': 0.046875}Pass 49, Batch 900, Cost 0.203645, {'classification_error_evaluator': 0.078125}Test with Pass 49, Cost 0.033639, {'classification_error_evaluator': 0.008100000210106373}Best pass is 48, testing Avgcost is 0.0313018567383The classification accuracy is 99.28%Label of image/infer_3.png is: 3real 5m3.151suser 4m0.052ssys 1m8.084s

从上面的数据来看,这个效果还是很不错滴,对比之前用keras训练的效果来看,结果如下:

可以看到这个速度差异是很大的了,在准确率差不多的情况下,训练时间几乎比原来缩短了六倍,网络结构也相对简单,说明需要调整的参数也少了很多。

总结

paddlepaddle用起来还是很方便的,不论是定义网络结构还是训练速度,都值得一提,然而我个人的体验中,认为最值得说的是这几点:

1.导入数据方便。这次训练的手写数字识别数据量比较小,但是如果想要添加数据,也非常方便,直接添加到相应目录下。

2.event_handler机制,可以自定义训练结果输出内容。之前用的keras,以及mxnet等都是已经封装好的函数,输出信息都是一样的,这里paddlepaddle把这个函数并没有完全封装,而是让我们用户自定义输出的内容,可以方便我们减少冗余的信息,增加一些模型训练的细节的输出,也可以用相应的函数画出模型收敛的图片,可视化收敛曲线。

3.速度快。上面的例子已经证明了paddlepaddle的速度,并且在提升速度的同时,模型准确度也与最优结果相差不多,这对于我们训练海量数据的模型是一个极大的优势啊!

然而,paddlepaddle也有几点让我用的有点难受,譬如文档太少了啊,报错了上网上搜没啥结果啊等等,不过我觉得这个应该不是大问题,以后用的人多了以后肯定相关资料也会更多。所以一直很疑惑,为啥paddlepaddle不火呢?安装诡异是一个吐槽点,但其实还是很优秀的一个开源软件,尤其是最值得说的分布式训练方式,多机多卡的设计是非常优秀的,本篇没有讲,下次讲讲如何用paddlepaddle做单机单卡,单机多卡,多机单卡和多机多卡的训练方式来训练模型,大家多多用起来呀~~可以多交流呀~

matlab朴素贝叶斯手写数字识别_「深度学习系列」PaddlePaddle之手写数字识别相关推荐

  1. 深度学习数字仪表盘识别_【深度学习系列】手写数字识别实战

    上周在搜索关于深度学习分布式运行方式的资料时,无意间搜到了paddlepaddle,发现这个框架的分布式训练方案做的还挺不错的,想跟大家分享一下.不过呢,这块内容太复杂了,所以就简单的介绍一下padd ...

  2. 脑电信号(EEG)处理中的机器学习方法总结——回归模型,SVM、K近邻、人工神经网络、朴素贝叶斯、决策树和随机森林、集成学习、模糊逻辑、LDA线性判别分析、K-means聚类、强化学习、迁移学习

    本文归纳总结了机器学习在脑电分析中的应用,并详细介绍回归模型,SVM.K近邻.人工神经网络.朴素贝叶斯.决策树和随机森林.集成学习.模糊逻辑.LDA线性判别分析.K-means聚类.强化学习.迁移学习 ...

  3. 用matlab朴素贝叶斯,Matlab朴素贝叶斯

    你好我正在使用KDD 1999数据集,我正在寻找在matlab中应用朴素贝叶斯.我想知道的是,kdd数据集是一个494021x42数据数组,如果您注意到下面的朴素贝叶斯代码中的"traini ...

  4. matlab 朴素贝叶斯模型 代码及其案例

    简介 朴素贝叶斯分类器(Naive Bayes Classifier 或 NBC)发源于古典数学理论,有着坚实的数学基础,以及稳定的分类效率.同时,NBC模型所需估计的参数很少,对缺失数据不太敏感,算 ...

  5. python输入数字并排序_「每日一练」巧用Python实现数字排序

    原标题:「每日一练」巧用Python实现数字排序 数字排序在我们的生产和生活中占着非常大的比重,这种思维和技术可以让一组数据更快更明了的展现在我们的面前,极大的提高了我们的工作效率! 那么,你知道如何 ...

  6. matlab朴素贝叶斯手写数字识别_TensorFlow手写数字识别(一)

    本篇文章通过TensorFlow搭建最基础的全连接网络,使用MNIST数据集实现基础的模型训练和测试. MNIST数据集 MNIST数据集 :包含7万张黑底白字手写数字图片,其中55000张为训练集, ...

  7. matlab朴素贝叶斯手写数字识别_从“手写数字识别”学习分类任务

    机器学习问题可以分为回归问题和分类问题,回归问题已经在线性回归讲过,本文学习分类问题.分类问题跟回归问题有明显的区别,回归问题是连续的数值,而分类问题是离散的类别,比如将性别分为[男,女],将图片分为 ...

  8. matlab朴素贝叶斯手写数字识别_机器学习系列四:MNIST 手写数字识别

    4. MNIST 手写数字识别 机器学习中另外一个相当经典的例子就是MNIST的手写数字学习.通过海量标定过的手写数字训练,可以让计算机认得0~9的手写数字.相关的实现方法和论文也很多,我们这一篇教程 ...

  9. MATLAB朴素贝叶斯(德国信用卡案例)

    我们matlab建模课的案例 数据以及代码 链接:https://pan.baidu.com/s/18qpV2qsHzwbnOgZBMBHdGQ?pwd=r8g2  提取码:r8g2 参考书:MATL ...

  10. 利用深度学习进行交通灯识别_通过深度学习识别交通信号灯

    利用深度学习进行交通灯识别 by David Brailovsky 戴维·布雷洛夫斯基(David Brailovsky) 通过深度学习识别交通信号灯 (Recognizing Traffic Lig ...

最新文章

  1. C++中的new和delete用法
  2. 如何让 Mybatis 自动生成代码,提高开发效率
  3. uboot linux内核传递参数,Uboot与Linux之间的参数传递详解
  4. CSS3与动画有关的属性transition、animation、transform对比
  5. paddle_ocr1.0入门踩坑
  6. 快速清除SQL Server数据库日志的方法
  7. 实战SSM_O2O商铺_17【商铺编辑】Dao层开发
  8. how to add one row in the dataframe?
  9. pat 乙级 1015 德才论(C++)
  10. python基础代码技巧_写Python必须知道的这几个代码技巧!你会吗?
  11. jQuery插件开发详细教程
  12. Thrift RPC实战(七) 基于zookeeper和thrift的RPC服务发布订阅
  13. csdn设置资源下载所需积分
  14. Google 推出的编程学习应用 Grasshopper
  15. 计算机英语实用教程第五版答案,(计算机英语实用教程课后题参考答案.doc
  16. Laravel渴求式加载
  17. 苹果开发者账号变更公司名称
  18. Entrez Direct
  19. 2019清华大学、中山大学、中传自主招生笔试面试真题
  20. superset设置起止时间为明天

热门文章

  1. oracle 学习笔记 flashback query
  2. CCDA认证的详细综合叙述
  3. Deklarit3.0的确不错,推荐一下。
  4. SpringBoot番外篇-微服务架构【1.起源与定义】
  5. linux 判断某进程 前台还是后台,Linux进程管理——进程前后台(优先级)以及作业控制等...
  6. java array to list iterator_Iterator to list的三种方法
  7. 多元有序logistic回归_stata速学|logistic回归分析
  8. Mysql 存储类型范围
  9. Go 关键字 Select
  10. FluentPDO备忘