本博客为作者原创,如需转载请注明参考
 
        在深入理解Spark ML中的各类算法之前,先理一下整个库的设计框架,是非常有必要的,优秀的框架是对复杂问题的抽象和解剖,对这种抽象的学习本身,就是加深框架所面对的问题的理解的一种有效途径。纷繁复杂的机器学习问题,经过优秀框架的解析,变得简单清晰起来。
        基于面向对象语言的程序设计,本质上类似于搭积木,从一个最抽象、最简单的内容开始,一点一点的往上堆叠,形成一个对象的框架。比如Java中的Object,Python中的PyObject等等,这也是面向对象语言教给我们的一种解决问题的思路:剥洋葱,把外层非本质的核一个一个剥去,剩下的就是事物的本质与核心。
        那么,机器学习问题的核心是什么呢?Spark ML给出的答案是,参数。所有的机器学习模型、算法,说到底都是对参数的学习,都离不开参数。因此,在Spark ML框架中,最底层也是最抽象的类,就是Param,一个对象只要是能包含参数的,都可以叫做Param。
        在param文件夹下,包含了对参数类及其子类的代码。参数类的子类,主要分成两种,第一种是数据类型类,包括IntParam,DoubleParam,顾名思义,这些参数包含了某种数据类型的数据,第二种是参数集合Params,表示其中包含了许多参数,这个类就很了不起了,从它开始衍生出了很多实用的参数,比如HasRegParam,表示其中包含了正则化的参数,再比如HasMaxIter,表示其中包含了最大迭代次数的参数。看,机器学习模型的积木已经帮我们准备好了,从参数的角度来抽象各类机器学习问题,可以按照是否包含某个参数,对机器学习模型和算法进行拆解,一个算法需要什么参数,就在定义时,像搭积木一样,把对应的参数包括进来就好了。
        参数仅是静态的内容,如果要让这个对象有用,就需要让它具有一定的功能。最底层的具有功能性的类时PipelineStage,它实际上是一个Params,关于Pipeline的概念,我们稍后介绍,这里需要理解的是,虽然PipelineStage与Pipeline的名称很相似,但它们之间还隔了一层,完全不是一个层面上的东西。PipelineStage是一个抽象的阶段,它本身不具备任何功能,它的存在仅是为了给真正有功能的类一个公共的子类,与Param的其它子类相区分。
        接下来就到了我们日常使用时最常用的类,Transformer。一个类,只要它拥有将一个数据集转化成另外一个数据集的功能,它就是一个Transformer。注意,一个Transformer就是一个PipelineStage。
仅能完成数据转换,还不够,在机器学习中,最重要的事情是对数据的拟合,这里Estimator类正式登场,只要具有数据拟合的功能,即,只要能从数据中学习,就是Estimator,这个类里包含了我们最熟悉的一个函数,fit,是它赋予了所有Estimator从数据中学习的能力。
        到这里,我们在机器学习中最常见的“模型”的概念,就已经呼之欲出了。Model类本质上是一个Transformer,这个很好理解,一个训练得到的模型,本身的任务就是做预测,做数据转化的。Model的独特之处在于,它是由Estimator的fit方法生成的,一个Estimator在经过对数据的学习之后,就产生了一个Model,而一个Model中除了一个指向生成自己的Estimator的指针之外,真的什么都没有。
        这里我们再总结一下Transformer(简称T),Estimator(简称E),Model(简称M)三者之间的关系。T和E本质上都是PipelineStage,更本质的来说都是Param,而M本质上是一个T,但它是由E产生的,因此M是连接T和E之间的桥梁。
        下面要介绍的就是Pipeline,我们知道很多机器学习的任务,都不是一步能完成的,比如做分类,我们要先对数据进行预处理,进行分类,然后再对分类结果进行处理,才能得到想要的结果。于是Spark ML提供了一个非常棒的抽象,流水线(Pipeline),它的引入能使得机器学习的各个任务能像流水线一样被顺序执行,因此能提供非常简洁的编程接口。Pipeline本质上是一个E,它是由一个一个的PipelineStage组成的。通过上文我们知道,T和E都是PipelineStage,因此一个Pipeline中就包含了许多的T和E。由于Pipeline本质上是一个E,因此它在调用fit函数之后,会产生一个PipelineModel,这就是一个Model了。还记得Model的本质是Transformer吗?
        我们知道,机器学习中的问题可以简单分为两类,监督学习和非监督学习,监督学习的一个特点就是,能够对某个事情做出“预测”,而非监督学习更多的是挖掘数据中的一些内在本质特点,不能做出预测,因此,为了将监督学习的本质提炼出来,设计了一个Predictor类。
        能做出预测的类,需要有一些共同的参数,还记得刚才我们对于Param的分析吗?参数是区分各类机器学习算法的一种角度,PredictorParams就是有预测能力的监督学习模型拥有参数的一种抽象,而Predictor本质上是一个带有PredictorParams的Estimator,而每一个Estimator在调用fit函数之后都会产生一个Model,这里产生的就是一个PredictorModel,这是一个带有PredictorParams的Model。
       
        好了,今天就写到这里。写作也是整理思路的一种很好的方式,在刚才的写作中,对Spark ML的设计思路又有了新的认识。由于本人才疏学浅,以上的理解不免会有纰漏,还请大家不吝赐教。下次将跟大家一起分析下具体算法的设计。

Spark ML源码分析之一 设计框架解读的更多相关文章

  1. Spark ML源码分析之二 从单机到分布式

            前一节从宏观角度给大家介绍了Spark ML的设计框架(链接:http://www.cnblogs.com/jicanghai/p/8570805.html),本节我们将介绍,Spar ...

  2. Spark ML源码分析之三 分类器

            前面跟大家扯了这么多废话,终于到具体的机器学习模型了.大部分机器学习的教程,总要从监督学习开始讲起,而监督学习的众多算法当中,又以分类算法最为基础,原因在于分类问题非常的单纯直接,几乎 ...

  3. Spark ML源码分析之四 树

            之前我们讲过,在Spark ML中所有的机器学习模型都是以参数作为划分的,树相关的参数定义在treeParams.scala这个文件中,这里构建一个关于树的体系结构.首先,以Decis ...

  4. 第十一篇:Spark SQL 源码分析之 External DataSource外部数据源

    上周Spark1.2刚发布,周末在家没事,把这个特性给了解一下,顺便分析下源码,看一看这个特性是如何设计及实现的. /** Spark SQL源码分析系列文章*/ (Ps: External Data ...

  5. 【Spark SQL 源码分析系列文章】

    从决定写Spark SQL源码分析的文章,到现在一个月的时间里,陆陆续续差不多快完成了,这里也做一个整合和索引,方便大家阅读,这里给出阅读顺序 :) 第一篇 Spark SQL源码分析之核心流程 第二 ...

  6. Spring5源码分析(1)设计思想与结构

    1 源码地址(带有中文注解)git@github.com:yakax/spring-framework-5.0.2.RELEASE--.git Spring 的设计初衷其实就是为了简化我们的开发 基于 ...

  7. [转]Libev源码分析 -- 整体设计

    Libev源码分析 -- 整体设计 libev是Marc Lehmann用C写的高性能事件循环库.通过libev,可以灵活地把各种事件组织管理起来,如:时钟.io.信号等.libev在业界内也是广受好 ...

  8. 第十篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 query

    /** Spark SQL源码分析系列文章*/ 前面讲到了Spark SQL In-Memory Columnar Storage的存储结构是基于列存储的. 那么基于以上存储结构,我们查询cache在 ...

  9. 第九篇:Spark SQL 源码分析之 In-Memory Columnar Storage源码分析之 cache table

    /** Spark SQL源码分析系列文章*/ Spark SQL 可以将数据缓存到内存中,我们可以见到的通过调用cache table tableName即可将一张表缓存到内存中,来极大的提高查询效 ...

随机推荐

  1. Docker安装Nginx1.11.10+php7+MySQL

    Docker安装php-fpm 1.编辑Dockerfile FROM php:7.1.3-fpm ADD sources.list /etc/apt/sources.list RUN cp /usr ...

  2. windows系统下安装node

    最近项目中需要使用到vue框架来实现前后端分离,于是抽时间看了下vue的相关只是,从官网了解到可以使用命令行工具(CLI)来构建应用,于是在本地环境预练了一下 下面这句话摘抄自vue文档: Vue.j ...

  3. Laravel框架中Form表单Get请求搜索(在此感谢[https://simon8.com])

    首先看一下HTML部分的Form表单 <form role="search" method="get" id="searchform" ...

  4. Android Stdio 如何自定义生成APK的名称

    Android Stdio自动默认生成的app的名称都是app-release或者app-debug,生成完后还要手动更改apk的名称,很是麻烦. 自定义生成APK的名称的方法:在\app\build ...

  5. HDU - 1430 魔板 (bfs预处理 + 康托)

    对于该题可以直接预处理初始状态[0, 1, 2, 3, 4, 5, 6, 7]所有可以到达的状态,保存到达的路径,直接打印答案即可. 关于此处的状态转换:假设有初始状态为2,3,4,5,0,6,7,1 ...

  6. 基于Python的Flask的开发实战(第二节程序的基本结构)

    1.初始化 所有的flask程序都必须创建一个程序实例 web服务器使用wsgi接口协议,把接收客户端的请求都转发给这个程序实例来进行处理.这个程序实例就是flask对象 from flask imp ...

  7. Oracle 11g数据库安装和卸载教程

    Oracle11g的安装教程 同时解压缩两个zip文件,生成一个database文件夹,进入到database文件夹,点击setup 去掉安全更新的选项,直接下一步 选择创建和配置数据库,点击下一步 ...

  8. 流处理与消息队列------《Designing Data-Intensive Applications》读书笔记16

    上一篇聊了聊批处理的缺点,对于无界数据来说,流处理会是更好的选择,"流"指的是随着时间的推移逐步增加的数据.消息队列可以将这些流组织起来,快速的在应用程序中给予反馈.但是消息队列与 ...

  9. R语言︱用excel VBA把xlsx批量转化为csv格式

    笔者寄语:批量读取目前看到有以下几种方法:xlsx包.RODBC包.批量转化成csv后读入.本章来自博客:http://www.cnblogs.com/weibaar/p/4506144.html 在 ...

  10. HighCharts之2D对数饼图

    HighCharts之2D对数饼图 1.实例源码 LogarithmicPie.html: <!DOCTYPE html> <html> <head> <me ...