`

大神带你分分钟超越最好结果——基于分布式CPU计算的Deeplearning4j迁移学习应用实例

阅读更多
原文链接:http://click.aliyun.com/m/26852/
摘要: 本文通过应用开源工具Apache Spack、Apache Hadoop和Deeplearning4j以分布式CPU运算完成VGG16模型迁移学习的应用,在Caltech-256数据集上实现了最好结果。

首发地址:https://yq.aliyun.com/articles/114669

更多深度文章,请关注:https://yq.aliyun.com/cloud

         2016年,欧莱礼媒体公司首席数据科学家罗瑞卡宣称:“2017年将是数据科学和大数据圈参与AI技术合作的一年。”在2017年之前,对基于GPU的深度学习已经渗透到大学和研究机构,但基于CPU分散式深度学习开始在不同的公司和领域得到广泛采用。虽然GPU提供了顶级的数字计算性能,但CPU也在变得更加高效,并且现有的大部分硬件已经有大量可用的CPU计算能力。另外GPU的价格比CPU的价格要相对而言贵好多,相信大家最近一阵也发现显卡的价格暴涨,这源于数字货币比特币的暴涨,而比特币是通过电脑计算得到,计算能力越强,其每天的计算量也就越多,相当于每天“挖矿”的量。涉及深度学习的研究员都应该了解一个事实,基于GPU跑一个网络和基于CPU跑同一个网络,二者的仿真速度可以达到20倍左右的差距。因此,基于CPU的分散式深度学习也会成为后续研究的一个方向。而开源工具Deeplearning4j的出现将快速深度学习扩展到Hadoop堆栈,这将是未来几年影响深度学习的主要催化剂。
本文将详细介绍如何使用开源工具——Apache Spark、Apache Hadoop和Deeplearning4j(DL4J),再加上商用硬件(Commodity Hardware,便宜、被广泛使用、容易被买到),能够使用有限的训练集在图像识别任务上获得最先进的结果。
Deeplearning4j:JVM的深度学习工具集
     Deeplearning4j是许多开源深度学习工具包之一,创建于2014年。DL4J集成了Hadoop和Spark,设计用于运行在分布式GPU和CPU上的商用环境。它由总部位于旧金山的商用智能和企业软件公司Skymind牵头开发。团队成员包括数据专家、深度学习专家、Java系统工程师和具有一定感知力的机器人。虽然deeplearning4j是为JVM构建的,但它使用高性能原生线性代数库Nd4j,可以对CPU或GPU进行大量优化的计算。另外使用Java编写的DL4J API对于熟悉Java虚拟机(JVM)的Java和Scala开发人员特别有吸引力。此外,Spark模型的并行训练能力使得我们轻松利用现有的群集资源来加快训练时间,而不会牺牲精度。
基于Caltech-256图像数据集的对象分类
     本文介绍如何使用Apache Spark、Apache Hadoop和deeplearning4j来解决图像分类问题。简单来说,就是通过构建一个卷积神经网络来对Caltech-256数据集中的图像进行分类。在Caltech-256数据集中,实际上有257个对象类别,每类数量大概是80到800个图像,该数据集总共30,607个图像。值得注意的是,该数据集上目前最先进的分类精度在72 - 75%范围内。下面我将带领大家使用DL4J和Spark轻松超越这个结果。

小数据上的有效深度学习
     目前,卷积网络可以有几亿个参数,比如在大型视觉识别挑战 “ImageNet”中表现最佳的神经网络之一,有1.4亿个参数需要训练!这些网络不仅需要大量的计算和存储资源(即使是使用一组GPU,也可能需要几周时间才能完成计算),而且还需要大量数据。而Caltech-256只有30000多张图像,在这个数据集上训练这样一个复杂的模型是不现实的,因为没有足够的样本来充分学习这么多参数。相反,可以采用一种迁移学习的方法来实现。简单来说,就是将已学到的知识应用到其它领域,使其能够更好地完成新领域的学习。这是因为卷积神经网络在对图像数据集进行训练时往往会学习非常普遍的特征,因此这种类型的特征学习通常对其他图像数据集也是通用的。例如,在ImageNet上训练的网络可能已经学会了如何识别形状、面部特征、图案、文本等,这无疑对于Caltech-256数据集是有用的。
加载预训练的模型
     下面讲解如何使用训练好的模型来完成自己的任务,以下示例使用VGG16 模型,该模型夺得了2014 ImageNet竞赛中的亚军(网络结构及训练好的参数已公开)。由于使用了不同的图像数据集,所以需要对VGG16模型进行微小修改以适用于Caltech-256数据集预测任务。该模型具有约1.4亿个参数,大约占用500 MB空间。

首先,获取DL4J可以理解和使用的VGG16型号的版本。事实证明,这种东西是建立在DL4J的API中的,它可以通过几行Scala代码完成。


val modelImportHelper = new TrainedModelHelper(TrainedModels.VGG16)
val vgg16 = modelImportHelper.loadModel()
val savePath = "./dl4j-models/vgg16.zip"
val locationToSave = new File(savePath)
// save the model in DL4J native format, which is faster for future reads
ModelSerializer.writeModel(vgg16, locationToSave, saveUpdater = true)

该模型采用的格式易于DL4J使用,使用内置的模型进行检查。


val modelFile = new File("./dl4j-models/vgg16.zip")
val vgg16 = ModelSerializer.restoreComputationGraph(modelFile)
println(vgg16.summary())


==================================================================================================

VertexName (VertexType)                 nIn,nOut       TotalParams    ParamsShape                    Vertex Inputs

==================================================================================================

input_2 (InputVertex)                   -,-            -              -                              -

block1_conv1 (ConvolutionLayer)         3,64           1792           b:{1,64}, W:{64,3,3,3}         [input_2]

block1_conv2 (ConvolutionLayer)         64,64          36928          b:{1,64}, W:{64,64,3,3}        [block1_conv1]

block1_pool (SubsamplingLayer)          -,-            0              -                              [block1_conv2]

block2_conv1 (ConvolutionLayer)         64,128         73856          b:{1,128}, W:{128,64,3,3}      [block1_pool]

block2_conv2 (ConvolutionLayer)         128,128        147584         b:{1,128}, W:{128,128,3,3}     [block2_conv1]

block2_pool (SubsamplingLayer)          -,-            0              -                              [block2_conv2]

block3_conv1 (ConvolutionLayer)         128,256        295168         b:{1,256}, W:{256,128,3,3}     [block2_pool]

block3_conv2 (ConvolutionLayer)         256,256        590080         b:{1,256}, W:{256,256,3,3}     [block3_conv1]

block3_conv3 (ConvolutionLayer)         256,256        590080         b:{1,256}, W:{256,256,3,3}     [block3_conv2]

block3_pool (SubsamplingLayer)          -,-            0              -                              [block3_conv3]

block4_conv1 (ConvolutionLayer)         256,512        1180160        b:{1,512}, W:{512,256,3,3}     [block3_pool]

block4_conv2 (ConvolutionLayer)         512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_conv1]

block4_conv3 (ConvolutionLayer)         512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_conv2]

block4_pool (SubsamplingLayer)          -,-            0              -                              [block4_conv3]

block5_conv1 (ConvolutionLayer)         512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block4_pool]

block5_conv2 (ConvolutionLayer)         512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block5_conv1]

block5_conv3 (ConvolutionLayer)         512,512        2359808        b:{1,512}, W:{512,512,3,3}     [block5_conv2]

block5_pool (SubsamplingLayer)          -,-            0              -                              [block5_conv3]

flatten (PreprocessorVertex)            -,-            -              -                              [block5_pool]

fc1 (DenseLayer)                        25088,4096     102764544      b:{1,4096}, W:{25088,4096}     [flatten]

fc2 (DenseLayer)                        4096,4096      16781312       b:{1,4096}, W:{4096,4096}      [fc1]

predictions (DenseLayer)                4096,1000      4097000        b:{1,1000}, W:{4096,1000}      [fc2]

--------------------------------------------------------------------------------------------------------------------------------------------

           Total Parameters:  138357544

       Trainable Parameters:  138357544

          Frozen Parameters:  0

==================================================================================================


上面代码显示VGG16网络的结构及参数,ConvolutionLayer表示卷积层、SubsamplingLayer表示采样层、DenseLayer表示全连接层。下图简明扼要的展示了该网络结构:

7b68f25bb9d9cf6fe4cb67cdbaa6dae34a2b2f05

           VGG16具有13个卷积层,中间间隔放置最大池化层以收缩图像,降低计算复杂度。卷积层中的权重实际上是过滤器,可以学习从图像中挑选出视觉特征,当使用最大池化层时,它们会“收缩”图像,这意味着后来的卷积层中的滤波器实际上提取更加抽象的特征。这样,卷积层的输出是输入图像的抽象的视觉特征,如“这个图像中有脸吗?”还是“有日落?”卷积层的输出被馈送到连续的三个全连接层,全连接层能够学习这些视觉特征与输出之间的非线性关系。

另外卷积网络的关键性质之一是允许我们进行迁移学习——可以通过已经训练好的VGG16网络传递新的图像数据,并获取每个图像的特征。一旦提取了这些特征,就只需要送人最后的预测网络就可以完成相应的任务,这在计算和复杂度上都是非常容易解决的问题。

使用VGG16进行图像特征化
     数据集可以从Caltech-256 网站下载,拆分为三个数据集,分别为训练/验证/测试数据集,并存储在HDFS中。一旦完成该步骤,下一步就是将整个图像数据集传递到网络的所有卷积层和第一个全连接层,并将该输出保存到HDFS。
     样做的原因是是因为卷积网络中的大多数内存占用和耗时计算都是发生在卷积层中,VGG16中的大多数参数(权重)调用发生在全连接层。迁移学习利用预先训练的卷积层来获取关于新输入图像的特征,这意味着只有原始模型的一小部分——全连接层被重新训练。其余的参数是静态不变的。通过这种操作,迁移学习可以节省大量的训练时间和计算量。
首先提取用于特征化步骤的网络部分,Deeplearning4j具有内置的迁移学习API可用于此任务。即拆分VGG16模型,在拆分之前和之后获取整个图层列表,代码如下。


val modelFile = new File("./dl4j-models/vgg16.zip")
val vgg16 = ModelSerializer.restoreComputationGraph(modelFile)
val (frozenLayers: Array[Layer], unfrozenLayers: Array[Layer]) = {
vgg16.getLayers.splitAt(vgg16.getLayers.map(_.conf().getLayer.getLayerName).indexOf("fc2") + 1)
}
现在使用org.deeplearning4j.nn迁移学习包来提取全连接“fc2”层之前(包括“fc2”层)的网络模型,如下图所示:垂线左边部分。

dc9a57ad25f7dcb047bd3f695301bcad81315d14



val builder = new TransferLearning.GraphBuilder(model)
.setFeatureExtractor(frozenLayers.last.conf().getLayer.getLayerName)
// remove all the unfrozen layers, leaving just the un-trainable part of the model
unfrozenLayers.foreach { layer =>
builder.removeVertexAndConnections(layer.conf().getLayer.getLayerName)
}
builder.setOutputs(frozenLayers.last.conf().getLayer.getLayerName)
val frozenGraph = builder.build()
     接下来是读取数据库中的图像文件。在这种情况下,这些文件被单独保存到HDFS作为JPEG文件。图像被组织成子目录,其中每个子目录包含属于特定类的一组图像。首先通过使用sc.binaryFiles 加载存储在HDFS中的图像,并使用DataVec库(DL4J的ETL库)中的图像处理工具将它们转换为INDArrays,这是DL4J处理的本机张量表示(此处为完整代码)。最后,使用上图中的冻结网络部分对输入图像进行特征提取,本质上是将它们传递到VGG16模型中的预测层前。


val finalOutput = Utils.getPredictions(data, frozenGraph, sc)
val df = finalOutput.map { ds =>
(Nd4j.toByteArray(ds.getFeatureMatrix), Nd4j.toByteArray(ds.getLabels))
}.toDF()

df.write.parquet("hdfs:///user/leon/featurizedPredictions/train")
      经过上述操作后,得到一个保存到HDFS中新的数据集。接下来可以开始构建使用这种特征化数据的传输学习模型,从而大大减少训练时间和计算复杂度。在上述示例中,得到的新数据集由30607个长度为4096的向量组成(这是由于VGG16模型中的全连接层“f2”维度为4096)。

替换VGG16的预测层
         VGG16模型是在ImageNet数据集上进行训练的,而ImageNet数据集具有1000种不同对象类别。在典型的图像分类神经网络中,输出层的最后一层使用其输入来为数据集中的每个对象生成概率(哪一类的概率大就判断为哪一类)。因此,该输入可以被认为是关于图像的抽象视觉特征,提供关于其包含的对象的有用信息。直观地说,上述步骤生成的新数据集于Caltech-256数据集中识别对象应该是有用的。因此,定义一个新的模型,“f2”层前的模型不变,只是替换VGG16模型的最后一层预测层,将维度从原先的1000变成257,正好对应Caltech256数据集的257个类别。


val conf = new NeuralNetConfiguration.Builder()
.seed(42)
.optimizationAlgo(OptimizationAlgorithm.STOCHASTIC_GRADIENT_DESCENT)
.iterations(1)
.activation(Activation.SOFTMAX)
.weightInit(WeightInit.XAVIER)
.learningRate(0.01)
.updater(Updater.NESTEROVS)
.momentum(0.8)
.graphBuilder()
.addInputs("in")
.addLayer("layer0",
   new OutputLayer.Builder(LossFunction.NEGATIVELOGLIKELIHOOD)
     .activation(Activation.SOFTMAX)
     .nIn(4096)
     .nOut(257)
     .build(),
   "in")
.setOutputs("layer0")
.backprop(true)
.build()
val model = new ComputationGraph(conf)
直观图如下,可以看到只是改变了预测层的维度:

5d799bde174c83a77bb5082b6ea162a67dc56c79

    该模型现在已准备好使用DL4J进行大量计算,而且还使用Spark进行规模化。简单来说是切分大规模的数据集,然后将分片交给spark群集中的每个工作核心上运行SGD,最后使用Spark RDD聚合操作对每个核心上学习的不同模型进行平均,实现分布式训练。


val tm = new ParameterAveragingTrainingMaster.Builder(1)
.averagingFrequency(5)
.workerPrefetchNumBatches(2)
.batchSizePerWorker(32)
.rddTrainingApproach(RDDTrainingApproach.Export)
.build()
val model = new SparkComputationGraph(sc, graph, tm)
现在针对具体的迭代次数训练SparkComputationGraph,并监控一些训练统计数据以跟踪进度。


model.setListeners(new ScoreIterationListener(1))
(1 to param.numEpochs).foreach { i =>
logger4j.info(s"epoch $i starting")
model.fit(trainRDD)

// print model accuracy and score on entire train and validation sets every 5 iterations
if (i % 5 == 0) {
   logger4j.info(s"Train score: ${model.calculateScore(trainRDD, true)}")
   logger4j.info(s"Train stats:\n${Utils.evaluate(model.getNetwork, trainRDD, 16)}")
   if (validRDD.isDefined) {
     logger4j.info(s"Validation stats:\n${Utils.evaluate(model.getNetwork, validRDD.get, 16)}")
     logger4j.info(s"Validation score: ${model.calculateScore(validRDD.get, true)}")
   }
}
}
最后,通过spark提交训练工作,然后使用DL4J webui监控进度并诊断问题。下图绘制的是模型得分与迭代次数的关系,注意到分数是minibatch的负对数似然率,分数越小,效果越好。

b58c5b4d78ad0cd097854d0083f4593507d379ea

这次将学习率调低后,该模型似乎能比Imagenet模型能更快地学习,因为这次使用的特征比ImageNet概率更具预测性。


17/05/12 16:06:12 INFO caltech256.TrainFeaturized$: Train score: 0.6663876733861492
17/05/12 16:06:39 INFO caltech256.TrainFeaturized$: Train stats:
Accuracy: 0.8877570632327504
Precision: 0.8937314411403346
Recall: 0.876864905154427

17/05/12 16:07:17 INFO caltech256.TrainFeaturized$: Validation stats:
Accuracy: 0.7625918867410836
Precision: 0.7703367671469078
Recall: 0.7383574179140013

17/05/12 16:07:26 INFO caltech256.TrainFeaturized$: Validation score: 1.08481537405921
由于训练准确率为88.8%,但验证准确率仅为76.3%,从结果上看该模型似乎已经过拟合了。为了确保模型不会过拟合到验证集,在测试集上评估该模型。


Accuracy: 0.7530218882718066
Precision: 0.7613121478786196
Recall: 0.7286152891276695
虽然准确率有所降低,但是使用基于现有Hadoop集群和商用CPU的简单深度学习架构仍然打破了该数据集的最好结果!虽然这可能不是一个突破性的成就,但这仍然是一个令人兴奋的结果。
结论
    虽然deeplearning4j只是许多深度学习可用的工具之一,但它具有本机Apache Spark集成,并且采用Java编写,使其特别适合整个Hadoop生态系统。由于现有的企业数据已经通过Hadoop进行了大量访问,而且在Spark上进行处理,所以deeplearning4j的定位是花费更少的时间部署和减少开销,从而企业公司可以立即开始从深度学习中提取数据。它利用ND4J进行大量计算,这是一种高度优化的库,可与商用CPU配合使用,但在需要性能提升时也支持GPU。Deeplearning4j提供了一个全功能的深度学习库,具有从采集到部署的工具,可
用于各种任务,如图像/视频识别,音频处理等。

作者信息
Nisha Muktewar,数据科学家,目前就职于Cloudera的数据科学团队,专注于专业服务、售前工作。
Seth Hendrickson,以前是电气工程师,现在是数据科学家和软件工程师,研究方向是分布式机器学习。

本文由北邮@爱可可-爱生活老师推荐,阿里云云栖社区组织翻译。

文章原标题《Deep learning on Apache Spark and Apache Hadoop with Deeplearning4j | Cloudera Engineering Blog》,作者:Nisha Muktewar、Seth Hendrickson,译者:海棠,审阅:
原文链接:http://click.aliyun.com/m/26852/
  • 大小: 21.6 KB
分享到:
评论

相关推荐

    Deep Learning——Nature2015.pdf

    经典深度学习教材,入门深度学习必备数目,...经典深度学习教材,入门深度学习必备数目,众多大神推荐,经典深度学习教材,入门深度学习必备数目,众多大神推荐,经典深度学习教材,入门深度学习必备数目,众多大神推荐

    深度学习(Deep Learning) 三本 Part I 【共 5 个分卷】

    Deep Learning Part I 深度学习(Deep Learning) 中文版 [ 感谢大神们的翻译 Github 地址:https://github.com/exacity/deeplearningbook-chinese ],中文文字版,【 在线版本地址:...

    深度学习(Deep Learning) 三本 Part II 【共 5 个分卷】

    Deep Learning Part II 深度学习(Deep Learning) 中文版 [ 感谢大神们的翻译 Github 地址:https://github.com/exacity/deeplearningbook-chinese ],中文文字版,【 在线版本地址:...

    深度学习(Deep Learning) 三本 Part IV 【共 5 个分卷】

    Deep Learning Part IV 深度学习(Deep Learning) 中文版 [ 感谢大神们的翻译 Github 地址:https://github.com/exacity/deeplearningbook-chinese ],中文文字版,【 在线版本地址:...

    Deep Learning电子书

    Bengio大神的 deeplearning 电子书全部章节

    深度学习(Deep Learning) 三本 Part V 【共 5 个分卷】

    Deep Learning Part V 深度学习(Deep Learning) 中文版 [ 感谢大神们的翻译 Github 地址:https://github.com/exacity/deeplearningbook-chinese ],中文文字版,【 在线版本地址:...

    Deep Learning - Yoshua Bengio

    全面讲解Deep Learning的一本好书,作者是机器学习大神Yoshua Bengio, Ian Goodfellow and Aaron Courville,这是最新的版本(Version 03/10/2015),为方便阅读,制作成PDF的格式。

    分布式算法学习资料

    4. 分布式调度和任务分配:如何有效地在多台机器之间分配任务,优化资源利用率,是分布式计算中的重要问题。 5. 分布式数据存储与检索:如GFS(Google File System)、HDFS(Hadoop Distributed File System)等,...

    ChartCtrl——基于MFC的自绘表格控件

    《ChartCtrl——基于MFC的自绘表格控件深度解析》 在软件开发过程中,界面设计与数据展示是至关重要的环节。MFC(Microsoft Foundation Classes)作为微软提供的一套C++库,为开发者提供了丰富的控件和框架支持,极...

    deep learning caffe入门

    《深度学习中文版20170904.pdf》可能是Yann LeCun、 Yoshua Bengio 和 Geoffrey Hinton三位深度学习大神合著的经典著作《Deep Learning》的中文译本。这本书全面介绍了深度学习的基础理论、技术和应用,涵盖了神经...

    分布式系统.zip

    《分布式计算——原理、算法和系统》可能是另一本深入探讨分布式计算的书籍,它可能涵盖了分布式计算模型、并行算法、网格计算、云计算等方面。这本书有助于读者理解如何在大规模分布式环境中有效利用计算资源。 ...

    OpenCV+DeepLearning+Python2周速成教程及源码(第一周)

    Adrian Rosebrock大神力作,16天速成教程,把你从计算机视觉小白变成大师,从简单的人脸检测案例入手,包含opencv图像处理基础、OCR文档扫描,计算机自动阅卷的光学标志识别OMR、球运动跟踪、物体大小尺寸测量、人脸...

    考研数学——140分大神告诉你考研数学如何开挂复习.pdf

    在考研数学的复习过程中,140分大神分享了他的成功秘诀,这主要包括以下几个关键环节: 1. **前期准备**:首先,这位大神以“空杯心态”重新认识数学,通过阅读各类数学书籍、下载数学论文,以及利用网络资源来加深...

    《UE4实例》大神作者Benjamin Carnall原版电子书

    《UE4实例》是由大神级作者Benjamin Carnall撰写的一本深入浅出的Unreal Engine 4(简称UE4)教程书籍。这本书以其实践性强、案例丰富的特点,深受UE4学习者和开发者喜爱。通过这本书,读者可以系统地了解并掌握UE4...

    tandford Deep learning for NLP lecture3

    标签“深度学习 deep learning NLP”则清楚地指出了本次课程的重点内容,即深度学习以及其在自然语言处理中的应用。这表明课程将深入探讨深度学习技术如何被应用于自然语言处理任务,包括语言模型的构建、语义理解、...

    《Neural Networks and Deep Learning》中文版

    Michael Nielsen 大神的 《Neural Networks and Deep Learning》 网络教程一直是很多如我一样的小白入门深度学习的很好的一本初级教程。不过其原版为英文,对于初期来说我们应该以了解原理和基本用法为主,所以中文...

    基于tensorflow Inception V3模型迁移学习的图片鉴定分类程序(鉴黄、鉴血腥)

    基于tensorflow Inception V3模型迁移学习的图片鉴定程序 色情图片鉴定 血腥图片鉴定 代码是在官网的代码基础上更改后的,由于python水平有限,因此比较乱. 图片分类的最终正确率在95%左右,该模型在1W张图片之内就...

Global site tag (gtag.js) - Google Analytics