Spark新愿景:让深度学习变得更加易于使用——见https://github.com/yahoo/TensorFlowOnSpark
Spark新愿景:让深度学习变得更加易于使用
前言
Spark成功的实现了当年的承诺,让数据处理变得更容易,现在,雄心勃勃的Databricks公司展开了一个新的愿景:让深度学习变得更容易。 当然牛好吹,也是要做些实际行动的,所有便有了spark-deep-learning项目。这件事情已经有很多人尝试做了,但显然太浅了,DB公司则做的更深入些。
原理
要做深度学习,肯定不能离开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 提出了三个新的东西:
- 首先是,Spark的数据终于可以用DF的方式无缝的喂给Tensorflow/Keras了,而且对Tensorflow/Keras的适配了一套Mllib的库,方便以Spark Mllib的方式进行编程。当然,为了使得原先是Tensorflow/Keras的用户感觉爽,如果你使用Python API你也可以完全使用Keras/Tensorflow 的Style来完成代码的编写。
- 其次是多个TF模型同时训练,给的一样的数据,但是不同的参数,从而充分利用分布式并行计算来选择最好的模型。
- 另外是模型训练好后如何集成到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里的,所以也是分布式的。
如何开发
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
这样代码提示的问题就被解决了。
Spark新愿景:让深度学习变得更加易于使用——见https://github.com/yahoo/TensorFlowOnSpark的更多相关文章
- 用Apache Spark和TensorFlow进行的深度学习
原文:https://databricks.com/blog/2016/01/25/deep-learning-with-apache-spark-and-tensorflow.html by Tim ...
- 微软的深度学习框架cntk ,我目前见过 安装方式最简单的一个框架,2.0之后开始支持C# 咯
wiki:https://github.com/Microsoft/CNTK/wiki 嗨,你也是我这种手残党么?之前试着安装着mxnet和tensorflow,但是因为时间比较短所以往往来不及安装完 ...
- [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark
[源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 目录 [源码解析] 深度学习分布式训练框架 horovod (8) --- on spark 0x00 摘要 0 ...
- [源码解析] 深度学习分布式训练框架 Horovod (1) --- 基础知识
[源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 目录 [源码解析] 深度学习分布式训练框架 Horovod --- (1) 基础知识 0x00 摘要 0x01 分布式并 ...
- [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入
[源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 目录 [源码解析] 深度学习分布式训练框架 horovod (2) --- 从使用者角度切入 0x00 摘要 0 ...
- [源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架
[源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架 目录 [源码解析] 深度学习分布式训练框架 horovod (5) --- 融合框架 0x00 摘要 0x01 架构图 ...
- [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构
[源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 目录 [源码解析] 深度学习分布式训练框架 horovod (6) --- 后台线程架构 0x00 摘要 0x01 ...
- 一个基于深度学习回环检测模块的简单双目 SLAM 系统
转载请注明出处,谢谢 原创作者:Mingrui 原创链接:https://www.cnblogs.com/MingruiYu/p/12634631.html 写在前面 最近在搞本科毕设,关于基于深度学 ...
- 开源项目(9-0)综述--基于深度学习的目标跟踪sort与deep-sort
基于深度学习的目标跟踪sort与deep-sort https://github.com/Ewenwan/MVision/tree/master/3D_Object_Detection/Object_ ...
随机推荐
- 前端HTML中float学习笔记
float元素原本的作用是用来使文字包裹图片,现在人们更多的是用来进行布局(ps:有没有点滥用的意思) 也就是说本来你排好的界面设计,但是因为浮动会导致元素脱离文档流,使得其他非浮动的块级元素会无视这 ...
- Android Fragment间的广播消息接收
这种方式不用在配置文件加东西,我比较喜欢. 广播注册,可以写在Activity(onCreate),也可以写在Fragment(onActivityCreated)里. LocalBroadcastM ...
- github添加公钥出现 github ssh key Key is invalid. Ensure you've copied the file correctly的解决办法
因为在公钥查看的时候可能是利用了vim明明查看,所以会有换行,导致这个错误,解决方法是用cat命令查看文件,或者其他方式查看,总之公钥不能有换行.
- tomcat映射java目录 sever.xml
<Valve className="org.apache.catalina.authenticator.SingleSignOn" /> --> & ...
- AndroidStudio 内存泄漏的分析过程
前言部分这次泄漏是自己代码写的太随意引起的,讲道理,代码写的太为所欲为了,导致有些问题根本就很难发现. 泄漏产生的原因,由于activity未被回收导致.这里给我们提出的一个警示,在使用上下文的时候, ...
- 02-Linux命令基础-第02天(压缩包管理、服务器搭建与使用、vim)
01- 复习 /boot 目录 引导项 八种文件类型: 文件:- 目录:d 软链接:l 字符设备文件:c 块设备文件:b 管道:p 套接字:s 未知 cp –a 保持源文件属性(如时间属性 如果不 ...
- QBXT Day2
遭遇[问题描述]你是能看到第一题的 friends呢.—— hjaN座楼房,立于城中 .第i座楼,高度 hi.你需要一开始选择座楼,开始跳楼. 在第 i座楼准备跳需要 ci的花费. 每次可以跳到任何一 ...
- node源码详解(四)
本作品采用知识共享署名 4.0 国际许可协议进行许可.转载保留声明头部与原文链接https://luzeshu.com/blog/nodesource4 本博客同步在https://cnodejs.o ...
- Java基础学习总结(66)——配置管理库typesafe.config教程
Typesafe的Config库,纯Java写成.零外部依赖.代码精简.功能灵活.API友好.支持Java properties.JSON.JSON超集格式HOCON以及环境变量.它也是Akka的配置 ...
- ACdream 1735 输油管道
输油管道 Time Limit: 2000/1000MS (Java/Others) Memory Limit: 262144/131072KB (Java/Others) Problem Des ...