如何在 Spark 机器学习中应用 scikit-learn?
程序员文章站
2022-04-30 14:10:05
...
最近在写spark下的机器学习程序,用RDD编程模型。spark自带的机器学习算法API局限太多。想请问各路大侠,能不能再spark的编程模型下引用scikit-learn?
我们知道scikit-learn运算中最核心的数据结构存储主要是numpy ndarray,而Spark运算中最核心的存储是RDD,说白了就是一个基于有向无环图的MapReduce,图的目的就是减少Map和Reduce之间传递的数据,所以非常适合反复迭代的机器学习场景。PySpark可以提供很好用的API来计算map、reduce、join、filter等函数式运算,但没法处理numpy ndarray这种local存储。
所以就是要想办法将狼(distributed的RDD)披上羊(local的ndarray)的皮(变成ndarrayRDD),混入羊群(scikit-learn)就能吃上肉了。简单地说,就是用RDD的键值对(key-value pairs)来表示多维数组的不同部分,并从中记录着变换后的子数组的形状及其计算时发生的各种变化。比如说吧,我们设定一个数组可以用其axes的子集作为键,因此一个标出横轴和纵轴(axis=(0,1))的五维数组就可以表示成key-value pairs,其中keys是二元组,values是三维数组,这就算做成了一个ndarrayRDD。然后ndarrayRDD不断地转置、变形,从而实现不断并行化的过程。这当中我们可以用Python中的map、filter、reduce等函数式运算,再加上Spark中的cache、unpersist等方法控制RDD的缓存,也就没浪费Spark的快速特点,同时也发挥了Python和scikit-learn的优势。
我就这样大致这么一说,更具体的理解还要有赖于直接阅读源码。是的,其实这方面的尝试早就有人做了,而且有的开发得已经相当不错了呢。
GitHub - bolt-project/bolt: Unified interface for local and distributed ndarrays
推荐!这是我最早看到的关于多维数组的单机和分布式之间的转换方法,其设计思路的关键在于一个叫swap的方法,也就是我上面提到的ndarrayRDD的key-value pairs不断变换,把value axes挪到key axes,value axes可以分开挪到key axes等等,split就越来越多,自然就越来越并行化。
GitHub - thunder-project/thunder: scalable analysis of images and time series
thunder是一个可以处理以图像为主的海量数据的包,其中用到分布式的部分就是引用了上面所说的bolt.spark。
GitHub - lensacom/sparkit-learn: PySpark + Scikit-learn = Sparkit-learn
这个splearn是我觉得目前很有前途的一个包,因为它提供了三种分布式的数据结构:arrayRDD、sparseRDD、dictRDD,同时也相应地改写了scikit-learn,以适用于变换过的RDD。
GitHub - databricks/spark-sklearn: Scikit-learn integration package for Spark
最后说一下databricks亲自开发的这个Spark-sklearn。开发得还不够充分,功能还非常有限,只能是在数据集in memory的前提下,用网格搜寻对参数做交叉验证(也就是用到scikit-learn里面的GridSearchCV)的时候实现并行,而不能像MLlib那样对每个学习算法实现并行;当内存架不住很大的数据集的时候,还得上Spark MLlib。o(︶︿︶)o 泻药!简单的回答是:不能。
spark的核心是RDD,是一个DAG版的map reduce,机器学习算法的单机和并行化版本的实现是完全不同的,sklearn作为单机的算法库是不能简单的移植到spark上的
2016.2.10 updated:
在github上发现了一个项目GitHub - databricks/spark-sklearn: Scikit-learn integration package for Spark,目的是为了无缝的把sklearn和spark集成,不过现在看上去功能还比较简单 家里的不规则自留地就别指望用生产队的康麦因收割了 顶多是提供和scikit一样的API,但是内部实现是完全不一样的,底层的数据结构就不同,上层的算法逻辑也不同,还怎么移植? 有那么爽就好了 没有用过scikit这个包,不过很同意你所说的spark api限制多这个结论。很多我们习惯使用的参数或者用法在spark里都不好使了。但是我对于spark mllib的理解是他的算法是basic的,但是其中的散列化和网络吞吐量的考虑是亮点,很棒的亮点。如果有时间和精力,完全可以去把基础算法改进至你想要的模式。上次scikit照理说应该在pyspark下引进去,但是能否实现分布式效率得看scikit实现方法了。浅见,希望有用
回复内容:
和以上几个观点不同,我认为在PySpark下引用scikit-learn可能的,但不能直接简单粗暴地移植,而是要相应地对各自环境下的数据结构做一些转换。我们知道scikit-learn运算中最核心的数据结构存储主要是numpy ndarray,而Spark运算中最核心的存储是RDD,说白了就是一个基于有向无环图的MapReduce,图的目的就是减少Map和Reduce之间传递的数据,所以非常适合反复迭代的机器学习场景。PySpark可以提供很好用的API来计算map、reduce、join、filter等函数式运算,但没法处理numpy ndarray这种local存储。
所以就是要想办法将狼(distributed的RDD)披上羊(local的ndarray)的皮(变成ndarrayRDD),混入羊群(scikit-learn)就能吃上肉了。简单地说,就是用RDD的键值对(key-value pairs)来表示多维数组的不同部分,并从中记录着变换后的子数组的形状及其计算时发生的各种变化。比如说吧,我们设定一个数组可以用其axes的子集作为键,因此一个标出横轴和纵轴(axis=(0,1))的五维数组就可以表示成key-value pairs,其中keys是二元组,values是三维数组,这就算做成了一个ndarrayRDD。然后ndarrayRDD不断地转置、变形,从而实现不断并行化的过程。这当中我们可以用Python中的map、filter、reduce等函数式运算,再加上Spark中的cache、unpersist等方法控制RDD的缓存,也就没浪费Spark的快速特点,同时也发挥了Python和scikit-learn的优势。
我就这样大致这么一说,更具体的理解还要有赖于直接阅读源码。是的,其实这方面的尝试早就有人做了,而且有的开发得已经相当不错了呢。
GitHub - bolt-project/bolt: Unified interface for local and distributed ndarrays
推荐!这是我最早看到的关于多维数组的单机和分布式之间的转换方法,其设计思路的关键在于一个叫swap的方法,也就是我上面提到的ndarrayRDD的key-value pairs不断变换,把value axes挪到key axes,value axes可以分开挪到key axes等等,split就越来越多,自然就越来越并行化。
GitHub - thunder-project/thunder: scalable analysis of images and time series
thunder是一个可以处理以图像为主的海量数据的包,其中用到分布式的部分就是引用了上面所说的bolt.spark。
GitHub - lensacom/sparkit-learn: PySpark + Scikit-learn = Sparkit-learn
这个splearn是我觉得目前很有前途的一个包,因为它提供了三种分布式的数据结构:arrayRDD、sparseRDD、dictRDD,同时也相应地改写了scikit-learn,以适用于变换过的RDD。
GitHub - databricks/spark-sklearn: Scikit-learn integration package for Spark
最后说一下databricks亲自开发的这个Spark-sklearn。开发得还不够充分,功能还非常有限,只能是在数据集in memory的前提下,用网格搜寻对参数做交叉验证(也就是用到scikit-learn里面的GridSearchCV)的时候实现并行,而不能像MLlib那样对每个学习算法实现并行;当内存架不住很大的数据集的时候,还得上Spark MLlib。o(︶︿︶)o 泻药!简单的回答是:不能。
spark的核心是RDD,是一个DAG版的map reduce,机器学习算法的单机和并行化版本的实现是完全不同的,sklearn作为单机的算法库是不能简单的移植到spark上的
2016.2.10 updated:
在github上发现了一个项目GitHub - databricks/spark-sklearn: Scikit-learn integration package for Spark,目的是为了无缝的把sklearn和spark集成,不过现在看上去功能还比较简单 家里的不规则自留地就别指望用生产队的康麦因收割了 顶多是提供和scikit一样的API,但是内部实现是完全不一样的,底层的数据结构就不同,上层的算法逻辑也不同,还怎么移植? 有那么爽就好了 没有用过scikit这个包,不过很同意你所说的spark api限制多这个结论。很多我们习惯使用的参数或者用法在spark里都不好使了。但是我对于spark mllib的理解是他的算法是basic的,但是其中的散列化和网络吞吐量的考虑是亮点,很棒的亮点。如果有时间和精力,完全可以去把基础算法改进至你想要的模式。上次scikit照理说应该在pyspark下引进去,但是能否实现分布式效率得看scikit实现方法了。浅见,希望有用
下一篇: 对numpy中布尔型数组的处理方法