返回 登录
0

深度解析BigDL深度学习框架

作者:本文来源于Intel官网
编译:孙浩峰
责任编辑:孙浩峰  技术之路,一起进步,云计算、大数据、人工智能、运维、安全等方面的干货文章,欢迎投稿。
投稿信箱:sunhf@csdn.net

BigDL是一种基于Apache Spark的分布式深度学习框架。通过BigDL,开发者可以使用Scala或Python语言编写深度学习应用程序,并可以充分发挥Spark群集在可扩展方面的强大能力。这篇文章主要介绍BigDL、并展示如何在各种平台上构建BigDL深度学习框架,并举例说明了BigDL的实际应用。

深度学习是什么?

深度学习是机器学习的一个分支,深度学习通过算法来描述更加抽象的高层表示属性类别或特征,以发现数据的分布式特征表示。这些方法基于人工智能神经网络拓,并能够基于使用更大规模的数据集而扩展。

下图展示了传统学习和深度学习方法的基本区别。在传统的方法中,通常会注重一个阶段的特征提取,并以此来作为机器学习的模型,而深度学习则通过在模型中创建特征提取流水线来增加学习的深度。这些在深度学习特征提取流水线中的多个阶段,通过分层特征提取,将最终提高模型的整体预测准确性。


图片描述
图1 深度学习特征提取流水线

BigDL 是什么?

BigDL是一款基于Apache Spark的分布式深度学习框架,它可以无缝的直接运行在现有的Apache Spark和Hadoop集群之上。开发者可以使用Scala或Python语言编写深度学习应用程序。

丰富的深度学习算法支持

BigDL的设计吸取了Torch框架许多方面的知识,为深度学习提供了全面的支持;包括数值计算(numeric computing)和高级神经网络(high level neural networks);除此之外,用户可以使用BigDL将事先训练好的Caffe或Torch模型加载到Spark程序中。

强大的扩展能力

BigDL可以很高效地进行横向规模扩展并处理大规模数据。通过利用Spark计算框架,以及Synchronous SGD的高效实现,全面减少了在Spark上的通信。

极高的性能

为了实现极高的性能,BigDL使用了Intel MKL和在每个Spark task中进行了多线程编程。所以,BigDL比其他开源框架Caffe、Torch和TensorFlow有显著的性能提升。BigDL速度可与主流GPU匹敌,而且能够扩展到数十个Xeon服务器。

什么是 Apache Spark ?

Spark是由加州大学伯克利分校、AMP实验室开发的具有闪电般速度的分布式数据处理框架。Spark可以运行在独立模式下,也可以在YARN、Hadoop或Apache Mesos的集群上(图 2) 运行。Spark从各种来源处理数据,包括HDFS、Apache Cassandra或 Apache Hive。其高性能来源于通过内存持久性的RDDs或DataFrames代替以前将数据保存在Hadoop MapReduce体系结构中的硬盘而获得的内存处理能力。


图片描述
图2 Apache Spark栈中的BigDL

为什么使用 BigDL?

您可能需要使用BigDL开发深度学习应用,如果满足下列条件之一:

1.您的数据存储在HDFS,HBase,Hive上,并想使用同一大数据集群(Hadoop/Spark)来分析数据;

2.在Spark程序中/工作流中加入深度学习功能;

3.利用现有的 Hadoop/Spark 集群来运行深度学习程序,然后将代码与其他的应用场景进行动态共享,例如ETL、数据仓库(data warehouse)、特征工程(feature engineering)、经典机器学习(classical machine learning)、图表分析(graph analytics)等。

(不适合使用BigDL的场景是使用Spark以外的另一种分布式的框架来实现深度学习的算法。)

安装工具链

注:本文主要针对全新安装BigDL的用户,并假设您没有安装任何 Linux 工具。如果您不是Linux用户新手,可以随时跳过一些基本的安装步骤,比方说,类似于Git的安装。

在Oracle VM VirtualBox上安装工具链

要在Oracle VM VirtualBox 上安装工具链,请执行以下步骤:

1.启用计算机BIOS中的虚拟化设置 (如图3)。BIOS中虚拟化的设置通常在安全菜单下,需要重新启动计算机并进入BIOS设置菜单进行设置。


图片描述
图3 启用计算机BIOS中的虚拟化功能

2.确定您的计算机是否是64位或32位的。目前,大多数计算机是64位的,但是为了确认,请进入控制面板-系统和安全-系统中查看(图4)。


图片描述
图4 确认您的计算机是否是32位或64位

注:您的计算机必须拥有4 GB以上的内存。您的虚拟机 (VM)可以在2 GB内存的机器上运行,将大多数 BigDL示例在2GB内存环境下运行效果很差(或者根本无法运行)。要执行本篇文章的示例,建议您的计算机至少拥有8 GB内存。

3.从VirtualBox 网站安装 VirtualBox GuestAdditions 或其他虚拟机客户端。图5中的虚拟机正在运行 BigDL。


图片描述
图5 虚拟机正在运行BigDL

重要:
您需要预留35-50 GB 的硬盘,以用于Ubuntu、Spark、BigDL和所有 DeepLearning模块的安装,在分配硬盘空间,建议选择"动态"分配,以便您以后扩展分区(虽然并不常用)。但如果您选择"静态"磁盘分配方式,如果遇到运行时磁盘空间不足,您唯一的选择就是格式化硬盘,重新安装整个系统。

4.从Ubuntu 下载页面安装 Ubuntu。

5.下载完成后,请指定您的虚拟机启动文件为下载的安装文件,以便可以通过其引导系统启动。(有关Ubuntu安装得详细说明,请转到Ubuntu 常见问题解答)

sudo apt-get update
sudo apt-get upgrade

执行上述两条命令,安装就将开始,除非是另有说明,Ubantu将会顺利的完整安装在您的虚拟机上。

如果您在访问Internet时遇到问题,您可能需要设置代理服务器(注意:VPN和Cisco AnyConnect经常会修改虚拟机的代理服务器设置,所以最好不要使用它们来进行虚拟机的安装)。VirtualBox 5.1.12和 64位Ubuntu代理服务器设置请见图6。


图片描述
图6 Oracle VM VirtualBox 5.1.12和64 bit Ubuntu的代理服务器设置

6.使用以下命令安装 Java :
sudo add-apt-repository ppa:webupd8team/java
sudo apt-get update
sudo apt-get install oracle-java8-installer

7.验证Java的版本:
java –version

8.从Scala下载页面安装Scala 2.11版本

下载Scala时,请使用 Debian文件格式,默认情况下,下载的文件默认将会保存在Downloads文件夹下。在文件浏览器中,找到Scala,并单击它,然后执行下列命令:
sudo apt-get update

9.从Spark 下载页面下载并安装 Spark。

以下的命令适用于Spark 1.6,如果您安装了不同版本,请替换为1.6.x版本:

a.用您下载的版本替换现有的Spark版本:
$ cd Downloads
$ tar -xzf spark-1.6.1-bin-hadoop2.6.tgz
b.将文件移到适当位置:
$ sudo mkdir /usr/local/spark
$ sudo mv spark-1.6.1-bin-hadoop2.6 /usr/local/spark

c.对安装进行测试:
$ cd /usr/local/spark
$ cd spark-2.1.0-bin-hadoop2.6
$ ./bin/spark-shell

d.安装 Git:
$ sudo apt-get install git

下载BigDL

BigDL可以使用 Git 源代码管理工具从 GitHub 获得。用以下命令克隆 BigDL Git 存储库:
$ git clone https://github.com/intel-analytics/BigDL.git

完成后,您将看到新的子目录,名为BigDL,其中包含 BigDL 存储库。您还必须安装Apache Maven,,以便编译Scala代码,安装命令如下:
$ sudo apt-get install maven

构建 BigDL

本节将向您展示如何在您的 Linux 发行版中下载并构建 BigDL。构建BigDL的前提条件是:
•Java 8 (为获得最佳性能);
•Scala 2.10 或 2.11 (如果您打算使用 Spark 2.0 或更高版本,您还必须安装 Scala 2.11);
•Maven 3
•Git

Apache Maven 环境设置

您需要Maven 3构建BigDL。您可以从Maven网站下载Maven。

安装Maven 3后,需要设置环境变量MAVEN_OPTS :

$ export MAVEN_OPTS="-Xmx2g -XX:ReservedCodeCacheSize=512m"

在编译Java 7时,您必须添加选项-XX:MaxPermSize=1G.

构建

强烈建议您使用make-dist.sh script构建BigDL,下载完成后,请使用以下命令构建BigDL:

$ bash make-dist.sh

在此之后,您可以找到包含您需要运行BigDL的所有文件的文件夹dist。在dist文件中包括:

1.dist/bin/bigdl.sh。使用此脚本来设置适当的环境变量和启动BigDL。

2.dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies.jar。这个JAR包包含了除Spark以外的所有依赖项。

3.dist/lib/bigdl-0.1.0-SNAPSHOT-jar-with-dependencies-and-spark.jar。此 JAR包包含所有依赖项,包括Spark。

替代方案

如果您正在构建 Spark 2.0,您应修改bash调用为Scala 2.11版本。Spark 2.0默认情况下使用 Scala 2.11,为此您需要在执行make-dist.sh脚本中使用–P spark_2.0参数,如下所示:
$ bash make-dist.sh -P spark_2.0

强烈建议在Spark 2.0运行时,使用Java 8。否则,系统性能将急剧下降。默认情况下,make-dist.sh为Spark 1.5.x/1.6.x 使用Scala 2.10,为Spark 2.0使用Scala 2.11。要覆盖默认行为,请在执行make-dist.sh时使用-P scala_2.10或-P scala_2.11参数。

快速入门

在开始运行BigDL 之前,您还需要先做几个小步骤。本节主要介绍这些入门步骤。

设置环境变量

为实现高性能,BigDL使用英特尔MKL和多线程的编程。因此,您首先必须使用如下所示的PATH_To_BigDL/scripts/bigdl.sh脚本设置环境变量:
$ source PATH_To_BigDL/scripts/bigdl.sh
或者,您可以使用PATH_To_BigDL/scripts/bigdl.sh脚本启动BigDL。

使用交互式 Scala Shell

您可以通过使用交互式Scala shell测试BigDL代码。要执行此操作,请运行:

`$ scala -cp bigdl-0.2.0-SNAPSHOT-jar-with-dependencies-and-spark.jar

`然后,您可以看到类似:

Welcome to Scala 2.11.8 (Java HotSpot(TM) 64-Bit Server VM, Java 1.8.0_91).
Type inexpressions forevaluation. Or try :help.
scala>

例如,要测试BigDL中Tensor应用编程接口 (APIs),您可以使用如下命令:

scala> importcom.intel.analytics.bigdl.tensor.Tensor
importcom.intel.analytics.bigdl.tensor.Tensor
scala> Tensor[Double](2,2).fill(1.0)
res9: com.intel.analytics.bigdl.tensor.Tensor[Double] =
1.0 1.0
1.0 1.0
[com.intel.analytics.bigdl.tensor.DenseTensor of size 2x2]

有关BigDL APIs的更多详细信息,请参阅BigDL编程指南。

运行本地 Java程序 (单模式)

您可以运行一个 BigDL 程序(例如VGG 模型培训),作为以单模式(计算机)运行的本地 Java 程序。为此,请执行以下步骤:

1.从CIFAR 10 数据集页面中下载 CIFAR 10 数据.
请记住,选择二进制文件的版本。

2.使用bigdl.sh脚本运行本地的 Java 程序示例:

./dist/bin/bigdl.sh -- \
java -cpdist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies-and-spark.jar \
com.intel.analytics.bigdl.models.vgg.Train \
--core core_number \
--node 1 \
--envlocal \
-f cifar10_folder \
-b batch_size

3.此命令使用以下参数:
–core。在训练中使用的物理内核数量
–node。在训练中使用的节点数 (计算机)(例如在此情况下运行作为本地的 Java 程序时,其设置为1.)
–env。”local”或”spark”(在此示例中,它被设置为”local”.)
-f。存储 CIFAR 10 数据集的文件夹
-b。mini-batch的大小(程序所预计的mini-batch大小是node_number ×core_number的乘积。在此示例中,node_number是1,所以需要将最小化批处理大小设置为core_number×4)。

运行一个Spark程序

您可以运行一个BigDL程序(例如,VGG模型培训),作为标准Spark程序(在本地模式或群集模式下运行)。为此,请执行以下步骤:

1.从CIFAR 10数据集页面中下载CIFAR 10数据。请记住,选择二进制文件的版本。

2.使用bigdl.sh script来运行一个Spark示例:

./dist/bin/bigdl.sh -- \
spark-submit --class com.intel.analytics.bigdl.models.vgg.Train \
dist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies.jar \
--core core_number_per_node \
--node node_number \
--envspark \
-f cifar10_folder/ \
-b batch_size

6.此命令使用以下参数:

–core。在 Spark 群集的每个执行程序(或容器)中使用的物理内核数

–node。在Spark群集中,执行程序(容器)的数量(当运行在Spark本地模式下,此数量设置为1)

–env。”local”或”spark”(在此情况下,它被设置为”spark”.)
-f。存放 CIFAR 10 数据集的文件夹(请注意,在此示例中,这是只需保存在 Spark驱动器上的本地文件文件夹。因为 CIFAR 10数据有点小[大约120MB],在此示例中,可以直接将此数据从驱动器中发送给执行程序)
-b。mini-batch的大小(预期的mini-batch大小是node_number×core_number_per_node的乘积。在此示例中,mini-batch大小设置应为为node_number×core_number_per_node×4.)

在Mac OS中的安装说明

一般情况下,在Mac OS的安装是比在Windows虚拟机中的安装要简单,因为Mac OS是基于Unix的。但是,命令的语法明显不同。以下是一些有区别的地方:

1.安装Java

转至java.com并安装JDK的Mac OS版本。按照安装提示。您需要安装Mac OS JDK(Java 开发套件)。或者,您可以打开一个终端提示并键入

$ java –version

这将提示您安装 JDK (单击”更多信息”而不是”确定“按钮)。

2.验证Java的版本:

java –version

预期的输出:

图片描述

按照说明安装 Scala,具体参考此处http://biercoff.com/how-to-install-scala-on-mac-os/

Spark的安装步骤和上述在虚拟机中的安装步骤一样。

安装 Homebrew: https://brew.sh

安装 Git:

$ brew installgit
Do a git pull as directed above.
Maven may have been installed already as part of one of the previous steps. To check:
$ mvn –v.

期待的输出:

图片描述

如果未安装Mavon,只需通过以下命令安装

$ brew install maven

调试常见的问题

目前,BigDL使用同步的mini-batch SGD模型训练,当处理一个mini-batch时,它将在每个执行程序 (或容器) 上启动一个 Spark 任务 (在多线程模式下运行):

•设置Engine.nodeNumber的值为在 Spark 群集中的执行器的数量。

•请确保每个 Spark执行程序具有相同数量的内核 (Engine.coreNumber)。

•Mini-batch的大小必须是nodeNumber×coreNumber的乘积。

注意:在Spark 2.0 与 Java 7 环境中运行 BigDL性能欠佳,因此建议在Spark 2.0和Java 8环境中构建和运行 BigDL。

在Spark 2.0中,默认使用Java串行器而代替Kryo,这是由于Kryo有一个341问题:”由于无标签的parentScope被推送给同一个对象而导致的栈溢出错误”(请参阅Kryo 问题页以了解更多信息)。Kryo 4.0中已修正此问题,但Spark 2.0使用 Kryo 3.0.3。Spark 1.5和1.6中也没有此问题。

在CentOS 6和7中,增加最大用户进程数为更大的值,比如514585。否则,您可能会看到这样的错误,例如”无法创建新的本地线程。”

目前,BigDL在训练中将加载所有的训练和验证数据到内存中,如果BigDL耗尽内存,可能会碰到错误。

BigDL示例

注意: 如果您使用的虚拟机,系统的性能将不如在本机操作系统中好,主要是由于虚拟机的可用的资源有限。同时,在虚拟机中也体现不出Spark的真实性能。

在MNIST上训练LeNet

一个在LeNet 上训练的”Hello World”的深度学习应用示例, (卷积神经网络——基于MNIST 数据库)。图7显示了一个克隆LeNet的示例。


图片描述
图7 克隆LeNet示例

BigDL程序开始于com.intel.analytics.bigdl的导入。然后,它会初始化引擎,包括执行器节点,每个执行程序的物理内核数量以及并确定程序是在Spark上运行,还是作为一个本地Java程序运行。

val sc = Engine.init(param.nodeNumber, param.coreNumber, param.env=="spark").map(conf => {
conf.setAppName("Train Lenet on MNIST")
.set("spark.akka.frameSize", 64.toString)
.set("spark.task.maxFailures", "1")
new SparkContext(conf)
})

如果在Spark上运行,Engine.init()会返回一个SparkConf值,这是一个可以用来创建SparkContext的正确配置的值。否则程序将以当地 Java 程序的方式运行运行,Engine.init()返回的值将为None。

初始化完成后,将开始通过调用LeNet5()创建LeNet 模型,这将创建 LeNet 5 卷积网络模型,如下所示:
val model = Sequential()
model.add(Reshape(Array(1, 28, 28)))
.add(SpatialConvolution(1, 6, 5, 5))
.add(Tanh())
.add(SpatialMaxPooling(2, 2, 2, 2))
.add(Tanh())
.add(SpatialConvolution(6, 12, 5, 5))
.add(SpatialMaxPooling(2, 2, 2, 2))
.add(Reshape(Array(12 * 4 * 4)))
.add(Linear(12 * 4 * 4, 100))
.add(Tanh())
.add(Linear(100, classNum))
.add(LogSoftMax())

接下来,通过创建DataSet.scala命令加载数据 (分布式或本地之一,具体取决于它是否在 Spark 上运行),然后运行一系列的Transformer.scala命令(例如, SampleToGreyImg、GreyImgNormalizer和GreyImgToBatch):
val trainSet = (if (sc.isDefined) {
DataSet.array(load(trainData, trainLabel), sc.get, param.nodeNumber)
} else {
DataSet.array(load(trainData, trainLabel))
})
-> SampleToGreyImg(28, 28)
-> GreyImgNormalizer(trainMean, trainStd)
-> GreyImgToBatch(param.batchSize)

在此之后,您可以通过指定数据集、 模型和标准创建优化器(分布式或本地之一,具体取决于它是否在 Spark 上运行),以给定输入和目标,从而计算出每个损失函数的梯度变化曲线:
val optimizer = Optimizer(
model = model,
dataset = trainSet,
criterion = ClassNLLCriterion[Float]())

最后,在选择指定的验证数据和验证方法进行优化之后, 您就可以通过调用Optimizer.optimize()来训练模型:
optimizer
.setValidation(
trigger = Trigger.everyEpoch,
dataset = validationSet,
vMethods = Array(new Top1Accuracy))
.setState(state)
.setEndWhen(Trigger.maxEpoch(param.maxEpoch))
.optimize()

以下是从命令行执行LeNet示例:
$ dist/bin/bigdl.sh -- \
java -cpdist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies-and-spark.jar \
com.intel.analytics.bigdl.models.lenet.Train \
-f ~/data/mnist/ \
--core 1 \
--node 1 \
--envlocal \
--checkpoint

以下是在虚拟机上执行LeNet Spark 本地模式的示例:

注意: 在采用Spark 本地模式运行之前,请导出SPARK_HOME=your_spark_install_dir和PATH=$PATH:$SPARK_HOME/bin:


$ ./dist/bin/bigdl.sh \
-- spark-submit \
--master local[1] \
--driver-class-path dist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies.jar \
--class com.intel.analytics.bigdl.models.lenet.Train \
dist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies.jar \
-f ~/data/mnist/ \
--core 1 \
--node 1 \
--envspark \
--checkpoint ~/model/model_lenet_spark

图像分类

注意:有关在预训练的模型上运行的图像推理示例,请参阅 BigDL README.md。将图像下载到ILSVRC2012_img_val.tar目录中。这个目录中是预训练的模型图像.tar文件。例如,将其解压到~/data/imagenet目录下。接着,下载resnet-18.t7模型,并将其保存在~/model/resnet-18.t7中。

从命令行运行以下命令 (本例为针对虚拟机,因此内存大小设置为1G):
$ ./dist/bin/bigdl.sh --spark-submit --master local[1] \
--driver-memory 1g \
--executor-memory 1g \
--driver-class-path dist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies.jar \
--class com.intel.analytics.bigdl.example.imageclassification.ImagePredictor \
dist/lib/bigdl-0.2.0-SNAPSHOT-jar-with-dependencies-and-spark.jar \
--modelPath ~/model/resnet-18.t7/resnet-18.t7 \
--folder ~/data/imagenet/predict_100 \
--modelType torch -c 1 -n 1 \
--batchSize 4 \
--isHdfs false

该程序输出具有两个列的表:*.JPEG文件名称和一个数字标签。要检查的预测的准确性,请参阅imagenet1000_clsid.txt标签文件(请注意,文件标签是从0开始的,而示例的标签是从1开始的)。

图像文件的前几行如下所示:

{0: 'tench, Tinca tinca',
 1: 'goldfish, Carassius auratus',
 2: 'great white shark, white shark, man-eater, man-eating shark, Carcharodon carcharias',
 3: 'tiger shark, Galeocerdo cuvieri',
 4: 'hammerhead, hammerhead shark',
 ...

以下是示例输出的开头几行:

[ILSVRC2012_val_00025162.JPEG,360]
[ILSVRC2012_val_00025102.JPEG,958]
[ILSVRC2012_val_00025113.JPEG,853]
[ILSVRC2012_val_00025153.JPEG,867]
[ILSVRC2012_val_00025132.JPEG,229]
[ILSVRC2012_val_00025133.JPEG,5]

图像ILSVRC2012_val_00025133.JPEG (图 8) 已被正确的标识为标签5,其对应的imagenet1000_clsid.txt文件中的条目为”4: ‘hammerhead,hammerhead shark’” 。

图片描述
图8 图像文件ILSVRC2012_val_00025133.JPEG

若要在 IntelliJ IDE 中运行分类示例,必须设置与在虚拟机略有不同的参数,如图9所示。

图片描述
图9 IntelliJ IDE中的分类示例

因为在如图 9 所示的 IntelliJ IDE 中,并没有显示全部命令行,在此补充虚拟机的选项:

-Dspark.master=local[1]
-Dspark.executor.cores=1
-Dspark.total.executor.cores=1
-Dspark.executor.memory=1g
-Dspark.driver.memory=1g
-Xmx1024m -Xms1024m

此处是程序参数:

ImageClassifier Program arguments:
  --modelPath ~/model/resnet-18.t7/resnet-18.t7
  --folder ~/data/imagenet/predict_100
  --modelType torch
  -c 1
  -n 1
  --batchSize 1
  --isHdfs false

广度和深度神经网络支持

BigDL 目前支持以下预置的神经网络模式:
• Autoencoder
• Inception
• LeNet
• Resnet
• Rnn
• VGG

有关详细信息,请参阅BigDL模型。

此外,BigDL 支持 100 多个标准的神经网络”构建模块“,允许您配置自己的拓扑结构 (图10)。

图片描述
图10 BigDL标准神经网络构建模块

有关详细信息,请参阅BigDL神经网络页面。

此外,BigDL自带端到端实现 LeNet、ImageNet和TextClassification (如图 11) 的示例程序。

图片描述
图11 BigDL示例

有关详细信息,请参阅BigDL示例页面。

缩写词
HDFS    Hadoop 分布式文件系统
IDE     集成的开发环境
MKL     数学核心函数库
RDD     弹性分布式数据集
RNN     循环神经网络
SGD     随机梯度下降
VM      虚拟机
YARN    另一个 Hadoop 资源管理器

CSDN原创,未经授权,禁止转载!

评论