本章包含以下内容:

机器学习;Spark MLlib与Spark ML;数据预处理;分类算法运用;聚类算法运用;推举系统运用;演习之后;流式机器学习。
6.1 机器学习

Spark机械进修:MLlib_特点_数据 云服务

在本节中,我们将试着从打算机科学、统计学和数据剖析的定义角度来机器学习。
机器学习是打算机科学的一个分支,为打算机供应了无须明确编程的学习能力(Arthur Samuel,1959)。
这个研究领域是从人工智能中的模式识别和打算学习理论的研究中蜕变而来的。

更详细地说,机器学习磋商了启示式学习和基于数据进行预测的算法的研究和构建。
这种算法通过从样本输入构建模型,通过订定数据驱动的预测来代替严格的静态程序代码。
现在来看看卡耐基梅隆的Tom M. Mitchell教授对机器学习的定义,他从打算机科学的角度阐明了机器学习的真正意义:

对付某类任务T和性能度量P,如果一个打算机程序在T上以P衡量的性能随着履历E而自我完善,那么就称这个打算机程序从履历E中学习。

基于该定义,我们能够得出打算机程序或者机器能够:

从历史数据中学习;通过履历而得到提升;交互式地增强可用于预测问题结果的模型。

范例的机器学习任务是观点学习、预测建模、聚类以及探求有用的模式。
终极目标是提高学习的自动化程度,从而不再须要人为地干预,或尽可能地降落人为干预的水平。

6.1.1 范例的机器学习事情流

一个范例的机器学习运用程序涉及从输入、处理到输出的几个步骤,形成一个科学的事情流程,如图6-1所示。
范例的机器学习运用程序涉及以下步骤。

图6-1 机器学习流程

(1)加载样本数据。

(2)将数据解析为算法所需的格式。

(3)预处理数据并处理缺失落值。

(4)将数据分成两组:一组用于构建模型(演习数据集),另一组用于测试模型(验证数据集)。

(5)运行算法来构建或演习你的ML模型。

(6)用演习数据进行预测并不雅观察结果。

(7)利用测试数据测试和评估模型,或者利用第三个数据集(称为验证数据集)利用交叉验证技能验证模型。

(8)调度模型以得到更好的性能和准确性。

(9)调度模型扩展性,以便将来能够处理大量的数据集。

(10)支配模型。

在步骤4中,实验数据集是随机分割的,常日被分为一个演习数据集和一个称为采样的测试数据集。
演习数据集用于演习模型,而测试数据集用于终极评估最佳模型的性能。
更好的做法是尽可能多地利用演习数据集以提高泛化性能。
另一方面,建议只利用一次测试数据集,以在打算预测偏差和干系度量时避免过度拟合问题。

6.1.2 机器学习任务的学习类型

根据学习系统学习反馈的实质,机器学习任务常日被分为以下3类,即监督学习、无监督学习以及增强学习,如图6-2所示。

图6-2 机器学习的任务类型

1.监督学习

监督学习的目标是学习将输入映射到与现实天下相同等的输出的一样平常规则。
例如,垃圾邮件过滤数据集常日包含垃圾邮件以及非垃圾邮件。
因此,能够知道演习集中的数据是垃圾邮件还是正常邮件。
我们有机会利用这些信息来演习模型,以便对新来的邮件进行分类。
如图 6-3所示,该图为监督学习的示意图。
算法找到所需的模式后,可以利用这些模式对未标记的测试数据进行预测。
这是最常见的机器学习任务类型,MLlib 也不例外,个中大部分算法都是监督学习,如朴素贝叶斯、逻辑回归、随机森林等,监督学习的数据处理流程大致如图 6-3所示。

图6-3 监督学习流程

从图中可以看出,经由数据预处理后,数据被分为两部分,一部分为测试集,另一部分为演习集,通过学习算法,可以由演习集得到我们所需的模型,模型会用测试集进行验证,工程师会根据验证的情形对模型进行调优,实现一个数据驱动的优化过程。

2.无监督学习

在无监督学习中,数据没有干系的标签,也便是说无法区分演习集与测试集。
因此,我们须要用算法上加上标签,如图 6-4 所示。
因此,标签必须从数据集中推断出来,这意味着无监督学习算法的目标是通过描述构造,以某种构造化的办法对数据进行预处理。

图6-4 无监督学习流程

为了战胜无监督学习中的这个障碍,常日利用聚类技能,基于某些相似性度量来对未标记样本进行分组。
因此,无监督学习任务会涉及挖掘隐蔽的模式、特色学习等。
聚类是智能地对数据集中的元素进行分类的过程。
总体思路是,同一个类中的两个元素比属于不同类中的元素彼此更为“靠近”。
“靠近”的定义可以有很多种。

无监督的例子包括聚类、频繁模式挖掘以及降维等。
MLlib也供应了 k均值聚类、潜在狄利克雷分布(Latent Dirichlet Allocation)、主身分剖析(Principal Component Analysis)、奇异值分解(Singular value decomposition)等聚类与降维算法。

3.增强学习

作为一个人,我们也曾从过去的履历中学习。
多年来积极的赞颂和负面的批评都有助于塑造出本日的我们。
通过与朋友、家人,乃至陌生人互动,我们可以理解什么让人愉快,什么让人难过。
当你实行某个操作时,你有时会立即得到褒奖。
例如,在附近找到购物中央可能会产生即时的知足感,但也有些时候,褒奖不会立时兑现,比如长途跋涉去探求某个地方。
这些都与增强学习密切干系。

因此,增强学习是一种模型本身从一系列行为中学习的技能。
数据集或样本的繁芜性对付须要算法成功学习目标函数的增强学习非常主要。
此外,为了达到终极目标,每条数据都须要做到一点,即在担保与外部环境相互浸染的同时,应确保褒奖函数的最大化,如图 6-5所示。

图6-5 增强学习流程

从图 6-5 中也可以看出增强学习与监督学习最大的不同是其演习集包含着一个考试测验的过程,会试图从环境中得到评价或者反馈。
如围棋这种博弈类游戏,会有两个代理相互用已有的模型订定策略,并根据末了的结果改动自己的模型的过程。
谷歌公司的AlphaGo便是深度学习与增强学习相结合的一个很好的例子。
总而言之,增强学习在行动——评价的环境中得到知识,改进行动方案以适应环境。
增强学习在物联网环境、路线问题、股市交易、机器人等场景得到了广泛运用。

6.2 Spark MLlib与Spark ML

在Spark MLlib模块中,可以看到它的源码紧张分为两个包:spark.ml与spark.mllib,我们将前者称为Spark ML API,后者称为Spark MLlib API,有些算法在两个包中都可以找到,如协同过滤,有些算法只有MLlib有,如SVD。
除此以外,它们还有一些差异。

一言以蔽之,MLlib与ML之间最大的差异在于,ML基于DataFrame,而MLlib API基于RDD,这与GraphX和GraphFrame之间的关系类似。
在Spark 2.0后,基于RDD的API,也便是MLlib API,就已经进入了掩护状态,而Spark MLlib紧张的API为ML API。
虽然如此,Spark MLlib仍旧会以修复Bug的办法支持MLlib API,但不会增加新特性了。
在Spark 2.x的版本中,ML API会逐渐变得与MLlib API一样,在完成这个过程后,MLlib API会被弃用。
在Spark 3.0中,MLlib API会被彻底舍弃。

Spark MLlib转而供应基于DataFrame API的缘故原由有以下3点。

利用DataFrame可以享受到Spark 2.x带来的性能优化,以及跨措辞的统一API。
DataFrame易于利用ML Pipelines特性,这在特色转换方面尤其有用,个中Spark ML Pipelines会不才一节先容。
ML供应了一套跨措辞以及跨机器学习算法的API。

本书提到的Spark ML,并不是一个正式的名字,而是指Spark MLlib中基于DataFrame的那一套API,它紧张是由org.apache.spark.ml的包名,以及术语Spark ML Pipelines得名而来。
此外,由于MLlib API是注定会被替代的,因此本书不会对其着墨太多,紧张以Spark ML API为主。

Spark ML Pipelines

Spark MLlib想成为大数据机器学习的最佳实践,简化机器学习过程,并使其可扩展。
Spark ML API引入了Pipelines API(管道),这类似于Python机器学习库Scikit-Learn中的Pipeline,它采取了一系列API定义并标准化了6.1.1节中事情流,它包含了数据网络、预处理、特色抽取、特色选择、模型拟合、模型验证、模型评估等一系列阶段。
例如,对文档进行分类大概会包含分词、特色抽取、演习分类模型以及调头等过程。
大多数机器学习库不是为分布式打算而设计的,也不供应Pipeline的创建与调优,而这便是Spark ML PipeLines要做的。

Spark ML Pipelines便是对分布式机器学习过程进行模块化的抽象,这样使得多个算法合并成一个Pipeline或者事情流变得更加随意马虎,下面是Pipelines API的关键观点。

DataFrame:DataFrame与Spark SQL中用到的DataFrame一样,是Spark的根本数据构造,贯穿了全体Pipeline。
它可以存储文本、特色向量、演习集以及测试集。
除了常见的类型,DataFrame还支持Spark MLlib特有的Vector类型。
Transformer:Transformer对应了数据转换的过程,它吸收一个DataFrame,在它的浸染下,会天生一个新的DataFrame。
在机器学习中,在涉及特色转换的过程中常常会用到,其余还会用于演习出的模型将特色数据集转换为带有预测结果的数据集的过程,Transformer都必须实现transform()方法。
Estimator:从上面 Transformer 的定义可以得知,演习完成好的模型也是一个Transformer,那么Estimator包含了一个可以让数据集拟合出一个Transformer的算法,Estimator必须实现fit()方法。
Pipeline:一个Pipeline将多个Transformer和Estimator组装成一个特定的机器学习事情流。
Parameter:所有的Estimator和Transformer共用一套通用的API来指定参数。

文档分类是一个在自然措辞处理中非常常见的运用,如垃圾邮件监测、情绪剖析等,下面通过一个文档分类的例子来让读者对Spark的Pipeline有一个感性的理解。
大略来说,任何文档分类运用都须要以下4步。

(1)将文档分词。

(2)将分词的结果转换为词向量。

(3)学习模型。

(4)预测(是否为垃圾邮件或者正负情绪)。

比如在垃圾邮件监测中,我们须要通过邮件正文甄别出哪些是垃圾邮件,邮件正文一样平常会是一段笔墨,如:代开各种***,手续费极低,请联系我。
这样一段笔墨是无法直接应用于Estimator的,须要将其转换为特色向量,一样平常做法是用一个词典构建一个向量空间,个中每一个维度都是一个词,涌现过的为1,未涌现的为0,再根据文档中涌现的词语的频数,用TF-IDF算法为文档中涌现的词维度授予权重。
这样的话,每个文档就能被转为一个等长的特色向量,如下:

(0, 0, …, 0.27, 0, 0, …, 0.1, 0)

接着就可以用来拟合模型并输出测试结果。

用一个流程图来表示全体过程,如图6-6所示,个中Tokenizer和HashingTF为Transformer,浸染分别是分词和打算权重,演习出的模型也是Transformer,用来天生测试结果;Estimator采取的是逻辑回归算法(LR);DS0-DS3都是不同阶段输出的数据。
这便是一个完全意义上的Pipeline。

图6-6 Spark ML Pipeline模型

下面用代码实现全体Pipeline,如下:

package com.spark.examples.mllibimport org.apache.spark.ml.{Pipeline, PipelineModel}import org.apache.spark.ml.classification.LogisticRegressionimport org.apache.spark.ml.feature.{HashingTF, Tokenizer}import org.apache.spark.ml.linalg.Vectorimport org.apache.spark.sql.Rowimport org.apache.spark.sql.SparkSessionobject PipelineExample{ def main(args: Array[String ]): Unit = { val spark = SparkSession .builder .master("local[2]") .appName("PipelineExample") .getOrCreate() import spark.implicits._ // 准备演习数据,个中末了一列便是该文档的标签,即是否为垃圾邮件 val training = spark.createDataFrame(Seq( (0L, "a b c d e spark", 1.0), (1L, "b d", 0.0), (2L, "spark f g h", 1.0), (3L, "hadoop mapreduce", 0.0) )).toDF("id", "text", "label") // 配置全体Pipeline,由3个组件组成:tokenizer(Transformer)、hashingTF(Transformer) // 和 lr(Estimator) val tokenizer = new Tokenizer() .setInputCol("text") .setOutputCol("words") val hashingTF = new HashingTF() .setNumFeatures(1000) .setInputCol(tokenizer.getOutputCol) .setOutputCol("features") val lr = new LogisticRegression() .setMaxIter(10) .setRegParam(0.001) val pipeline = new Pipeline() .setStages(Array(tokenizer, hashingTF, lr)) // 拟合模型,得到结果 val model = pipeline.fit(training) // 将模型持久化 model.write.overwrite().save("/tmp/spark-logistic-regression-model") // 将Pipeline持久化 pipeline.write.overwrite().save("/tmp/unfit-lr-model") // 加载模型 val sameModel = PipelineModel.load("/tmp/spark-logistic-regression-model") // 准备无标签的测试集 val test = spark.createDataFrame(Seq( (4L, "spark i j k"), (5L, "l m n"), (6L, "spark hadoop spark"), (7L, "apache hadoop") )).toDF("id", "text") // 用模型预测测试集,得到预测结果(标签) model.transform(test) .select("id", "text", "probability", "prediction") .collect() .foreach { case Row(id: Long, text: String, prob: Vector, prediction: Double) => println(s"($id, $text) --> prob=$prob, prediction=$prediction") } }}

这样就用Spark完全实现了一个机器学习的流程。
由上面的代码可以看出,这样的构造非常有利于复用Transformer与Estimator组件。

Spark MLlib(ML API)的算法包紧张分为以下几个部分:

特色抽取、转换与选择;分类和回归;聚类;协同过滤;频繁项集挖掘。

个中每一类都有多少种算法的实现,用户可以利用Pipeline按需进行切换,下面姑息这几个种别,分别实现一些真实数据的案例,让读者可以直接上手运用。

此外,在上面代码中,我们用Pipeline API将模型序列化成文件,这样的好处在于可以将模型算作一个黑盒,非常方便模型上线,而不用在上线运用时再去对模型进行硬编码,这将在6.8.3节中有所表示,类似于Python的Pickle库的用法。

6.3 数据预处理

在机器学习实践中,数据科学家拿到的数据常日是不尽如人意的,例如存在大量的缺失落值、特色的值是不同的量纲、有一些无关的特色、特色的值须要再次处理等情形,这样的数据无法直接演习,因此我们须要对这些数据进行预处理。
预处理在机器学习中是非常主要的步骤,如果没有按照精确的方法对数据进行预处理,每每会得到缺点的演习结果。
下面先容几种常见的预处理方法。

6.3.1 数据标准化

常日,我们直接得到的数据包含了量纲,也便是单位,例如身高180 cm,体重75 kg,对付某些算法来说,如果特色的单位分歧一,就无法直接进行打算,因此在很多情形下的预处理过程中,数据标准化是必不可少的。
数据标准化的方法一样平常有z分数法、最大最小法等。

1.z分数法

这种方法根据原始数据(特色)的均值(mean)和标准差(standard deviation)进行数据的标准化,将原始数据转换为z分数,转换函数如下:

个中μ为所有样本数据的均值,σ为所有样本数据的标准差。
Spark MLlib内置了z分数标准化转换功能的Transformer实现类StandardScaler,代码如下:

import org.apache.spark.ml.feature.StandardScalerval dataFrame = spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.***")val scaler = new StandardScaler().setInputCol("features").setOutputCol("scaledFeatures").setWithStd(true).setWithMean(false)// 打算汇总统计量,天生ScalerModelval scalerModel = scaler.fit(dataFrame)// 对特色进行标准化val scaledData = scalerModel.transform(dataFrame)scaledData.show()2.最大最小法

这种方法也称为离差标准化,是对原始数据的线性变换,使结果值映射到 [0 - 1] 之间。
转换函数如下:

个中max为样本数据的最大值,min为样本数据的最小值。
这种方法的毛病是当有新数据加入时,可能导致max和min的变革,须要重新定义,但这种情形在演习过程中很少见。
这种方法对付方差特殊小的特色可以增强其稳定性。
Spark MLlib内置了最大最小转换功能的Transformer实现类MinMaxScaler。

import org.apache.spark.ml.feature.MinMaxScalerimport org.apache.spark.ml.linalg.Vectorsval dataFrame = spark.createDataFrame(Seq( (0, Vectors.dense(1.0, 0.1, -1.0)), (1, Vectors.dense(2.0, 1.1, 1.0)), (2, Vectors.dense(3.0, 10.1, 3.0)))).toDF("id", "features")val scaler = new MinMaxScaler().setInputCol("features").setOutputCol("scaledFeatures")// 打算汇总统计量,天生MinMaxScalerModelval scalerModel = scaler.fit(dataFrame)// rescale each feature to range [min, max].val scaledData = scalerModel.transform(dataFrame)println(s"Features scaled to range: [${scaler.getMin}, ${scaler.getMax}]")scaledData.select("features", "scaledFeatures").show()3.p范数法

p范数法指的是通过打算样本的p范数,用该样本除以该样本的p范数,得到的值便是标准化的结果。
p范数的打算公式如下:

p = 1时,p范数也叫L1范数,此时L1即是样本的所有特色值的绝对值相加。
p = 2时也叫L2范数,此时L2即是样本x间隔向量空间的***的欧氏间隔:

归一化的结果为:

Spark MLlib内置了p范数标准化转换功能的Transformer实现类Normalizer,其代码如下:

import org.apache.spark.ml.feature.Normalizerimport org.apache.spark.ml.linalg.Vectorsval dataFrame = spark.createDataFrame(Seq((0, Vectors.dense(1.0, 0.5, -1.0)),(1, Vectors.dense(2.0, 1.0, 1.0)),(2, Vectors.dense(4.0, 10.0, 2.0)))).toDF("id", "features")// 设置p = 1val normalizer = new Normalizer().setInputCol("features").setOutputCol("normFeatures").setP(1.0)val l1NormData = normalizer.transform(dataFrame)l1NormData.show()// 设置p = -∞val lInfNormData = normalizer.transform(dataFrame, normalizer.p -> Double.PositiveInfinity)println("Normalized using L^inf norm")lInfNormData.show()6.3.2 缺失落值处理

对付缺失落值的处理,须要根据数据的详细情形,比如如果特色值是连续型,常日用中位数来添补;如果特色值是标签型,常日用众数来补齐;某些情形下,还可以用一个显著差异于已有样本中该特色的值来补齐。
Spark并没有供应预置的缺失落值处理的Transformer,这常日须要自己实现,在后面的例子中,我们会实现一个对缺失落值处理的自定义Transformer。

6.3.3 特色抽取

特色抽取(feature extraction)是从原有特色中按照某种映射关系天生原有特色的一个特色子集,而6.3.4节中将提到的特色选择(feature selection),是根据某种规则对原有特色筛选出一个特色子集。
特色选择和特色抽取有相同之处,它们都试图减少数据集中的特色数目,但详细方法不同,特色抽取的方法紧张是通过特色间的关系,如组合不同特色得到新的特色,这样就改变了原来的特色空间;而特色选择的方法是从原始特色数据集中选择出子集,是一种包含关系,没有变动原始的特色空间,如图6-7所示。

图6-7 特色抽取与特色选择

Spark 也供应了很多种特色抽取的方法,常见的如主身分剖析、广泛运用于文本的Word2Vector等。

1.主身分剖析

如果在样本中特色与特色相互干联,无关的特色太多,就会影响模式的创造。
我们须要用降维技能从样本中天生用来代表原有特色的一个特色子集。

在理解主身分剖析(PCA)之前,须要先理解协方差的观点,X特色与Y特色之间的协方差为:

如果协方差为正,解释XY是正干系关系。
协方差为负解释是负干系关系。
协方差为0时,XY相互独立。
如果样本集Dn维特色,那么两两之间的协方差可以组成一个n×n的矩阵,如下是n = 3的情形:

然后须要对这个矩阵进行特色值分解,得到特色值和特色向量,再取出最大的mm < n)个特色值对应的特色向量(w1, w2,…, wm),组成特色向量矩阵W,对每个样本xi实行如下操作,得到降维后的样本zi,如下:

则降维后的数据集为:

下面以数据挖掘领域著名的鸢尾花数据集(IRIS)来用PCA实现降维操作,鸢尾花数据集是常用的分类数据集,包含150个样本,分3种种别,各50条,每个样本4个维度,分别是花萼长度、花萼宽度、花瓣长度和花瓣宽度,代码如下:

package com.spark.examples.mllibimport org.apache.spark.ml.feature.{PCA, VectorAssembler}import org.apache.spark.sql.{Dataset, Row, SparkSession}import org.apache.spark.ml.feature.StandardScalerimport org.apache.spark.sql.types.{DoubleType, StringType, StructField, StructType}import org.apache.spark.ml.Pipelineobject IRISPCA { def main(args: Array[String]): Unit = { val spark = SparkSession .builder() .master("local[2]") .appName("IRISPCA") .getOrCreate() // 数据构造为花萼长度、花萼宽度、花瓣长度、花瓣宽度 val fields = Array("id","Species","SepalLength","SepalWidth","PetalLength","PetalWidth") val fieldsType = fields.map( r => if (r == "id"||r == "Species") {StructField(r, StringType)} else {StructField(r, DoubleType)} ) val schema = StructType(fieldsType) val featureCols = Array("SepalLength","SepalWidth","PetalLength","PetalWidth") val data=spark.read.schema(schema).csv("data/iris") val vectorAssembler = new VectorAssembler() .setInputCols(featureCols) .setOutputCol("features") val vectorData=vectorAssembler.transform(data) // 特色标准化 val standardScaler = new StandardScaler() .setInputCol("features") .setOutputCol("scaledFeatures") .setWithMean(true) .setWithStd(false) .fit(vectorData) val pca = new PCA() .setInputCol("scaledFeatures") .setOutputCol("pcaFeatures") // 主身分个数,也便是降维后的维数 .setK(2) val pipeline = new Pipeline() .setStages(Array(vectorAssembler,standardScaler,pca)) val model = pca.fit(data) // 对特色进行PCA降维 model.transform(data).select("Species", "pcaFeatures").show(100, false) }}

降维后的数据只有两个维度,如下:

 

2.Word2Vector

在自然措辞处理领域,演习集常日为纯文本,这样的数据是无法直接演习的,前面提到的TF-IDF便是一种天生词向量的办法。
但是TF-IDF的缺陷在于纯挚以“词频”衡量一个词的主要性,不足全面,忽略了高下文信息,例如“阿里巴巴成立达摩院”与“人工智能运用有望加速落地”字面无任何相似之处,但它们之间有很强的关联,这用TF-IDF却无法表示。
Word2Vec最先涌如今谷歌公司在2013年揭橥的论文“Efficient Estimation of Word Representation in Vector Space”中,作者是Mikolov。
Word2Vec的基本思想是采取一个3层的神经网络将每个词映射成n维的实数向量,为接下来的聚类或者比较相似性等操作做准备。
这个3层神经网络实际是在对措辞模型进行建模,但在建模的同时也得到了单词在向量空间上的表示,即词向量,也便是说这个词向量是建模过程的中间产物,而这个中间产物才是Word2Vec的真正目标。

Word2Vec采取了两种措辞模型:CBOW与Skip-gram,前者是根据高下文预测下一个词,后者是根据当前词预测高下文。
以CBOW为例,如图6-8所示。

图6-8 CBOW措辞模型

我们选择一个固定的窗口作为语境(高下文):t − 2 — t + 2,在输入层是4个n维的词向量(初始为随机值),隐蔽层做的操作是累计求和操作,隐蔽层包含n个结点,输出层是一棵巨大的二叉树,构建这棵二叉树的算法便是霍夫曼树,它的叶子结点代表了语估中的M个词语,语估中有多少个词,就有多少个叶子结点。
假设左子树为1,右子树为0,这样每个叶子结点都有一个唯一的编码。
末了输出的时候,CBOW采取了层次Softmax算法,隐蔽层的每个结点都与树的每个结点相连,则霍夫曼树上的每个结点都会有M条边,每条边都有权重,对付输入的高下文,我们须要预测的是在高下文一定的情形下,使得预测词w的概率最大,以010110为例,解释霍夫曼树有5层,我们希望在根结点,词向量与根结点相连,也便是第一层,经由回归运算得到第一位即是0的概率只管即便即是1,依次类推,在第二层,希望第二位的值即是1的概率尽可能即是 1。
这样一贯下去,路径上所有的权重乘积便是预测词在当前高下文的概率P(wt),而在语估中我们可以得到当前高下文的残差1 − P(wt),这样的话,就可以利用梯度低落来学习参数了。

由于不须要标注,Word2Vec实质上是一种无监督学习,对自然措辞处理有兴趣的读者不妨仔细阅读谷歌公司的那篇论文。

Spark MLlib内置了Word2Vec算法的Transformer实现类Word2Vec,代码如下:

import org.apache.spark.ml.feature.Word2Vecimport org.apache.spark.ml.linalg.Vectorimport org.apache.spark.sql.Row// 每一行输入数据都是来源于某句话或是某个文档val documentDF = spark.createDataFrame(Seq("Hi I heard about Spark".split(" "),"I wish Java could use case classes".split(" "),"Logistic regression models are neat".split(" ")).map(Tuple1.apply)).toDF("text")// 设置word2Vec参数val word2Vec = new Word2Vec().setInputCol("text").setOutputCol("result").setVectorSize(3).setMinCount(0)val model = word2Vec.fit(documentDF)val result = model.transform(documentDF)result.collect().foreach { case Row(text: Seq[_], features: Vector) =>println(s"Text: [${text.mkString(", ")}] => \nVector: $features\n") }6.3.4 特色选择

特色选择的目标常日是提高预测准确性、提升演习性能、能够更好地阐明模型。
特色选择的一种很主要思想便是对每一维的特色打分,这样就能选出最主要的特色了,基于这种思想的方法有:卡方考验、信息增益以及干系系数。
干系系数紧张量化的是任意两个特色是否存在线性干系,信息增益会不才一节先容,本小节紧张先容卡方考验。

卡方考验因此卡方分布为根本的一种常用假设考验方法,它的原假设是不雅观察频数与期望频数没有差别。
该考验的基本思想是:首先假设原假设成立,基于此条件打算出

值,它表示不雅观察值与理论值之间的偏离程度。
根据卡方分布及自由度可以确定在原假设成立的条件下获得当前统计量及更极度情形的概率P
如果P值很小,解释不雅观察值与理论值偏离程度太大,应该谢绝无效假设,表示比较资料之间有显著差异;否则就不能谢绝无效假设,尚不能认为样本所代表的实际情形和理论假设有差别。

假设样本的某一个特色,它的取值为A和B两个组,而样本的种别有0和1两类。
对样本进行统计,可以得到表6-1所示的统计表。

如果两个变量是独立无关的,那么表6-2中的理论值与实际值的差别会非常小。

χ 2值的打算公式为:

个中A为实际值,也便是表6-1中的4个数据,T为理论值,也便是表6-2中给出的4个数据,打算得到χ 2值为10.01。
得到该值后,须要在给定的置信水平下查得卡方分布临界值,如表6-3所示。

表6-3 给定置信水平下的卡方统计量的值

显然10.01 > 7.88,也便是说该特色与分类结果无关的概率小于0.5%,换言之,我们该当保留这个特色。

Spark MLlib内置了卡方考验组件ChiSqSelector,代码如下:

import org.apache.spark.ml.feature.ChiSqSelectorimport org.apache.spark.ml.linalg.Vectorsval data = Seq( (7, Vectors.dense(0.0, 0.0, 18.0, 1.0), 1.0), (8, Vectors.dense(0.0, 1.0, 12.0, 0.0), 0.0), (9, Vectors.dense(1.0, 0.0, 15.0, 0.1), 0.0))val df = spark.createDataset(data).toDF("id", "features", "clicked")// 配置卡方考验参数val selector = new ChiSqSelector().setNumTopFeatures(3).setFeaturesCol("features").setLabelCol("clicked").setOutputCol("selectedFeatures")val result = selector.fit(df).transform(df)println(s"ChiSqSelector output with top ${selector.getNumTopFeatures} features selected")result.show()6.4 分类算法运用

分类器是机器学习最常见的运用,MLlib中也内置了许多分类模型,本节将会先容决策树和随机森林,以及用Spark MLlib的随机森林分类器实现根据身体监控数据判断人体状态的实例。

6.4.1 决策树

决策树是一种机器学习的方法,实质上是通过一种树形构造对样本进行分类,每个非叶子结点是一次判断,每个叶子结点代表了分类结果。
决策树是一种范例的监督学习,须要一定量的样本来学习的一个树形构造,常见的决策树布局树算法有C4.5与ID3。

下面先来看一个例子,是信贷审批常见的场景:根据信息判断客户是否会过时,表6-4所示是一些样本,一共有4个特色,以及末了的分类结果,为了大略这是一个二分类场景。

表6-4 信贷审批样本(表略)

如果两个变量是独立无关的,那么表6-2中的理论值与实际值的差别会非常小。

χ 2值的打算公式为:

个中A为实际值,也便是表6-1中的4个数据,T为理论值,也便是表6-2中给出的4个数据,打算得到χ 2值为10.01。
得到该值后,须要在给定的置信水平下查得卡方分布临界值,如表6-3所示。

表6-3 给定置信水平下的卡方统计量的值

显然10.01 > 7.88,也便是说该特色与分类结果无关的概率小于0.5%,换言之,我们该当保留这个特色。

Spark MLlib内置了卡方考验组件ChiSqSelector,代码如下:

import org.apache.spark.ml.feature.ChiSqSelectorimport org.apache.spark.ml.linalg.Vectorsval data = Seq( (7, Vectors.dense(0.0, 0.0, 18.0, 1.0), 1.0), (8, Vectors.dense(0.0, 1.0, 12.0, 0.0), 0.0), (9, Vectors.dense(1.0, 0.0, 15.0, 0.1), 0.0))val df = spark.createDataset(data).toDF("id", "features", "clicked")// 配置卡方考验参数val selector = new ChiSqSelector().setNumTopFeatures(3).setFeaturesCol("features").setLabelCol("clicked").setOutputCol("selectedFeatures")val result = selector.fit(df).transform(df)println(s"ChiSqSelector output with top ${selector.getNumTopFeatures} features selected")result.show()6.4 分类算法运用

分类器是机器学习最常见的运用,MLlib中也内置了许多分类模型,本节将会先容决策树和随机森林,以及用Spark MLlib的随机森林分类器实现根据身体监控数据判断人体状态的实例。

6.4.1 决策树

决策树是一种机器学习的方法,实质上是通过一种树形构造对样本进行分类,每个非叶子结点是一次判断,每个叶子结点代表了分类结果。
决策树是一种范例的监督学习,须要一定量的样本来学习的一个树形构造,常见的决策树布局树算法有C4.5与ID3。

下面先来看一个例子,是信贷审批常见的场景:根据信息判断客户是否会过时,表6-4所示是一些样本,一共有4个特色,以及末了的分类结果,为了大略这是一个二分类场景。

以上内容摘选自《Spark海量数据处理:技能详解与平台实战》

本书基于Spark发行版2.4,循规蹈矩,紧张分为基本理论、运用实践和总结。
本书紧张有下面3个特点。

突出实践。
本书第一部分包含20余个Spark运用的例子,绝大部分带有真实数据集,供读者实践;本书第二部分是一个选自生产环境的完全的真实案例,并针对本书做了相应的优化与简化。
层次分明,循规蹈矩。
本书针对学习曲线进行了优化,对付运用型内容,紧张突出利用方法与实践案例;对付事理与关键问题,会深入讲解,乃至少部分还会涉及源码解读与干系论文解析。
技能版本新。
Spark 2.0是Spark一个非常主要的版本,在设计理念与利用办法上都与以前版本有较大不同,本书脱稿前的新版本2.4.4,包含了这一版本的新特性,并根据社区进展对Spark 3.0的干系特性进行了谈论与展望。