订阅业界RSS CSDN首页> 业界

在 Apache Spark* 上使用 BigDL 推进人工智能

发表于2019-03-19 14:50| 来源intel| 作者intel

摘要:特性、用例和未来 英特尔公司高级首席工程师 Jason Dai ,工程经理 Radhika Rangarajan @IntelDevTools | 打分 自英特尔于 2016 年 12 月推出 BigDL 以来,它已经发展成为一个充满活力的开源项目。在本文中,我们提供了有关 BigDL 实施的详细信息,描述了真实的用例,并简要介绍了构建于 Apache Spark* 和 BigDL 之上的全新端...

特性、用例和未来

英特尔公司高级首席工程师 Jason Dai,工程经理 Radhika Rangarajan

@IntelDevTools| 打分

自英特尔于2016 12 月推出 BigDL 以来,它已经发展成为一个充满活力的开源项目。在本文中,我们提供了有关 BigDL 实施的详细信息,描述了真实的用例,并简要介绍了构建于 Apache Spark* BigDL之上的全新端到端分析和人工智能 (AI) 管道(Analytics Zoo 平台)。[编者注:我们在《The Parallel Universe》第 28 期发布了一篇文章BigDL:Apache Spark 上优化的深度学习,描述了该框架的首个版本。此后(该框架的)很多方面都发生了变化。]

为什么选择 BigDL

企业将深度学习技术(计算机视觉、自然语言处理、生成式对抗网络)应用于大数据平台和分析管道的需求越来越旺盛。为了将深度学习和大数据分析融合在一起,英特尔在 2016 12 月开放了 BigDL 分布式深度学习框架的源代码。

BigDL 可作为 Apache Spark 库运行,该库支持用户将大规模深度学习应用(包括模型训练和推理)编写为可在现有大数据(Hadoop* Spark)集群上直接运行的标准 Spark 程序。

BigDL 全面支持深度学习技术:

  • 神经网络运算
  • 损失
  • 优化器

特别是,用户能够以分布式的方式在 Spark 上直接运行在其他框架(如 TensorFlow*Keras*Caffe* Torch*)内定义的现有模型。BigDL 还可以将深度学习技术无缝集成至大数据生态系统。BigDL 程序不仅可以直接与 Spark 组件(如 DataFramesSpark Streaming、机器学习管道)交互,还可以在各种大数据框架(如 Apache Storm*Apache Flink*Apache Kafka*)上运行。

编写 BigDL 应用

由于 BigDL Apache Spark 中运行,用户可按照以下 5 个步骤轻松执行端到端的数据分析。

第一步:将文本数据(文章和相关标签)读取至 Spark 弹性分布式数据集 (RDD)

spark = SparkContext(appName=text_classifier, )

texts_rdd = spark.textFile(hdfs://...)

words_rdd = texts_rdd.map(lambda text, label:

                   ([w for w in to_words(text)], label))

第二步:使用 RDD 转换将加载的数据转变为训练示例的 RDD

w2v = news20.get_glove_w2v(dim=)

vector_rdd = words_rdd.map(lambda word_list, label  

                ([to_vec(w, w2v) for w in word_list], label))

sample_rdd = vector_rdd.map(lambda vector_list, label:                              

                              to_sample(vector_list, label))

第三步:构建一个神经网络模型。

model = Sequential().add(Recurrent().add(LSTM()))

                    .add(Linear())

                                   .add(LogSoftMax())

第四步:训练模型(使用指定的损失和优化方法)。

loss = ClassNLLCriterion()

optim_method = Adagrad()

optimizer = Optimizer(model=model, training_rdd=sample_rdd,                

                criterion=loss, optim_method=optim_method, )

optimizer.set_train_summary(summary=TrainSummary())

trained_model = optimizer.optimize()

第五步:使用现有模型(在 BigDLTensorFlow*Keras*Caffe* Torch* 中预先训练)预测结果

test_rdd =

prediction_rdd = trained_model.predict(test_rdd)

分布式训练

BigDL 使用同步小批量随机梯度下降和数据并行方式提供高度可扩展的分布式训练。它直接在 Spark 内部的 BlockManager 之上实施参数服务器 (PS) 架构(通过 all-reduce 运算)。每个任务计算各自的局部梯度,而不是将其发送至驱动环境,然后在本地从单个 worker 的所有分区聚合梯度。接着,每个节点的聚合梯度被分割为块,并在所有集群节点中交换块。每个节点负责特定的块,实质上是在 BigDL 中实施 PS 架构,以便同步参数。每个节点检索与聚合它负责计算的模型切片的梯度。成对交换完成后,每个节点拥有自己的聚合梯度部分,用于更新自己的权重部分。然后再次交换,以同步更新的权重。在这个过程的最后,每个节点均拥有更新权重的副本。因此,BigDL 可对深度学习模型执行高度可扩展的分布式训练(图 1)。

1 ImageNet* Inception v1 训练的吞吐量,Cray 使用 BigDL 0.3.0 和双路英特尔® 至强™ 处理器 E5-2620 节点实现。1 吞吐量已接近线性的方式扩展至高达 128 个节点并继续扩展至 256 个节点。

模型量化

量化指的是以更紧凑、低精度的形式存储数字与执行计算的技术。BigDL 利用此类低精度计算量化已有的模型,以优化推理。BigDL 首先加载已有的模型,然后将选定层(如空间卷积)的参数量化为 8 位整数形式,以生成量化模型(图 2)。

在模型推理期间,每个量化层:

  • 32 位浮点输入量化为 8 位整数
  • 使用量化参数和数据执行 8 位计算(如 GEMM
  • 将结果反量化为 32 位浮点

许多运算都可以在实施中融合,量化和反量化亦是如此。

Math.round(1.0 * value

           / Math.max(Math.abs(max), Math.abs(min))           

           * Byte.MaxValue).toByte

2 - 32 位浮点量化为 8 位整数的方程式

不同于许多量化运算,BigDL 采用了全新的本地量化方案,该方案在每个小型本地量化窗口(参数或输入数据的小型子块,如卷积中的补丁或内核)中执行量化和反量化操作。因此,BigDL 可以在模型量化中使用低位整数(如 8 位),将准确性的损失降至最低(低于 0.1%),模型尺寸减少至 1/4,推理速度提升至高达两倍(图 3)。

3 – 使用 BigDL 0.3.0 Amazon Web Services* EC2 C5.18x 大型实例,得到 SSDVGG16 VGG19 模型量化的结果(准确性、推理速度和模型尺寸)2

本地执行

BigDL 不仅是标准的 Spark 程序,还支持在本地 Java* 虚拟机(不包含 Spark)上进行模型训练和推理。这有助于提高在单个节点上运行 BigDL 的效率,因为参数同步或任务调度不会产生开销。更重要的是,更容易使用基于 JVM 的各种大数据框架(如 Apache StormFlink Kafka)直接集成 BigDL 模型(进行推理或微调)。

用例和应用

在本部分,我们将介绍 3 种典型的 BigDL 用例:

1.    模型推理

2.    分布式训练

3.    迁移学习

图像特征提取

京东是世界上最大的在线零售商之一。它在 BigDL Spark 上构建了一个端到端的对象检测和图像特征提取管道(图 4)。该管道首先将数亿张图片从分布式数据库读取至 Spark(作为图片的 RDD,接着使用 Spark 以分布式的方式预处理 RDD(包括调整大小、正规化和批处理)。然后,使用 BigDL 加载 SSD 模型(在 Caffe 中预训练),以便在 Spark 上进行大规模分布式对象检测。这样就生成每张图片中检测对象的坐标和评分。之后生成目标图像(将得分最高的对象保存为目标并基于目标的坐标裁剪原始图片)并进一步预处理目标图像的 RDD(包括调整大小和批处理)。最后,使用 BigDL 加载 DeepBit 模型(在 Caffe 中再次预训练),对目标图像进行分布式特征提取并生成对应的特征。最后将结果(如提取的对象特征的 RDD)存储在 Hadoop 分布式文件系统 (HDFS) 中。

在统一的编程范式下,使用 Spark BigDL 可以轻松实施整个数据分析和深度学习管道(包括数据加载、分区、预处理、模型推理和存储结果)。京东报告显示,相比在 GPU 集群(图 5)上运行相同的解决方案,端到端管道还实现了约 3.83 倍的速度提升。3

4 Spark BigDL 上的端到端对象检测和图像特征提取管道(使用 SSD DeepBit 模型)3

5 GPU 集群和基于英特尔® 至强® 处理器的集群上的图像特征提取管道吞吐量,由京东测试所得3 GPU 吞吐量是在 20 NVIDIA Tesla* K40 显卡上进行测试,而英特尔® 至强® 处理器的吞吐量是在 1,200 个逻辑内核上进行测试(基于双路英特尔® 至强® 处理器 E5-2650 v4 的每台服务器均运行 50 个逻辑内核)。

降水预报

Cray 还将 BigDL 集成至 Urika-XC* 分析软件套件并构建了一个端到端降水预报(预测短期降水)工作流程,包括数据准备、模型训练和推理(图 6)。首先,该应用将超过 1 TB 的原始雷达扫描数据读取至 Spark,作为雷达图像的 RDD,再将其转化为 NumPy* ndarrays RDD。然后训练序列到序列模型,将截至当前时间的一系列图像用作输入,将未来任意时间的一系列预测图像作为输出。训练模型后,它能够预测下一个小时的降水模式等(图 7)。

6 - Spark BigDL 上的端到端降水预报工作流程

7 - 使用 Spark BigDL 预测下一小时的降水模式

基于图像相似性的推荐

MLSListings 公司是一家大型房地产多重上市服务 (MLS) 机构,它们正在 Spark BigDL 上构建基于图像相似性的房屋推荐系统。通过迁移学习(包括特征提取和微调)可以实施端到端的工作流程,以计算房屋照片的语义和视觉相似性(图 8)。为了计算照片的语义相似性,系统对 Places 数据集4上预训练的 Inception v1 模型进行微调,以构建 3 个全新的分类器,确定照片是否显示房屋正面外观、房屋风格和楼层数。

该系统首先加载 3 个预训练 Inception v1 模型,然后将两个新层(一个完全连接层和一个 Softmax* 层)附加到每个模型,以训练新分类器。训练结束后,这些分类器可用于标记每个房屋上市照片。为了计算视觉相似性,系统使用在 Places 数据集上预训练的 VGG-16 模型提取每张房屋上市照片的图像特征。然后将其与分类器生成的标记相结合,并存储为分布式表。在模型服务时间,用户可选择一个房屋上市照片,系统会推荐拥有类似视觉特征的房源(图 9)。

8 – Spark BigDL 上,基于图像相似性,房屋推荐系统的端到端工作流程。

9 - 自动推荐相似的房屋

BigDL 的未来发展趋势如何?

虽然 BigDL 被集成至 Spark,并扩展功能以应对大数据应用开发人员遇到的挑战,但是,单凭库能否简化并加速机器学习/深度学习工作负载在生产集群上的部署呢?基于社区反馈和客户实施,英特尔构建了Analytics Zoo,即端到端分析与人工智能平台,它能通过提供高级管道 API 和包含推理用例的内置深度学习模型,轻松构建 Spark BigDL 应用。

高级管道 API

Analytics Zoo Spark BigDL 上提供了一系列易于使用的高级管道 API,包括:

  • nnframesSpark DataFrames 和机器学习管道中的原生深度学习支持
  • autograd:使用自动微分构建自定义层/损失
  • 迁移学习:面向特征提取或微调自定义预训练模型

通过使用这些高级管道 API ,用户只需编写几行代码,就可以轻松构建复杂的深度学习管道。

第一步:初始化 NNContext 并使用 NNImageReader 将图像加载至 DataFrames

from zoo.common.nncontext import *

from zoo.pipeline.nnframes import *

sc = init_nncontext ()

imageDF = NNImageReader.readImages(image_path, sc)

第二步:使用 DataFrames 转换来处理数据

getName = udf(lambda row: ...)

getLabel = udf(lambda name: ...)

df = imageDF.withColumn(name, getName(col(image))) \       

       .withColumn(label, getLabel(col(name)))

第三步:使用内置特征设计运算处理图像。

from zoo.feature.image import *

transformer = RowToImageFeature() \

              -> ImageResize(64, 64) \

              -> ImageChannelNormalize(123.0, 117.0, 104.0) \

              -> ImageMatToTensor() \

                     -> ImageFeatureToTensor())

第四步:加载已有的模型(在本示例中,在 Caffe 中预训练),删除最后几层并冻结前几层。

from zoo.pipeline.api.net import *

full_model = Net.load_caffe(def_path, model_path)

 

# Remove layers after pool5/drop_7x7_s1

model = full_model.new_graph([pool5/drop_7x7_s1])

 

# freeze layers from input to pool4/3x3_s2 inclusive

model.freeze_up_to([pool4/3x3_s2])

第五步:使用 Keras API 和自定义 Lambda 层添加几个新层。

from zoo.pipeline.api.autograd import *

from zoo.pipeline.api.keras.layers import *

from zoo.pipeline.api.keras.models import *

 

def add_one_func(x):

    return x + 1.0

 

input = Input(name=input, shape=(3, 224, 224))

inception = model.to_keras()(input)

flatten = Flatten()(inception)

lambda = Lambda(function=add_one_func)(flatten)

logits = Dense(2)(lambda)

newModel = Model(input, logits)

第六步:使用 Spark ML 管道来训练模型。

cls = NNClassifier(model, CrossEntropyCriterion(), transformer) \

        .setLearningRate(0.003).setBatchSize(40) \       

               .setMaxEpoch(1).setFeaturesCol(image) \       

               .setCachingSample(False)

nnModel = cls.fit(df)

内置的深度学习模型

Analytics Zoo 提供了几种内置的深度学习模型,适用于各种问题类型,如对象检测、图像分类、文本分类和推荐。

  • 对象检测:使用对象检测 API(包括一组预训练检测模型,如 SSD Faster-RCNN),您可以轻松构建对象检测应用(如在图像和视频中定位与确定多个对象)。
  • 图像分类:使用图像分类 API(包括一组预训练检测模型,如 VGGInceptionResNet MobileNet),您可以轻松构建图像分类应用。
  • 文本分类:文本分类 API 为文本分类应用提供一组预定义模型(如 CNNLSTM)。
  • 推荐:推荐 API 提供一组预定义模型(如神经协同过滤、广泛和深度学习),用于创建推荐引擎。

您可以轻松使用 Analytics Zoo 对象检测 API 对大型图像集进行即时推理。

第一步:从 Detection Model Zoo 中下载 Analytics Zoo 中的对象检测模型,包括一组检测模型(在 PSCAL VOC COCO 数据集上预训练)。

第二步:加载图像数据和对象检测模型。

from zoo.common.nncontext import get_nncontext

from zoo.models.image.objectdetection import *

 

spark = init_nncontext()

image_set = ImageSet.read(img_path, spark)

第三步:使用对象检测 API实现即时推理和可视化

output = model.predict_image_set(image_set)

 

visualizer = Visualizer(model.get_config().label_map(), \

                        encoding=jpg)

visualized = visualizer(output).get_image(to_chw=False) \                              

                               .collect()

 

for img_id in range(len(visualized)):   

    cv2.imwrite(output_path + / + str(img_id) + .jpg, \

                     visualized[img_id])

BigDL 的最大特点

BigDL 正在实施中,但是最初的体验和反馈令人振奋。自 2016 12 月发布初始版本以来,BigDL GitHub* 上获得了超过 2,400 颗星,并支持大量用户在 Hadoop / Spark 集群上构建全新的分析和深度学习应用。全新的 Analytics Zoo 项目通过在 Apache Spark BigDL 上提供端到端的分析和人工智能平台,以进一步简化 BigDL 应用的构建。

 #DataScience

参考资料

1.Alex Heye 等。《在 Urika-XC 软件套件中使用 BigDL 实现可扩展的深度学习

2.Jason (Jinquan) Dai 等。《使用 Amazon EC2 C5 实例和 BigDL 充分利用面向深度学习的低精度和量化

3.Jason (Jinquan) Dai 等。《解析京东大数据下高效图像特征提取方案

4.B. Zhou 等。《Places面向场景识别的数据库(包含 1,000 万张图像)》,《IEEE Transactions on Pattern Analysis and Machine Intelligence(TPAMI)2017 年。