DeepLearning4j 实战:手写体数字识别的 GPU 实现与性能对比

在之前的博客中已经用单机、Spark分布式两种训练的方式对深度神经网络进行训练,但其实DeepLearning4j也是支持多GPU训练的。

这篇文章我就总结下用GPU来对DNN/CNN进行训练和评估过程。并且我会给出CPU、GPU和多卡GPU之前的性能比较图表。不过,由于重点在于说明Mnist数据集在GPU上训练的过程,所以对于一些环境的部署,比如Java环境和CUDA的安装就不再详细说明了。

软件环境的部署主要在于两个方面,一个是JDK的安装,另外一个是CUDA。目前最新版本的DeepLearning4j以及Nd4j支持CUDA-8.0,JDK的话1.7以上。

环境部署完后,分别用java -version和nvidia-smi来确认环境是否部署正确,如果出现类似以下的信息,则说明环境部署正确,否则需要重新安装。

  GPU配置:

  Java环境截图:

从系统返回的信息可以看到,jdk是openJDK1.7,GPU是2张P40的卡。

  下面说明下代码的构成:

由于我这里用了DeepLearning4j最新的版本--v0.8,所以和之前博客的pom文件有些修改,具体如下:

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
  <modelVersion>4.0.0</modelVersion>
  <groupId>DeepLearning</groupId>
  <artifactId>DeepLearning</artifactId>
  <version>2.0</version>  

  <properties>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    <nd4j.version>0.8.0</nd4j.version>
    <dl4j.version>0.8.0</dl4j.version>
    <datavec.version>0.8.0</datavec.version>
    <scala.binary.version>2.11</scala.binary.version>
  </properties>  

 <dependencies>
       <dependency>
         <groupId>org.nd4j</groupId>
         <artifactId>nd4j-native</artifactId>
         <version>${nd4j.version}</version>
       </dependency>
       <dependency>
            <groupId>org.deeplearning4j</groupId>
            <artifactId>deeplearning4j-core</artifactId>
            <version>${dl4j.version}</version>
        </dependency>
        <dependency>
         <groupId>org.nd4j</groupId>
         <artifactId>nd4j-cuda-8.0</artifactId>
         <version>${nd4j.version}</version>
        </dependency>
        <dependency>
            <groupId>org.deeplearning4j</groupId>
            <artifactId>deeplearning4j-parallel-wrapper_${scala.binary.version}</artifactId>
            <version>${dl4j.version}</version>
        </dependency>
    </dependencies>
  <build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.4</version>
            <configuration>
                <source>1.7</source>
                <target>1.7</target>
                <archive>
                    <manifest>
                        <mainClass>cn.live.wangongxi.cv.CNNMnist</mainClass>
                    </manifest>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>
</project>  

创建完Maven工程以及添加了上面POM文件的内容之后,就可以开始着手上层应用逻辑的构建。这里我参考了官网的例子,具体由以下几个部分构成:

● 初始化CUDA的环境(底层逻辑包括硬件检测、CUDA版本校验和一些GPU参数)

● 读取Mnist二进制文件(和之前的博客内容一致)

● CNN的定义,这里我还是用的LeNet

● 训练以及评估模型的指标

首先贴一下第一部分的代码:

//精度设置,常用精度有单、双、半精度
//HALF : 半精度
DataTypeUtil.setDTypeForContext(DataBuffer.Type.HALF);
//FLOAT : 单精度
//DataTypeUtil.setDTypeForContext(DataBuffer.Type.FLOAT);
//DOUBLE : 双精度
//DataTypeUtil.setDTypeForContext(DataBuffer.Type.DOUBLE);  

//创建CUDA上下文实例并设置参数
   CudaEnvironment.getInstance().getConfiguration()
    //是否允许多GPU
       .allowMultiGPU(false)
       //设置显存中缓存数据的容量,单位:字节
       .setMaximumDeviceCache(2L * 1024L * 1024L * 1024L)
       //是否允许多GPU间点对点(P2P)的内存访问
       .allowCrossDeviceAccess(false);  

通常我们需要根据需要来设置GPU计算的精度,常用的就像代码中写的那样有单、双、半精度三种。通过选择DataBuffer中定义的enum类型Type中的值来达到设置精度的目的。如果不设置,默认的是单精度。

再下面就是设置CUDA的一些上下文参数,比如代码中罗列的cache数据的显存大小,P2P访问内存和多GPU运行的标志位等等。对于网络结构相对简单,数据量不大的情况下,默认的参数就够用了。这里我们也只是简单设置了几个参数,这对于用LeNet来训练Mnist数据集来说已经足够了。

从2~4部分的逻辑和之前的博客里几乎是一样的,就直接上代码了:

int nChannels = 1;
int outputNum = 10;  

int batchSize = 128;
int nEpochs = 10;
int iterations = 1;
int seed = 123;  

log.info("Load data....");
DataSetIterator mnistTrain = new MnistDataSetIterator(batchSize,true,12345);
DataSetIterator mnistTest = new MnistDataSetIterator(batchSize,false,12345);  

log.info("Build model....");
MultiLayerConfiguration conf = new NeuralNetConfiguration.Builder()
    .seed(seed)
    .iterations(iterations)
    .regularization(true).l2(0.0005)
    .learningRate(.01)
    .weightInit(WeightInit.XAVIER)
    .optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
    .updater(Updater.NESTEROVS).momentum(0.9)
    .list()
    .layer(0, new ConvolutionLayer.Builder(5, 5)
        .nIn(nChannels)
        .stride(1, 1)
        .nOut(20)
        .activation(Activation.IDENTITY)
        .build())
    .layer(1, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
        .kernelSize(2,2)
        .stride(2,2)
        .build())
    .layer(2, new ConvolutionLayer.Builder(5, 5)
        .stride(1, 1)
        .nOut(50)
        .activation(Activation.IDENTITY)
        .build())
    .layer(3, new SubsamplingLayer.Builder(SubsamplingLayer.PoolingType.MAX)
        .kernelSize(2,2)
        .stride(2,2)
        .build())
    .layer(4, new DenseLayer.Builder().activation(Activation.RELU)
        .nOut(500).build())
    .layer(5, new OutputLayer.Builder(LossFunctions.LossFunction.NEGATIVELOGLIKELIHOOD)
        .nOut(outputNum)
        .activation(Activation.SOFTMAX)
        .build())
    .setInputType(InputType.convolutionalFlat(28,28,1))
    .backprop(true).pretrain(false).build();
MultiLayerNetwork model = new MultiLayerNetwork(conf);
model.init();
log.info("Train model....");
model.setListeners(new ScoreIterationListener(100));
long timeX = System.currentTimeMillis();  

for( int i=0; i<nEpochs; i++ ) {
    long time1 = System.currentTimeMillis();
    model.fit(mnistTrain);
    long time2 = System.currentTimeMillis();
    log.info("*** Completed epoch {}, time: {} ***", i, (time2 - time1));
}
long timeY = System.currentTimeMillis();  

log.info("*** Training complete, time: {} ***", (timeY - timeX));  

log.info("Evaluate model....");
Evaluation eval = new Evaluation(outputNum);
while(mnistTest.hasNext()){
    DataSet ds = mnistTest.next();
    INDArray output = model.output(ds.getFeatureMatrix(), false);
    eval.eval(ds.getLabels(), output);
}
log.info(eval.stats());  

log.info("****************Example finished********************");  

以上逻辑就是利用一块GPU卡进行Mnist数据集进行训练和评估的逻辑。如果想在多GPU下进行并行训练的话,需要修改一些设置,例如在之前第一步的创建CUDA环境上下文的时候,需要允许多GPU和P2P内存访问,即设置为true。然后在逻辑里添加并行训练的逻辑:

ParallelWrapper wrapper = new ParallelWrapper.Builder(model)
    .prefetchBuffer(24)
    .workers(4)
    .averagingFrequency(3)
    .reportScoreAfterAveraging(true)
    .useLegacyAveraging(true)
    .build();  

这样如果有多张GPU卡就可以进行单机多卡的并行训练。

下面贴一下训练Mnist数据集在CPU/GPU/多GPU下的性能比较还有训练时候的GPU使用情况:

  单卡训练截图:

  双卡并行训练截图:

  训练时间评估:

最后做下简单的总结。由于Deeplearning4j本身支持GPU单卡,多卡以及集群的训练方式,而且对于底层的接口都已经进行了很多的封装,暴露的接口都是比较hig-level的接口,一般设置一些属性就可以了。当然前提是硬件包括CUDA都要正确安装。

====================================分割线================================

本文作者:AI研习社

本文转自雷锋网禁止二次转载,原文链接

时间: 2024-10-26 05:29:28

DeepLearning4j 实战:手写体数字识别的 GPU 实现与性能对比的相关文章

《精通软件性能测试与LoadRunner最佳实战》—第2章2.11节性能测试总结

2.11 性能测试总结精通软件性能测试与LoadRunner最佳实战性能测试工作完成以后,需要编写性能测试总结报告. 性能测试总结不仅使我们能够了解到如下内容:性能测试需求覆盖情况,性能测试过程中出现的问题,我们又是如何去分析.调优.解决的,测试人员.进度控制与实际执行偏差,性能测试过程中遇到的各类风险是如何控制的,而且,还能描述经过该产品/项目性能测试后有哪些经验和教训等内容.随着,国内软件企业的发展.壮大,越来越多的企业也更加重视软件产品的质量,而好的软件无疑和良好的软件生命周期过程控制密不

简单手写体数字识别系统

摘要 为了实现对手写字体的识别,运用了人工智能的分层神经网络思想,对识别的字体通过训练学习,达到识别手写字体的功能. 关键字 VC,人工智能,神经网络,手写识别. 1 引言 1.1 编写目的 人工智能英文名表示是"Artificial Intelligence",简称 AI,也就是用计算机模拟人的思维和知识,通过对本系统的学习开发,对计算机人工智能和神经网络有了初步的认识,萌发初学者对人工智能和网络神经学习的基本方法和思路. 1.2 背景 目前市面上的语音识别系统和手写识别,指纹识别系

哈佛/MIT学生创造GPU数据库,性能提升70倍

2012年Todd Mostak 在哈佛中东研究中心攻读硕士研究生,他试图为自己的论文主题绘制和处理阿拉伯之春期间发布的4千万Twitter帖子,但处理这些帖子数小时耗费了甚至数 天.没有现成的系统能帮助他实现大数据集快速互动分析,于是他一边读MIT的数据库课程,一边开发出了利用GeForce Titan GPU处理数据的并行数据库系统MapD(演示,非论文).基于GFU的数据库系统比基于CPU的数据库性能提升了70倍,而整个硬件只花了5千美元.Todd Mostak计划在开源许可证下发布Map

《精通软件性能测试与LoadRunner最佳实战》—第2章2.3节性能测试计划

2.3 性能测试计划精通软件性能测试与LoadRunner最佳实战性能测试计划是性能测试的重要过程.在对客户提出的需求经过认真分析后,作为性能测试管理人员,需要编写的第一份文档就是性能测试计划,性能测试计划非常重要,在性能测试计划中,需要阐述产品.项目的背景,将前期的需要测试性能需求明确,并落实到文档中.指出性能测试可参考的一些文档,并将这些文档的作者.编写时间.获取途径逐一列出,形成一个表格,这些文档包括:用户需求规格说明书.会议纪要(内部讨论.与客户讨论等最终确定的关于性能测试内容)等性能测

MySQL架构优化实战系列2:主从复制同步与查询性能调优

一.主从复制同步部署   1.概念 主从复制:2台以上mysql服务器, 做负载均衡, 主服务器负责增删改 , 从服务器负责查询 同步原理:mysql开启bin-log日志,主服务器所有的增删改操作会记录到bin-log日志:然后主服务器把bin-log日志发送 给 从服务器 , 从服务器重放bin-log日志 确保数据同步 2.开启bin-log日志 配置 my.cnf 文件 并重启 mysql [root@localhost etc]# vim /etc/my.cnf     [root@l

玩深度学习选哪块英伟达 GPU?有性价比排名还不够!

与"传统" AI 算法相比,深度学习(DL)的计算性能要求,可以说完全在另一个量级上. 而 GPU 的选择,会在根本上决定你的深度学习体验.那么,对于一名 DL 开发者,应该怎么选择合适的 GPU 呢?这篇文章将深入讨论这个问题,聊聊有无必要入手英特尔协处理器 Xeon Phi,并将各主流显卡的性能.性价比制成一目了然的对比图,供大家参考. 先来谈谈选择 GPU 对研究深度学习的意义.更快的 GPU,能帮助新人更快地积累实践经验.更快地掌握技术要领,并把这些应用于新的任务.没有快速的反

黄仁勋:GPU才是AI时代的摩尔定律

在日益变得颠覆的AI背后,总有NVIDIA的影子. 今天上午,作为NVIDIA全球GTC(GPU Technology Conference)大会中最重要的一站之一,GTC China再次在北京召开了.身着标志性黑色皮衣的教主黄仁勋也在本次大会开始之际,奉上了一场题为"一个全新的计算时代(A NEW COMPUTING ERA)"的主题演讲. 按照惯例,NVIDIA基本上每年都会将自身重要的产品发布.软件更新在5月份美国本土召开GTC上宣布.而全球其他地区的GTC大会则主要是根据各地区

GPU计算的十大质疑——GPU计算再思考

作者:陈晓炜   原文链接:http://www.hpcwire.com/hpcwire/2011-06-09/top_10_objections_to_gpu_computing_reconsidered.html 作者:Dr. Vincent Natoli, Stone Ridge Technology (http://www.stoneridgetechnology.com/ ) 译者:陈晓炜(转载请注明出处 http://blog.csdn.net/babyfacer/article/d

赛灵思挑战CPU/GPU,FPGA为数据中心的主流应用加速

12月5日,赛灵思公司战略与市场营销高级副总裁Steve Glaser与赛灵思云计算战略市场开发总监Andy Walsh就赛灵思FPGA芯片在数据中心的主流应用与记者展示了座谈.   Steve Glaser首先向大家介绍了赛灵思在数据中心业务里完成的一些里程碑事件.包括与IBM.高通的联手合作,也包括百度亚马逊等超大型数据中心的成功应用,同时还包括赛灵思为加速FPGA在"超七大"数据中心中的主流应用而不断推出的产品.工具,以及在行业统一标准方面的先锋地位.   Andy Walsh则