Spark新愿景:让深度学习变得更加易于使用

01 前 言

Spark成功的实现了当年的承诺,让数据处理变得更容易,现在,雄心勃勃的Databricks公司展开了一个新的愿景:让深度学习变得更容易。 当然牛好吹,也是要做些实际行动的,所有便有了spark-deep-learning(https://github.com/databricks/spark-deep-learning)项目。这件事情已经有很多人尝试做了,但显然太浅了,DB公司则做的更深入些。

02

原 理

要做深度学习,肯定不能离开TensorFlow, MXNet之类的。 spark-deep-learning也是如此,尝试和Tensorflow进行整合。那么如何进行整合呢? 我们知道Tensorflow其实是C++开发的,平时训练啥的我们主要使用python API。Spark要和TensorFlow 进行整合,那么有三种方式:

  • 走Tensorflow的Java API
  • 走Tensorflow的Python API
  • 通过JNI直接走Tensorflow的C++ API

因为Spark自己也可以使用Python,虽然有性能的上的损耗(据说>30%),但是终究是能跑起来。实际上Spark采用了2和3的结合。 第二条容易理解,第三条则主要依赖于另外一个项目tensorframes。这个项目主要是实现tensorflow和spark的互相调用。简单的来说,在spark的dataframe运算可以通过JNI调用tensorflow来完成,反之Spark的dataframe也可以直接喂给tensorflow(也就是tensorflow可以直接输入dataframe了)。有了这个之后,spark-deep-learning 则无需太多关注如何进行两个系统完成交互的功能,而是专注于完成对算法的集成了。

为了给出一个直观的感受,我们看个示例代码(来源于官方):

import tensorflow as tf import tensorframes as tfs from pyspark.sql import Row data = [Row(x=float(x)) for x in range(10)] df = sqlContext.createDataFrame(data) with tf.Graph().as_default() as g: # The TensorFlow placeholder that corresponds to column 'x'. # The shape of the placeholder is automatically inferred from the DataFrame. x = tfs.block(df, "x") # The output that adds 3 to x z = tf.add(x, 3, name='z') # The resulting dataframe df2 = tfs.map_blocks(z, df) # The transform is lazy as for most DataFrame operations. This will trigger it: df2.collect()

在这里,通过tensorframes 我可以对spark dataframe里列使用tensorflow来进行处理。

x = tfs.block(df, "x")

相当于

x = tf.placeholder(shape=..., dtype=..., name='x')

程序自动从df可以知道数据类型。

df2 = tfs.map_blocks(z, df)

则相当于将df 作为tf的feed_dict数据。最终f2.collect 触发实际的计算。

spark-deep-learning 提出了三个新的东西:

1、首先是,Spark的数据终于可以用DF的方式无缝的喂给Tensorflow/Keras了,而且对Tensorflow/Keras的适配了一套Mllib的库,方便以Spark Mllib的方式进行编程。当然,为了使得原先是Tensorflow/Keras的用户感觉爽,如果你使用Python API你也可以完全使用Keras/Tensorflow 的Style来完成代码的编写。

2、其次是多个TF模型同时训练,给的一样的数据,但是不同的参数,从而充分利用分布式并行计算来选择最好的模型。

3、另外是模型训练好后如何集成到Spark里进行使用呢?没错,SQL UDF函数,你可以很方便的把一个训练好的模型注册成UDF函数,从而实际完成了模型的部署。

方便理解,我们也简单看看一些代码:

from pyspark.ml.classification import LogisticRegression from pyspark.ml.evaluation import MulticlassClassificationEvaluator from pyspark.ml import Pipeline from sparkdl import DeepImageFeaturizer from sparkdl import readImages from pyspark.sql.functions import lit //读取图片,设置为1分类 tulips_df = readImages(img_dir + "/tulips").withColumn("label", lit(1)) //读取图片,设置为2分类 daisy_df = readImages(img_dir + "/daisy").withColumn("label", lit(0)) //构成训练集 train_df = tulips_train.unionAll(daisy_train) //使用已经配置好的模型(InceptionV3) featurizer = DeepImageFeaturizer(inputCol="image", outputCol="features", modelName="InceptionV3") //接一个分类器,也就是传说中的迁移学习 lr = LogisticRegression(maxIter=20, regParam=0.05, elasticNetParam=0.3, labelCol="label") //组装下 p = Pipeline(stages=[featurizer, lr]) //训练,和Mllib保持了一致 model = p.fit(image_df) # train_images_df is a dataset of images (SpImage) and labels //预测 df = model.transform(train_df.limit(10)).select("image", "probability", "uri", "label") predictionAndLabels = df.select("prediction", "label")

整个模型一气呵成。

对于上面的例子比较特殊,DeepImageFeaturizer那块其实因为是使用别人已经训练好的参数,所以本身是分布式的,直接透过tensorrames 调用tensorflow把输入的图片转换为经过InceptionV3处理后的向量,然后到了LogisticRegression,因为这个算法本身是Mllib里的,所以也是分布式的。

03

如何开发

spark-deep-learning 还处于早期,很多东西还不太完善。

为了方便看源码以及编写实际的代码,你可以clone最新的代码,然后使用intellij idea 可以很方便的导入进来。导入进来后,添加python framework的支持,然后把根目录下的python目录作为source 目录,接着进入project structured 添加pyspark 的zip(一般放在spark home 里的lib目录),这样你在spark-deep-learning里就可以直接做开发了。

spark-deep-learning使用的是spark 2.1.1 以及python 2.7 ,不过我的环境是spark 2.2.0, python 3.6。 所以你需要在build.sbt里第一行修改为

val sparkVer = sys.props.getOrElse("spark.version", "2.2.0")

同时保证你的python为2.7版本(你可以通过一些python的管理工具来完成版本的切换),然后进行编译:

build/sbt assembly

编译的过程中会跑单元测试,在spark 2.2.0会报错,原因是udf函数不能包含“-”,所以你找到对应的几个测试用例,修改里面的udf函数名称即可。

编译好后,你就可以直接写个脚本,比如:

import os from pyspark import * from sparkdl import readImages os.environ['PYSPARK_PYTHON'] = '/Users/allwefantasy/python2.7/tensorflow/bin/python' sc = SparkContext.getOrCreate() image_df = readImages("/Users/allwefantasy/resources/images/flower_photos/daisy/") image_df.show()

比如我这里简单的读取图片文件,并且显示出来。你可以直接点击右键运行,也可以通过spark-submit运行:

./bin/spark-submit --driver-memory 8g --py-files spark-deep-learning-assembly-0.1.0-spark2.2.jar \ --jars spark-deep-learning-assembly-0.1.0-spark2.2.jar \ --master local[*] spark-deep-learning/python/tests/Test.py

因为比较消耗内存,这里可以通过driver-memory 设置spark submit 内存。

如果你导入项目,想看python相关的源码,但是会提示找不到pyspark相关的库,你可以使用:

pip install pyspark》

这样代码提示的问题就被解决了。

原文发布于微信公众号 - 人工智能LeadAI(atleadai)

原文发表时间:2017-09-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏专知

Tensorflow Eager Execution入门指南

本文介绍了最新版的Tensorflow 1.7的功能及其使用方法,重点介绍其中最有趣的功能之一eager_execution,它许用户在不创建静态图的情况下运行...

53712
来自专栏简书专栏

基于xgboost的波士顿房价预测kaggle实战

2018年8月24日笔记 这是作者在波士顿房价预测项目的第3篇文章,在查看此篇文章之前,请确保已经阅读前2篇文章。 第2篇文章链接:https://www....

1.5K3
来自专栏祝威廉

MLSQL如何支持部署SKLearn,Tensorflow,MLLib模型提供API预测服务

部署成API服务时,除了要把raw数据特征化成向量外,研发还要想着怎么加载模型,产生模型的框架五花八门,比如Tensorflow,SKlearn,Spark M...

1204
来自专栏磐创AI技术团队的专栏

Tensorboard 详解(上篇)

2163
来自专栏梦里茶室

毫秒级检测!你见过带GPU的树莓派吗?

树莓派3B+英特尔神经计算棒进行高速目标检测 转载请注明作者梦里茶 ? 代码: 训练数据预处理: https://gist.github.com/ahan...

4.2K8
来自专栏ATYUN订阅号

自定义对象检测问题:使用TensorFlow追踪星球大战中的千年隼号宇宙飞船

大多数的大型科技公司(如IBM,谷歌,微软,亚马逊)都有易于使用的视觉识别API。一些规模较小的公司也提供类似的产品,如Clarifai。但没有公司能够提供对象...

4595
来自专栏人工智能LeadAI

毫秒级检测!你见过带GPU加速的树莓派吗?

75810
来自专栏河湾欢儿的专栏

05-图片优化合并

遵循的原则: 把同属于一个模块的图片进行合并 把大小相近的图片进行合并 把色彩相近的图片进行合并 综合以上凡是合并

1212
来自专栏实用工具入门教程

如何部署 TensorFlow 服务器

TensorFlow是一款由Google构建的用于训练神经网络的开源机器学习软件。TensorFlow的神经网络以有状态数据流图的形式表示。图中的每个节点表示神...

5233
来自专栏专知

【最新TensorFlow1.4.0教程01】TF1.4.0介绍与动态图机制 Eager Execution使用

【导读】主题链路知识是我们专知的核心功能之一,为用户提供AI领域系统性的知识学习服务,一站式学习人工智能的知识,包含人工智能( 机器学习、自然语言处理、计算机视...

3868

扫码关注云+社区

领取腾讯云代金券