版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
项目8SparkMLlib学习目标(1)(4)学习SparkMLlib基础知识学习分类回归算法预测学习目标(2)学习使用SparkMLlib完成数据的基本统计(3)学习特征的提取转换和选择的基本方法任务1初识机器学习8.1.1机器学习的概念机器学习是一类算法的总称,其核心是“使用算法解析数据,从中学习,然后对世界上的某件事情做出决定或预测”。这些算法企图从大量历史数据中挖掘出其中隐含的规律,并用于预测或分类,更具体地说,可以把机器学习看作寻找一个函数,输入是样本数据,输出是期望的结果,只是这个函数过于复杂,以至于不太方便形式化表达。这意味着,与其显式地编写程序来执行某些任务,不如教计算机如何开发一个算法来完成任务。需要注意的是,机器学习的目标是使学到的函数很好地适用于“新样本”,而不仅仅是在训练样本上表现得很好。学到的函数适用于新样本的能力,被称为泛化(generalization)能力。8.1.1机器学习的概念综上所述,机器学习是学习得到更好的函数从而更合适处理样本,而通常学习一个好的函数需要以下6个步骤:(2)(3)(4)(5)(6)(1)场景解析数据预处理特征工程模型训练模型评估离线/在线服务8.1.2机器学习的分类机器学习是一个庞大的家族体系,涉及众多算法、任务和学习理论。按任务类型分,机器学习模型可以分为回归模型、分类模型和结构化学习模型。从方法的角度分,可以分为线性模型和非线性模型,线性模型较为简单,但作用不可忽视。线性模型是非线性模型的基础,很多非线性模型都是在线性模型的基础上变换而来的。非线性模型又可以分为传统机器学习模型(如SVM、KNN、决策树等)和深度学习模型。按照学习方式分,机器学习模型可以分为监督学习、无监督学习、半监督学习和强化学习。8.1.2机器学习的分类监督学习01监督学习(supervisedlearning)主要分两种类型:分类和回归。在分类中,机器被训练成将一个组划分为特定的类。回归是指每个进入算法的训练数据样本都有对应的期望值,进行机器学习的过程实际上就是特征值和目标队列映射的过程。例如,机器使用先前的(标记的)数据来预测未来。使用气象事件的历史数据(平均气温、湿度和降水量),手机天气应用程序可以查看当前天气,并在未来的时间内对天气进行预测。常见的监督学习算法见表8-1。表8-1监督学习算法8.1.2机器学习的分类无监督学习02无监督学习(unsupervisedlearning)指训练样本不依赖于先前数据的机器学习算法。既然是没有目标队列,也就缺少了特征环境下的最终结果,那么这样的数据可能对一些回归和分类的场景就不适合了。无监督学习分为聚类和降维。聚类用于根据属性和行为对象进行分组。这与分类不同,因为这些组不是提供的。聚类的一个例子是将一个组划分成不同的子组(如基于年龄和婚姻状况),然后应用到有针对性的营销方案中。降维通过找到共同点来减少数据集的变量。大多数大数据可视化使用降维来识别趋势和规则。常见的无监督学习算法见表8-2。表8-2无监督学习算法8.1.2机器学习的分类半监督学习03半监督学习(semi-supervisedlearning)是最近几年逐渐开始流行的一种机器学习种类。在一些场景下获得打标数据是很耗费资源的,但是无监督学习对于解决分类和回归这样场景的问题又有一些难度。所以人们开始尝试通过对样本的部分打标来进行机器学习算法的使用,这种部分打标样本的训练数据的算法应用,就是半监督学习。8.1.2机器学习的分类强化学习04强化学习(reinforcementlearning)是一种比较复杂的机器学习种类,强调的是系统与外界不断地交互,获得外界的反馈,然后决定自身的行为。强化学习是目前人工智能领域的一个热点算法种类,典型的案例包括无人汽车驾驶和阿尔法狗下围棋。机器学习的这些种类都有各自的常用算法,目前被应用到各种领域。例如,监督学习和无监督学习主要被应用在传统企业数据应用场景中;半监督学习主要应用到图像识别领域和图像处理领域,这是因为图像中存在大量的非标识数据;强化学习主要应用到机器人控制及系统控制领域。8.1.3MLlib数据类型01本地向量本地向量存储在单机上,其由整型、从零开始的索引值及浮点型的元素值组成。MLlib提供了两种类型的本地向量:稠密向量使用一个双精度浮点型数组来表示其中每一维元素。稀疏向量则是基于一个整型索引数组和一个双精度浮点型的值数组。8.1.3MLlib数据类型01本地向量使用SparkShell进行举例,代码如下。//创建稠密本地向量scala>valdv:Vector=Vectors.dense(1.0,0.0,3.0)dv:org.apache.spark.mllib.linalg.Vector=[1.0,0.0,3.0]//第一种方法:创建疏密本地向量,第二个参数数组指定了非零元素的索引,而第三个参数数组则//给定了非零元素值scala>valsv1:Vector=Vectors.sparse(3,Array(0,2),Array(1.0,3.0))sv1:org.apache.spark.mllib.linalg.Vector=(3,[0,2],[1.0,3.0])//第二种方法:创建疏密本地向量,第二个参数是一个序列,其中每个元素都是一个非零值的元组scala>valsv2:Vector=Vectors.sparse(3,Seq((0,2.0),(2,8.0)))sv2:org.apache.spark.mllib.linalg.Vector=(3,[0,2],[2.0,8.0])8.1.3MLlib数据类型02标记向量标注点是一种带有标签(label/response)的本地向量,它可以是稠密的或是稀疏的。在MLlib中,标注点可以用于监督学习算法。标签是用双精度浮点型来存储的,因此在回归和分类问题上可使用标注点。使用SparkShell进行举例,代码如下。importorg.apache.spark.mllib.linalg.Vectorsimportorg.apache.spark.mllib.regression.LabeledPoint//创建一个标签为1.0(分类中可视为正样本)的稠密向量标注点valpos=LabeledPoint(1.0,Vectors.dense(1.0,0.0,3.0))//创建一个标签为0.0(分类中可视为负样本)的稀疏向量标注点valneg=LabeledPoint(0.0,Vectors.sparse(3,Array(0,2),Array(1.0,3.0)))8.1.3MLlib数据类型03本地矩阵本地矩阵存储在本地主机上,它具有整数类型的行和列索引及双精度浮点类型值。MLlib支持稠密矩阵与稀疏矩阵两种,稠密矩阵的所有元素的值存储在以列为主要顺序的双精度数组中,稀疏矩阵的所有元素存储在以列为主要顺序的压缩稀疏列(CSC)模式中。CSC模式请参考/~mcrob/toolbox/c++/sparseMatrix/sparse_matrix_compression.html。例如,稠密矩阵存储在具有矩阵大小的一维阵列中。表示方式为:[1.0,3.0,5.0,2.0,4.0,6.0](3,2)。8.1.3MLlib数据类型03本地矩阵本地矩阵的基类是org.apache.spark.mllib.linalg.Matrix。DenseMatrix和SparseMatrix均是它的实现类,和本地向量类似,MLlib也为本地矩阵提供了相应的工具类Matrices,调用工厂方法dense即可创建实例,创建稠密矩阵的代码如下。scala>importorg.apache.spark.mllib.linalg.{Matrix,Matrices}importorg.apache.spark.mllib.linalg.{Matrix,Matrices}//创建一个3行2列的稠密矩阵[[1.0,2.0],[3.0,4.0],[5.0,6.0]]//请注意,这里的数组参数是列先序的scala>valdm:Matrix=Matrices.dense(3,2,Array(1.0,3.0,5.0,2.0,4.0,6.0))dm:org.apache.spark.mllib.linalg.Matrix=1.02.03.04.05.06.08.1.3MLlib数据类型03本地矩阵这里可以看出列优先的排列方式,即按照列的方式从数组中提取元素,也可以创建一个3行2列的稀疏矩阵[[9.0,0.0],[0.0,8.0],[0.0,6.0]]。//第一个数组参数表示列指针,即每一列元素的开始索引值//第二个数组参数表示行索引,即对应的元素是属于哪一行//第三个数组即是按列先序排列的所有非零元素,通过列指针和行索引即可判断每个元素所在的位置scala>valsm:Matrix=Matrices.sparse(3,2,Array(0,1,3),Array(0,2,1),Array(9,6,8))sm:org.apache.spark.mllib.linalg.Matrix=3x2CSCMatrix(0,0)9.0(2,1)6.0(1,1)8.08.1.3MLlib数据类型04分布式矩阵分布式矩阵具有长整数类型的行和列索引及双精度浮点类型值,其数据存储在多个RDD上。选择正确的格式来存储大型和分布式矩阵非常重要。将分布式矩阵转换为不同的格式可能需要全局进行调整存储,所以选择合适的分布式矩阵的存储方式非常重要,目前已经实现了4种类型的分布式矩阵:无索引行矩阵、有索引行矩阵、坐标矩阵和块矩阵。8.1.3MLlib数据类型04分布式矩阵行矩阵是一个面向行的分布式矩阵,其不具有行索引和列索引,其中每一行都是一个本地的向量,我们使用本地存储模拟存储这些数据。在创建完行矩阵实例后,通过其自带的computeColumnSummaryStatistics()方法获取该矩阵的一些统计摘要信息,并可以对其进行分解。用SparkShell来演示无索引行矩阵的创建,首先创建RDD[Vector],然后创建rows并以rows作为参数直接创建行矩阵mat,最后统计mat的行数和列数。1)无索引行矩阵8.1.3MLlib数据类型04分布式矩阵有索引行矩阵IndexedRowMatrix是对行矩阵RowMatrix的拓展,其中包含每一行的行索引值,这个索引值可以被用来识别不同行,或是进行诸如join之类的操作。一个索引行矩阵是由IndexedRow组成的,其数据存储在一个由IndexedRow组成的RDD中,IndexedRow中的每一行都有一个带长整型的索引值用来存储索引信息。2)有索引行矩阵8.1.3MLlib数据类型04分布式矩阵坐标矩阵CoordinateMatrix由矩阵类型MatrixEntry的RDD组成,而MatrixEntry中封装了非零元素的行、列信息及非零元素的值,矩阵项MatrixEntry是一个三元组:(i:Long,j:Long,value:Double)。其中i是行索引,j是列索引,value是该位置的值。CoordinateMatrix只有当矩阵的两个维度都很大且矩阵非常稀疏时才会被使用。3)坐标矩阵8.1.3MLlib数据类型04分布式矩阵块矩阵是由矩阵块MatrixBlocks的RDD构成的分布式矩阵,其中一个MatrixBlock封装了一个元组((Int,Int),Matrix),其中(Int,Int)是块索引,并且Matrix是给定索引处的子矩阵。块矩阵支持诸如加法add()和乘法multiply()等方法。除此之外,块矩阵还有一个辅助功能validate()方法,该方法可以用来检查块矩阵是否被成功创建。4)块矩阵8.1.3MLlib数据类型04分布式矩阵索引行矩阵和坐标矩阵可以通过调用toBlockMatrix()来创建块矩阵,调用该方法创建的块矩阵的默认大小为1024×1024。以下面的矩阵为例,先使用MatrixEntry创建出坐标矩阵,再转换为块矩阵,最后将矩阵A与其转置矩阵进行乘法运算,代码如下。8.1.4MLlib基本统计实践
01概况统计实践我们使用汽车数据集,它是一类多重变量分析的数据集,是常用的分类实验数据集,通过/ml/machinelearningdatabases/autos/imports85.data下载数据集,使用第10、11、12、13项数据,分别代表轮距、长度、宽度和高度。对于RDD[Vector]类型的变量,SparkMLlib提供了一种称为colStats()的统计方法,调用该方法会返回一个类型为MultivariateStatisticalSummary的实例。通过这个实例,我们可以获得每一列的最大值、最小值、均值、方差、总数等。8.1.4MLlib基本统计实践
01概况统计实践具体代码如下。importorg.apache.spark.mllib.linalg.{Vector,Ventors}importorg.apache.spark.mllib.stat.{MultivariateStatisticalSummary,Statistics}//根据数据集的第10、11、12、13属性转换成RDD[Vector]valobservations=sc.textFile("/home/imports-85.data").map(_.split(",")).map(p=>Vectors.dense(p(9).toDouble,p(10).toDouble,p(11).toDouble,p(12).toDouble))//调用colStats()方法,得到一个MultivariateStatisticalSummary类型的变量scala>valsummary:MultivariateStatisticalSummary=Statistics.colStats(observations)//查看这些数据集统计后的结果scala>println(summary.count)205//每列均值8.1.4MLlib基本统计实践
01概况统计实践具体代码如下。scala>println(summary.mean)[98.75658536585362,174.04926829268288,65.90780487804875,53.724878048780475]//每列方差scala>println(summary.variance)[36.26178240076516,152.20868818747027,4.6018995695839315,5.970799617407945]//每列最大值scala>println(summary.max)[120.9,208.1,72.3,59.8]//每列最小值scala>println(summary.min)[86.6,141.1,60.3,47.8]8.1.4MLlib基本统计实践
01概况统计实践具体代码如下。scala>println(summary.normL1)[20245.100000000024,35680.10000000003,13511.099999999993,11013.600000000008]scala>println(summary.normL2)[1416.5925137455722,2498.2285463904245,944.1534462151793,770.0145193436292]scala>println(summary.numNonzeros)[205.0,205.0,205.0,205.0]8.1.4MLlib基本统计实践
01概况统计实践其中,主要方法的含义与返回值类型见表8-3。表8-3统计表格8.1.4MLlib基本统计实践
02相关性实践相关系数是用来反映变量之间关系密切程度的统计指标。变量间相关系数绝对值越大,则变量间相关性越强(值越接近1或-1),当取值为0时,表示不相关,取值为(0~-1]表示负相关,取值为(0,1]表示正相关。MLlib提供了用于计算多系数数据之间两两相关的灵活算法,它支持Pearson相关和Spearman相关。Statistics提供了计算系列数据相关性的方法,它根据输入类型的不同,输出的结果也会发生相应的变化。如果输入的是两个RDD[Double],则输出的是一个Double类型的结果;如果输入的是一个RDD[Vector],则对应输出的是一个相关系数矩阵。8.1.4MLlib基本统计实践
02相关性实践我们仍然使用上述数据集进行实践,代码如下。scala>importorg.apache.spark.SparkContextscala>importorg.apache.spark.mllib.linalg._scala>importorg.apache.spark.mllib.stat.Statistics//将RDD1命名为seriesX,含义是车辆长度RDDscala>valseriesX=sc.textFile("/home/imports-85.data").map(_.split(",")).map(p=>p(10).toDouble)seriesX:org.apache.spark.rdd.RDD[Double]=MapPartitionsRDD[74]atmapat<console>:37//将RDD2命名为seriesY,含义是车辆宽度RDD8.1.4MLlib基本统计实践
02相关性实践我们仍然使用上述数据集进行实践,代码如下。scala>valseriesY=sc.textFile("/home/imports85.data").map(_.split(",")).map(p=>p(11).toDouble)seriesY:org.apache.spark.rdd.RDD[Double]=MapPartitionsRDD[78]atmapat<console>:37//调用Statistics的corr方法查看车辆长度与宽度的相关性scala>valcorrelation:Double=Statistics.corr(seriesX,seriesY,"pearson")correlation:Double=0.8411182684812752scala>print(correlation)0.8411182684812752这说明车辆的长度和宽度之间的相关性为0.8411182684812752,车辆长度与宽度之间的相关性非常高。8.1.4MLlib基本统计实践
02相关性实践上述方法输入的系数是两个RDD[Double]类型,然后使用一个RDD[Vector]来作为传入参数,从而得到一个相关矩阵。代码如下。scala>valdata=sc.textFile("/home/imports-85.data").map(_.split(",")).map(p=>Vectors.dense(p(10).toDouble,p(11).toDouble))data:org.apache.spark.rdd.RDD[org.apache.spark.mllib.linalg.Vector]=MapPartitionsRDD[86]atmapat<console>:37//调用Statistics包中的corr()函数,同样可以选择pearson或spearman,得到相关系数矩阵scala>valcorrelMatrix1:Matrix=Statistics.corr(data,"pearson")correlMatrix1:org.apache.spark.mllib.linalg.Matrix=1.00.84111826848127520.84111826848127521.08.1.4MLlib基本统计实践
02相关性实践相关矩阵也称相关系数矩阵,它是由矩阵各列间的相关系数构成的。在上述实例中,相关矩阵第0行第1列的元素是原矩阵data的第0列和第1列的相关系数。可以查看一下上述data数据矩阵。data.foreach{x=>println(x)}[168.8,64.1][168.8,64.1][171.2,65.5]……8.1.4MLlib基本统计实践
03分层抽样实践分层抽样(stratifiedsampling),顾名思义,就是将数据根据不同的特征分成不同的组,然后按特定条件从不同的组中获取样本,并重新组成新的数组。对于分层抽样,sampleByKey()和sampleByKeyExact()在RDD的键值对上执行,将键视为标签,将值视为特定属性。sampleByKey()需要对数据进行遍历,并输入数据的期望,从而确定抽样样本。sampleByKeyExact()方法比sampleByKey()更加复杂,单预测精准程度更高。8.1.4MLlib基本统计实践
04假设检验实践在统计分析过程中,假设检验是非常常用的工具,假设检验的基本思想是小概率反证法思想。小概率思想是指小概率事件(P<0.01或P<0.05)在一次试验中基本上不会发生。反证法思想是先提出假设(假设H0),再用适当的统计方法确定假设成立的可能性大小,若可能性小,则认为假设不成立,若可能性大,则还不能认为假设不成立。可以使用该方法判断结果是否统计充分,还可用来判断该结果是否为随机生成的。8.1.4MLlib基本统计实践
04假设检验实践//导入相关包importorg.apache.spark.mllib.linalg._importorg.apache.spark.mllib.regression.LabeledPointimportorg.apache.spark.mllib.stat.Statisticsimportorg.apache.spark.mllib.stat.test.ChiSqTestResultimportorg.apache.spark.rdd.RDD//数据集组成的向量值,可以使用汽车数据集组成向量值//valtest=sc.textFile("/home/imports85.data").map(_.split(",")).map(p=>Vectors.//dense(p(0).toDouble,p(1).toDouble,p(2).toDouble,p(3).toDouble)).first8.1.4MLlib基本统计实践
04假设检验实践valvec:Vector=Vectors.dense(0.1,0.15,0.2,0.3,0.25)//适合度检验valgoodnessOfFitTestResult=Statistics.chiSqTest(vec)println(s"$goodnessOfFitTestResult\\n")//创建一个矩阵((1.0,2.0),(3.0,4.0),(5.0,6.0))valmat:Matrix=Matrices.dense(3,2,Array(1.0,3.0,5.0,2.0,4.0,6.0))//使用矩阵进行独立性检测valindependenceTestResult=Statistics.chiSqTest(mat)println(s"$independenceTestResult\\n")任务2特征提取和转换8.2.1特征提取特征提取是机器学习中很常用的数据处理方式,一般都出现在实际搭建模型之前,以达到特征空间维度的变化(常见的是降维操作)。特征提取是通过适当变换把已有样本的D个特征转换成d(d<D)个新特征。这样做的主要目的有:降低特征空间的维度,使后续的分类器设计在计算上更容易实现;消除原有特征之间的相关度,减少数据信息的冗余,以更有利于分类。8.2.1特征提取1.TF-IDF“词频逆文档频率”(TF-IDF)是一种在文本挖掘中广泛使用的特征向量化方法,它可以体现一个文档中的词语在语料库中的重要性。TF表示词频,IDF表示逆文档频率。(1)TF:HashingTF是一个Transformer,在文本处理中,接收词条的集合然后把这些集合转化成固定长度的特征向量。这个算法在哈希的同时会统计各个词条的词频。(2)IDF:IDF是一个Estimator,在一个数据集上应用它的fit()方法,产生一个IDFModel。该IDFModel接收特征向量(由HashingTF产生),然后计算每一个词在文档中出现的频次。IDF会减少那些在语料库中出现频率较高的词的权重。8.2.1特征提取1.TF-IDF下面的代码段从一组句子开始,将每个句子使用Tokenizer分成单词。对于每个句子(单词包),我们使用HashingTF将句子散列为特征向量,然后使用IDF重新缩放特征向量。特征向量可以传递给学习算法。提前准备文本文件kmeans_data.txt,其内容如下。0.00.00.00.10.10.10.20.20.29.09.09.09.19.19.19.29.29.2代码如下。见书本P194-195。8.2.1特征提取2.词向量化Word2VecWord2Vec将一个单词转换为分布式的词向量的格式,它将单词序列化为新模型Word2VecModel。该模型将每个单词映射到一个唯一的固定大小的向量,使用Word2VecModel文档中所有单词的平均值将每个文档转换为向量。转换后的模型可以用来实现相似度计算、机器翻译与解析等,如图8-1所示。图8-1转换模型8.2.1特征提取2.词向量化Word2Vec在MLlib中创建Word2Vec对象需要设置很多参数,这里给出具体参数说明。·finalvalinputCol:Param[String]:输入列名。·finalvalmaxIter:IntParam:最大迭代次数。·finalvalminCount:IntParam:Word2Vec模型中词汇出现的最小次数,默认是5。·finalvalnumPartitions:IntParam:单词句子分区数,默认是1。·finalvaloutputCol:Param[String]:输出列名。·finalvalseed:LongParam:自由度。·finalvalstepSize:DoubleParam:每次迭代的步骤大小。·finalvalvectorSize:IntParam:转换的维度,默认是100。8.2.1特征提取3.CountVectorizerCountVectorizer旨在通过计数方法将一组文本文档转换为向量。当先验字典不可用时,CountVectorizer可以用作Estimator提取词汇表,并生成一个CountVectorizerModel。该模型为词汇表上的文档生成稀疏表示,然后可以将其传递给其他算法,如LDA。例子有如表8-4所示的文档,分别是数据id和text。表8-4数据id和text8.2.1特征提取3.CountVectorizer每行text都是Array[String]类型的文档。调用拟合CountVectorizer产生CountVectorizerModel词汇(a,b,c)。然后转换后的输出列vector见表8-5。表8-5数据id、text和Vector8.2.1特征提取3.CountVectorizer下面给出两个词汇库,分别是"a","b","c","e","f"和"a","b","b","c","a",并使用CountVectorizer统计词库中的单词数,同时设定统计结果的过滤条件为词汇表的最大量为3且该统计词汇至少要在2个文档中出现过,因此统计结果只统计了"a","b","c"。代码如下。importspark.implicits._importorg.apache.spark.ml.feature.{CountVectorizer,CountVectorizerModel}//假设有如下DataFrame,其包含id和text两列,可以被看成是一个包含两个文档的词语库valdf=spark.createDataFrame(Seq((0,Array("a","b","c","e","f")),(1,Array("a","b","b","c","a")))).toDF("id","text")//这里设定词汇表的最大量为3,设定词汇表中的词至少要在两个文档中出现过,并过滤偶然出8.2.1特征提取3.CountVectorizer//现的词汇e和f。通过CountVectorizer设定参数生成一个CountVectorizerModelvalcvModel:CountVectorizerModel=newCountVectorizer().setInputCol("text").setOutputCol("features").setVocabSize(3).setMinDF(2).fit(df)//通过调用CountVectorizerModel的vocabulary方法,获得模型的词汇表scala>cvModel.vocabularyres7:Array[String]=Array(b,a,c)//从打印结果可以看到,词汇表中有a、b、c三个词,且这三个词都在两个文档中出现过(前文设定//了minDF为2)//使用这一模型对DataFrame进行变换,可以得到文档的向量化表示scala>cvModel.transform(df).show(false)8.2.1特征提取3.CountVectorizer结果如图8-2所示。表8-5数据id、text和Vector图8-2结果输出8.2.2常用特征转换分词器(Tokenizer)提供了将文本切分成单词的功能,该函数的输入通常是一段句子或文本,然后将句子切分成词汇,并输出这些词汇。表8-6提供了3条数据,每条数据有2个字段,分别是序号id和预处理数据sentence,使用下面的实例来讲解如何用分词器Tokenizer和正则分词器RegexTokenizer将文本分割为单词。1.分词器表8-6文本表8.2.2常用特征转换1.分词器importorg.apache.spark.ml.feature.{RegexTokenizer,Tokenizer}importorg.apache.spark.sql.SparkSessionimportorg.apache.spark.sql.functions._valsentenceDataFrame=spark.createDataFrame(Seq((0,"HiIheardaboutSpark"),(1,"IwishJavacouldusecaseclasses"),(2,"Logistic,regression,models,are,neat"))).toDF("id","sentence")//创建tokenizer,设置标记输入列名为sentence,输出列名为words//使用默认“\s”匹配空格valtokenizer=newTokenizer().setInputCol("sentence").setOutputCol("words")8.2.2常用特征转换1.分词器//创建regexTokenizer,设置输入列为sentence,输出列为words,匹配正则表达式为“\\W”//\W匹配任何非单词字符,等价于[^A-Za-z0-9_]scala>valregexTokenizer=newRegexTokenizer().setInputCol("sentence").setOutputCol("words").setPattern("\W")valcountTokens=udf{(words:Seq[String])=>words.length}valtokenized=tokenizer.transform(sentenceDataFrame)scala>tokenized.select("sentence","words").withColumn("tokens",countTokens(col("words"))).show(false)结果如图8-3所示。图8-3tokenized分解结果8.2.2常用特征转换1.分词器scala>valregexTokenized=regexTokenizer.transform(sentenceDataFrame)scala>regexTokenized.select("sentence","words").withColumn("tokens",countTokens(col("words"))).show(false)c结果如图8-4所示。图8-4regexTokenized语句分解结果通过配置不同的参数Pattern,可以看到两个输出结果是不同的,结果一的tokens第三行为1,因为Pattern没有设置,使用默认匹配空格;结果二的tokens第三行为5,因为Pattern设置为匹配所有非单词字符。8.2.2常用特征转换2.排除词排除词(StopWordsRemover)是从输入中排除指定的词,通常是因为词经常出现但这些词没有意义。下面用一个例子来说明排除词的用法,如表8-7所示分别是数据id和raw。表8-7id和raw表在filtered,过滤掉了停用词“I”“the”“have”和“a”,使用StopWordsRemover进行处理,raw作为输入列,filtered作为输出列,希望得到如表8-8所示的结果。表8-8过滤表8.2.2常用特征转换2.排除词代码如下。importorg.apache.spark.ml.feature.StopWordsRemover//设置输入列名和输出列名,默认排除英语单词,但这并不是很准确valremover=newStopWordsRemover().setInputCol("raw").setOutputCol("filtered")valdataSet=spark.createDataFrame(Seq((0,Seq("I","saw","the","red","baloon")),(1,Seq("Mary","had","a","little","lamb")))).toDF("id","raw")remover.transform(dataSet).show(false)8.2.2常用特征转换3.n-gramn-gramn-gram是一种将输入的字符串数组转换成n-gram的特征变换器,如果输入数组的值为空则忽略,通过转换返回一个n-gram数组,数组中的每个元素由一个空格分隔的单词字符串表示。需要注意的是,当输入为空时,返回空数组。当输入数组长度小于n(每个ngram的元素数)时,不返回n-gram。8.2.2常用特征转换3.n-gram在MLlib中创建ngram对象需要设置很多参数,说明如下。·finalvalinputCol:Param[String]:输入列名。·valn:IntParam:最小ngram的长度,大于等于1,默认是2。·finalvaloutputCol:Param[String]:输出列名。8.2.2常用特征转换3.n-gram下面用一个例子来说明排除词的用法,如表8-9所示的数据分别是数据id和words。表8-9id和words数据表使用n-gram将words下的单词分割成由单词字符串组成的数组,长度为2,希望得到如表8-10所示的结果。表8-10单词分割表8.2.2常用特征转换3.n-gram代码如下。importorg.apache.spark.ml.feature.NGramvalwordDataFrame=spark.createDataFrame(Seq((0,Array("Hi","I","heard","about","Spark")),(1,Array("I","wish","Java","could","use","case","classes")),(2,Array("Logistic","regression","models","are","neat")))).toDF("id","words")//新建ngram,设置ngram的长度、输入列和输出列valngram=newNGram().setN(2).setInputCol("words").setOutputCol("ngrams")//通过ngram进行转换valngramDataFrame=ngram.transform(wordDataFrame)ngramDataFrame.select("ngrams").show(false)8.2.2常用特征转换3.n-gram结果如图8-5所示。图8-5n-gram转换结果8.2.2常用特征转换4.二值化二值化器采用通用参数inputcol和outputcol,以及二值化阈值。大于阈值的特征值被二值化为1.0;等于或小于阈值的值被二值化为0.0。inputcol支持Vector和Double类型。下面使用二值化将一组消费人群按照年龄50岁进行区分,分别为老年人和非老年人,数据见表8-11。表8-11id和age数据表8.2.2常用特征转换4.二值化使用Binarizer按照age进行二值化,区分老年人和非老年人,阈值为50.0,希望得到如表8-12所示的结果。表8-12二值化结果表8.2.2常用特征转换4.二值化scala>importorg.apache.spark.ml.feature.Binarizerscala>valdata=Array((0,34.0),(1,56.0),(2,50.0),(3,60.0),(4,25.0))data:Array[(Int,Double)]=Array((0,34.0),(1,56.0),(2,50.0),(3,60.0),(4,25.0))//将数组转换为DataFramescala>valdataFrame=spark.createDataFrame(data).toDF("id","age")//初始化Binarizer对象并进行设定:setThreshold是设置阈值,setInputCol是设置需要进行//二值化的输入列,setOutputCol是设置输出列valbinarizer:Binarizer=newBinarizer().setInputCol("age").setOutputCol("binarized_feature").setThreshold(50.0)//使用transform方法将DataFrame进行二值化valbinarizedDataFrame=binarizer.transform(dataFrame)//展示结果println(s"BinarizeroutputwithThreshold=${binarizer.getThreshold}")binarizedDataFrame.show()8.2.2常用特征转换4.二值化结果如图8-6所示。图8-6二值化结果18.2.2常用特征转换5.连续型数据处理之给定边界离散化(Bucketizer)Bucketizer将一列连续的特征转换为(离散的)特征区间,区间由用户指定。其中,创建Bucketizer需要设置一个参数splites(分箱数),说明如下:分箱数为n+1时,将产生n个区间。除了最后一个区间外,每个区间范围[x,y]由分箱的x、y决定。分箱必须是严格递增的。分箱(区间)建在分箱(区间)指定外的值将被归为错误。8.2.2常用特征转换5.连续型数据处理之给定边界离散化(Bucketizer)代码如下。scala>importorg.apache.spark.ml.feature.Bucketizerscala>valarray=Array((1,13.0),(2,16.0),(3,23.0),(4,35.0),(5,56.0),(6,44.0))//将数据转换为DataFramescala>valdf=spark.createDataFrame(array).toDF("id","age")//设定边界,分为5个年龄组:[0,20),[20,30),[30,40),[40,50),[50,正无穷)//注:人的年龄当然不可能正无穷,这里只是为了给大家演示正无穷PositiveInfinity的//用法,负无穷是NegativeInfinityscala>valsplits=Array(0,20,30,40,50,Double.PositiveInfinity)//初始化Bucketizer对象并进行设定:setSplits方法用于设置划分依据scala>valbucketizer=newBucketizer().setSplits(splits).setInputCol("age").setOutputCol("bucketizer_feature")//transform方法将DataFrame二值化scala>valbucketizerdf=bucketizer.transform(df)//show方法用于展示结果scala>bucketizerdf.show8.2.2常用特征转换5.连续型数据处理之给定边界离散化(Bucketizer)结果如图8-7所示。图8-7二值化结果28.2.2常用特征转换6.主成分分析主成分分析(principalcomponentsanalysis,PCA)是图像处理中经常用到的降维方法,在处理有关数字图像方面的问题时,如图像查询问题,在一个存有几万、几百万甚至更多图像的数据库中查询一幅相近的图像。8.2.2常用特征转换6.主成分分析PCA是一种统计过程,它使用正交变换将可能相关变量的一组观察值转换为称为主成分的线性不相关变量的一组值。PCA类使用PCA训练模型将向量投影到低维空间。下面的示例显示了如何将5维特征向量投影到3维主成分中。代码如下。importorg.apache.spark.ml.feature.PCAimportorg.apache.spark.ml.linalg.Vectors//创建一个5维向量valdata=Array(Vectors.sparse(5,Seq((1,1.0),(3,7.0))),Vectors.dense(2.0,0.0,3.0,4.0,5.0),Vectors.dense(4.0,0.0,0.0,6.0,7.0))//将向量转换为DataFrame形式valdf=spark.createDataFrame(data.map(Tuple1.apply)).toDF("features")df.show8.2.2常用特征转换6.主成分分析结果如图8-8所示。图8-8DataFrame图//创建PCA对象,输入列名为features,输出列名为pcaFeatures,过滤表格为df,维度为3valpca=newPCA().setInputCol("features").setOutputCol("pcaFeatures").setK(3).fit(df)valresult=pca.transform(df).select("pcaFeatures")result.show(false)结果如图8-9所示。图8-9PCA结果图8.2.2常用特征转换7.StringIndexerStringIndexer转换器可以把一列类别型的特征(或标签)进行编码,使其数值化,索引的范围从零开始,该过程可以使得相应的特征索引化,使得某些无法接收类别型特征的算法可以使用,并提高诸如决策树等机器学习算法的效率。8.2.2常用特征转换7.StringIndexer索引构建的顺序为标签的频率,优先编码频率较大的标签,所以出现频率最高的标签为0号。如果输入的是数值型的,我们会把它转化成字符型,然后对其进行编码。importorg.apache.spark.ml.feature.{StringIndexer,StringIndexerModel}//创建一个DataFrame,它只包含一个id和categoryscala>valdf1=spark.createDataFrame(Seq(|(0,"a"),|(1,"b"),|(2,"c"),|(3,"a"),|(4,"a"),|(5,"c"))).toDF("id","category")8.2.2常用特征转换7.StringIndexerdf1:org.apache.spark.sql.DataFrame=[id:int,category:string]//创建一个StringIndexer对象,设定输入、输出列名,其余参数采用默认值按照字母的出//现频率降序排序,并对这个DataFrame进行训练,产生StringIndexerModel对象scala>valindexer=newStringIndexer().|setInputCol("category").|setOutputCol("categoryIndex")scala>valmodel=indexer.fit(df1)//随后即可利用该对象对DataFrame进行转换操作,StringIndexerModel依次按照出现频率//的降序进行排序,即出现最多的a被编号成0,中间多的c为1,最少的b为2scala>valindexed1=model.transform(df1)scala>indexed1.show()8.2.2常用特征转换7.StringIndexer结果如图8-10所示。图8-10StringIndexer结果图18.2.2常用特征转换8.IndexToString与StringIndexer相对应,IndexToString的作用是把标签索引的一列重新映射回原有的字符型标签。其主要使用场景一般都是和StringIndexer配合,先用StringIndexer将标签转化成标签索引,进行模型训练,然后在预测标签时把标签索引转化成原有的字符标签。当然,也可以另外定义其他标签。具体代码见P207-208。8.2.2常用特征转换8.IndexToString结果如图8-11所示。图8-11StringIndexer结果图28.2.2常用特征转换9.VectorIndexerStringIndexer是针对单个类别型特征进行转换的,如果所有特征都已经被组织在一个向量中,又想对其中某些单个分量进行处理,SparkMLlib提供了VectorIndexer类来解决向量数据集中的类别性特征转换。VectorIndexer将Vectors的数据集中的特性进行分类转换,它既可以决定哪些特征被分类,也可以将原始值转换为类别的索引。8.2.2常用特征转换9.VectorIndexer操作步骤如下。(1)设置Vector类型的输入列和参数maxCategories。(2)根据每列的不同值数量确定哪些特征应该是分类的,小于等于maxCategories的认定为类别型特征转换,其他列依旧是原始值。(3)为每列数字从小到大排列,从0开始的类别索引,然后是1,以此类推。(4)将原始值转换为索引值。8.2.2常用特征转换9.VectorIndexer下面举个例子,输入为一个数据集,然后使用VectorIndexer训练出模型,通过设置maxCategories为2,来决定哪些特征需要被作为类别特征,将类别特征转换为索引,即只有种类小于2的特征才被认为是类别型特征,否则被认为是连续型特征。结果如图8-12所示。具体代码见P217。图8-12VectorIndexer结果图8.2.2常用特征转换10.StandardScaler基于特征值的均值(mean)和标准差(standarddeviation)进行数据的标准化。它的计算公式:标准化数据=(原数据-均值)/标准差标准化后的变量值围绕0上下波动,大于0说明高于平均水平,小于0说明低于平均水平。StandardScaler将行向量数据集的所有属性值进行标准化,代码如下。importorg.apache.spark.ml.feature.StandardScalervaldataFrame=spark.read.format("libsvm").load("data/mllib/sample_libsvm_data.txt")//setWithMean是否减均值,setWithStd是否将数据除以标准差//这里没有减均值但有除以标准差valscaler=newStandardScaler().setInputCol("features")8.2.2常用特征转换10.StandardScaler
.setOutputCol("scaledFeatures").setWithStd(true).setWithMean(false)valscalerModel=scaler.fit(dataFrame)valscaledData=scalerModel.transform(dataFrame)scaledData.show()结果如图8-13所示。图8-13StandardScaler结果图8.2.3特征选择特征选择(featureselection)指的是在特征向量中筛选出有价值的特征,将其组成新的特征向量的过程。特征选择应用在高维数据分析中十分重要,它可以剔除掉冗余和无关的特征,从而提升学习器的性能。VectorSlicer卡方选择器(ChiSqSelector)RFormula8.2.3特征选择1.VectorSlicerVectorSlicer是一个转换器,输入为特征向量,输出为原始特征向量子集。VectorSlicer接收带有特定索引的向量列,通过对这些索引的值进行筛选得到新的向量集。可接收如下两种索引。(1)整数索引,setIndices()。(2)字符串索引代表向量中特征的名字,此类要求向量列有AttributeGroup,因为该工具根据Attribute来匹配名字字段。8.2.3特征选择1.VectorSlicer下面通过一段代码来说明VectorSlicer的使用方法。8.2.3特征选择1.VectorSlicer下面通过一段代码来说明VectorSlicer的使用方法。8.2.3特征选择1.VectorSlicer结果如图8-14所示。图8-14VectorSlicer结果图8.2.3特征选择2.卡方选择器卡方选择是统计学上常用的一种有监督特征选择方法,它通过对特征和真实标签之间进行卡方检验,来判断该特征和真实标签的关联程度,进而确定哪些特性被选择使用。这其中涉及数学统计概率论的基本知识。卡方选择器(ChiSqSelector)支持5种选择方法:percentilenumTopFeaturesfprfdrfwr8.2.3特征选择2.卡方选择器下面通过一段代码来说明ChiSqSelector的使用方法。8.2.3特征选择2.卡方选择器结果如图8-15所示。图8-15卡方选择器结果图8.2.3特征选择3.RFormulaRFormula与线性代数知识关联性很高,可以选择性学习。通过R模型公式(Rmodelformu
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 校园图书借阅与管理制度
- 景区门票优惠审批制度
- 2026届辽宁抚顺市六校联合体生物高一第一学期期末统考模拟试题含解析
- 食品分拣配送设施制度
- 2025浙江富浙科技有限公司实习生岗位招聘2人备考题库有答案详解
- 2026广东佛山市南海区狮山镇英才学校物理、英语、语文、体育教师招聘4人备考题库及参考答案详解一套
- 2026江苏连云港市灌云万邦人力资源有限公司招聘10人备考题库参考答案详解
- 罕见肿瘤的个体化治疗疗效评估标准制定
- 收费员财务制度
- 地产财务制度汇编
- JCT 2126.1-2023 水泥制品工艺技术规程 第1部分:混凝土和钢筋混凝土排水管 (正式版)
- 高中地理选择性必修二知识点
- 航天禁(限)用工艺目录(2021版)-发文稿(公开)
- GB/T 4937.34-2024半导体器件机械和气候试验方法第34部分:功率循环
- 人教版小学数学一年级下册全册同步练习含答案
- 加油站防投毒应急处理预案
- 闭合导线计算(自动计算表)附带注释及教程
- 项目1 变压器的运行与应用《电机与电气控制技术》教学课件
- 网店运营中职PPT完整全套教学课件
- 北师大版八年级数学下册课件【全册】
- 关于提高护士输液时PDA的扫描率的品管圈PPT
评论
0/150
提交评论