分享

在PySpark中定制机器学习算法

本帖最后由 sehriff 于 2017-10-3 11:46 编辑
问题导读
1.机器学习算法可以分成哪些类型?
2.为什么python适合机器学习?
3.什么是PySpark,MLlib?


在PySpark(Apache Spark的 Python API)开发定制的机器学习算法难度高且工作量大。在本博客中,我们讲述改进PySpark API以简化定制算法开发流程改进而做的工作。 我们的关键改进把上百行用于持久化(保存和加载模型)的样板代码缩减到一行。这个特性会在下个Apache Spark发行版提供。

背景:PySpark的 开发者API
在最近几年,Python变成数据科学领域最流行的语言,超过百万的开发者对上千的开源机器学习项目贡献自己代码。虽然Python大行其道,Apache Spark MLlib 的开发者API 还是以Scala主导,所有算法都是用Scala 实现然后再对其封装来支持。这样做的结果就是数据科学家用Python 开发机器学习算法的同时也要写点Scala 代码。
本博客介绍PySpark 的一些改进点,有助于使开发定制机器学习算法和第三方机器学习包变得容易。介绍完MLlib的主要算法API后,我们讨论下当前在PySpark上构建传统定制机器学习算法遇到的挑战。再然后我们讨论PySpark的关键改进点,比如简化定制化流程。

MLlib 算法APIs
在讨论PySpark的改变前,了解Spark中机器学习主要API是有益的。算法主要分成两类主要类型:转换器和评估器
转换器是接收输入并通过 transform()方法来修改输入并产生输出数据集的算法。例如Binarizer 算法从数据集读取特征值数据列并输出带新的数据列(值为0或1,根据原始值的阀值)的数据集。
评估器机器学习算法利用训练数据集使用fit()方法训练机器学习模型并输出该模型。模型本身是个转换器,调用transform()方法将会在数据集中增加一列预测值。 常见例子有 逻辑回归随机森林
通常一个数据分析流程包含了多个转换器和评估器。机器学习管道(ML Pipelines)提供了链式算法的API,将上个算法的输出饲喂给下个算法。更多细节请查看链接 Databricks docs
以下,我们展示了一个简单的管道,包含2个特征转换器 (Tokenizer, HashingTF)和一个评估器 (LogisticRegression),该例子来自 MLlib guide on Pipelines
ml-Pipeline.png

困境:机器学习持久化
数据科学家想来引入他们自己的转换器和评估器来扩展PySpark.首先,他们用Python写了一个类继承转换器或评估器然后实现对应的transform() 或 fit()方法.在简单场景下,方法的实现是很直接的.例如,很多转换器使用用户自定义函数通过给输入的DataFrame加入新列来实现.
然而,MLlib一个至关重要的功能确是机器学习持久化.利用持久化,用户可以永久保存模型和管道,用于加载和复用或传递给别的团队使用.  API很简单; 以下代码片段使用CrossValidator来训练模型用于参数调优,保存训练后模型并重新加载进来:
[mw_shl_code=applescript,true]val cvModel = cv.fit(training)cvModel.save("myCVModelPath")val sameCVModel = CrossValidatorModel.load("myCVModelPath")[/mw_shl_code]
机器学习持久化以JSON 元数据 + Parquet格式保存模型和管道,并可以供不同Spark集群及团队用于转化模型和管道.更对关于持久化的资料,参考 blog postwebinar
传统是先用Scala 实现机器学习持久化. 直到今天,最简单的持久化实现方式需要数据科学家用Scala实现算法并用Python封装.在Scala中实现算法需要了解这两种语言,了解Java—Python交互接口并使用两种语言写一样的API.

结论:Python持久化混用
为了支持只有Python实现的机器学习算法,我们在PySpark API用实现与Scala API同名的持久化框架.有了这个框架,用Python实现定制的转换器或评估器时就无需用Scala实现对应的算法,而是使用带转换器或评估器的混合类来实现持久化.
对于所有参数都是可以JSON序列化(简单类型,如 string, float)的简单算法,算法的类可以继承DefaultParamsReadable和DefaultParamsWritable类 (SPARK-21542; code on Github) 来实现自动持久化. (如果你对机器学习管道的Param不熟悉,他们是标准化的指定算法参数或属性的方式.参考MLlib向导的Param部分获取更多信息)默认持久化的实现可以在PySpark保存并重新加载定制算法.
这些混合类在PySpark顶层显著减少了开发定制机器学习算法的工作量.之前在多个场景需要额外代码才能实现的持久化现在只要一行代码就可以搞定.
以下的代码片段展示了使用Scala实现和Python包装器持久化一个算法的代码长度:
before.png

这个代码片段展示了使用混合类用于实现仅Python支持的持久化:
[mw_shl_code=applescript,true]class MyShiftTransformer(UnaryTransformer, DefaultParamsReadable, DefaultParamsWritable):[/mw_shl_code]
将DefaultParamsReadable类和DefaultParamsWritable类加到MyShiftTransformer类可以少些许多代码.
对于参数或数据无法JSON序列化(复杂类型,如DataFrame)的复杂算法,开发者可以用Python写个定制的 save()和load()方法.之前,即使实现了 save()和load()方法,定制的Python实现也不能保存在机器学习管道中.我们的补丁 (SPARK-17025)解决了这个问题,使得集成定制Python的MLlib算法更顺滑.

Looking forward未来
有了这些实现,开发者将可以用Python写定制化的机器学习算法,在管道中使用,保存和加载这些算法而不用写Scala代码.我们相信这个会降低开发者使用门槛并鼓励更多开发者贡献仅以Python为中心的Spark包

已有(1)人评论

跳转到指定楼层
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条