VectorIndexer

主要作用:提高决策树或随机森林等ML方法的分类效果。
VectorIndexer是对数据集特征向量中的类别(离散值)特征(index categorical features categorical features )进行编号。
它能够自动判断那些特征是离散值型的特征,并对他们进行编号,具体做法是通过设置一个maxCategories,特征向量中某一个特征不重复取值个数小于maxCategories,则被重新编号为0~K(K<=maxCategories-1)。某一个特征不重复取值个数大于maxCategories,则该特征视为连续值,不会重新编号(不会发生任何改变)。结合例子看吧,实在太绕了。

    VectorIndexer helps index categorical features in datasets of Vectors. It can both automatically decide which features are categorical and convert original values to category indices. Specifically, it does the following:

    Take an input column of type Vector and a parameter maxCategories. Decide which features should be categorical based on the number of distinct values, where features with at most maxCategories are declared categorical.
Compute -based category indices for each categorical feature.
Index categorical features and transform original feature values to indices. Indexing categorical features allows algorithms such as Decision Trees and Tree Ensembles to treat categorical features appropriately, improving performance. This transformed data could then be passed to algorithms such as DecisionTreeRegressor that handle categorical features.

用一个简单的数据集举例如下:

//定义输入输出列和最大类别数为5,某一个特征
//(即某一列)中多于5个取值视为连续值
VectorIndexerModel featureIndexerModel=new VectorIndexer()
.setInputCol("features")
.setMaxCategories()
.setOutputCol("indexedFeatures")
.fit(rawData);
//加入到Pipeline
Pipeline pipeline=new Pipeline()
.setStages(new PipelineStage[]
{labelIndexerModel,
featureIndexerModel,
dtClassifier,
converter});
pipeline.fit(rawData).transform(rawData).select("features","indexedFeatures").show(,false);
//显示如下的结果:
+-------------------------+-------------------------+
|features |indexedFeatures |
+-------------------------+-------------------------+
|(,[,,],[2.0,5.0,7.0])|(,[,,],[2.0,1.0,1.0])|
|(,[,,],[3.0,5.0,9.0])|(,[,,],[3.0,1.0,2.0])|
|(,[,,],[4.0,7.0,9.0])|(,[,,],[4.0,3.0,2.0])|
|(,[,,],[2.0,4.0,9.0])|(,[,,],[2.0,0.0,2.0])|
|(,[,,],[9.0,5.0,7.0])|(,[,,],[9.0,1.0,1.0])|
|(,[,,],[2.0,5.0,9.0])|(,[,,],[2.0,1.0,2.0])|
|(,[,,],[3.0,4.0,9.0])|(,[,,],[3.0,0.0,2.0])|
|(,[,,],[8.0,4.0,9.0])|(,[,,],[8.0,0.0,2.0])|
|(,[,,],[3.0,6.0,2.0])|(,[,,],[3.0,2.0,0.0])|
|(,[,,],[5.0,9.0,2.0])|(,[,,],[5.0,4.0,0.0])|
+-------------------------+-------------------------+
结果分析:特征向量包含3个特征,即特征0,特征1,特征2。如Row=,对应的特征分别是2.,5.0,7.0.被转换为2.,1.0,1.0。
我们发现只有特征1,特征2被转换了,特征0没有被转换。这是因为特征0有6中取值(,,,,,),多于前面的设置setMaxCategories()
,因此被视为连续值了,不会被转换。
特征1中,(,,,,)-->(,,,,,)
特征2中, (,,)-->(,,) 输出DataFrame格式说明(Row=):
3个特征 特征0,, 转换前的值
|(, [,,], [2.0,5.0,7.0])
3个特征 特征1,, 转换后的值
|(, [,,], [2.0,1.0,1.0])|

StringIndexer

理解了前面的VectorIndexer之后,StringIndexer对数据集的label进行重新编号就很容易理解了,都是采用类似的转换思路,看下面的例子就可以了。

//定义一个StringIndexerModel,将label转换成indexedlabel
StringIndexerModel labelIndexerModel=new StringIndexer().
setInputCol("label")
.setOutputCol("indexedLabel")
.fit(rawData);
//加labelIndexerModel加入到Pipeline中
Pipeline pipeline=new Pipeline()
.setStages(new PipelineStage[]
{labelIndexerModel,
featureIndexerModel,
dtClassifier,
converter});
//查看结果
pipeline.fit(rawData).transform(rawData).select("label","indexedLabel").show(,false); 按label出现的频次,转换成0~num numOfLabels-(分类个数),频次最高的转换为0,以此类推:
label=,出现次数最多,出现了4次,转换(编号)为0
其次是label=,出现了3次,编号为1,以此类推
+-----+------------+
|label|indexedLabel|
+-----+------------+
|3.0 |0.0 |
|4.0 |3.0 |
|1.0 |2.0 |
|3.0 |0.0 |
|2.0 |1.0 |
|3.0 |0.0 |
|2.0 |1.0 |
|3.0 |0.0 |
|2.0 |1.0 |
|1.0 |2.0 |
+-----+------------+

在其它地方应用StringIndexer时还需要注意两个问题:
(1)StringIndexer本质上是对String类型–>index( number);如果是:数值(numeric)–>index(number),实际上是对把数值先进行了类型转换( cast numeric to string and then index the string values.),也就是说无论是String,还是数值,都可以重新编号(Index);
(2)利用获得的模型转化新数据集时,可能遇到异常情况,见下面例子。

StringIndexer对String按频次进行编号
id | category | categoryIndex
----|----------|---------------
| a | 0.0
| b | 2.0
| c | 1.0
| a | 0.0
| a | 0.0
| c | 1.0
如果转换模型(关系)是基于上面数据得到的 (a,b,c)->(0.0,2.0,1.0),如果用此模型转换category多于(a,b,c)的数据,比如多了d,e,就会遇到麻烦:
id | category | categoryIndex
----|----------|---------------
| a | 0.0
| b | 2.0
| d | ?
| e | ?
| a | 0.0
| c | 1.0
Spark提供了两种处理方式:
StringIndexerModel labelIndexerModel=new StringIndexer().
setInputCol("label")
.setOutputCol("indexedLabel")
//.setHandleInvalid("error")
.setHandleInvalid("skip")
.fit(rawData);
()默认设置,也就是.setHandleInvalid("error"):会抛出异常
org.apache.spark.SparkException: Unseen label: d,e
().setHandleInvalid("skip") 忽略这些label所在行的数据,正常运行,将输出如下结果:
id | category | categoryIndex
----|----------|---------------
| a | 0.0
| b | 2.0
| a | 0.0
| c | 1.0

IndexToString

相应的,有StringIndexer,就应该有IndexToString。在应用StringIndexer对labels进行重新编号后,带着这些编号后的label对数据进行了训练,并接着对其他数据进行了预测,得到预测结果,预测结果的label也是重新编号过的,因此需要转换回来。见下面例子,转换回来的convetedPrediction才和原始的label对应。

         Symmetrically to StringIndexer, IndexToString maps a column of label indices back to a column containing the original labels as strings. 
A common use case is to produce indices from labels with StringIndexer, train a model with those indices and retrieve the original labels from the column of predicted indices with IndexToString.
IndexToString converter=new IndexToString()
.setInputCol("prediction")//Spark默认预测label行
.setOutputCol("convetedPrediction")//转换回来的预测label
.setLabels(labelIndexerModel.labels());//需要指定前面建好相互相互模型
Pipeline pipeline=new Pipeline()
.setStages(new PipelineStage[]
{labelIndexerModel,
featureIndexerModel,
dtClassifier,
converter});
pipeline.fit(rawData).transform(rawData)
.select("label","prediction","convetedPrediction").show(,false);
|label|prediction|convetedPrediction|
+-----+----------+------------------+
|3.0 |0.0 |3.0 |
|4.0 |1.0 |2.0 |
|1.0 |2.0 |1.0 |
|3.0 |0.0 |3.0 |
|2.0 |1.0 |2.0 |
|3.0 |0.0 |3.0 |
|2.0 |1.0 |2.0 |
|3.0 |0.0 |3.0 |
|2.0 |1.0 |2.0 |
|1.0 |2.0 |1.0 |
+-----+----------+------------------+

离散<->连续特征或Label相互转换

oneHotEncoder

独热编码将类别特征(离散的,已经转换为数字编号形式),映射成独热编码。这样在诸如Logistic回归这样需要连续数值值作为特征输入的分类器中也可以使用类别(离散)特征。

独热编码即 One-Hot 编码,又称一位有效编码,其方法是使用N位 状态寄存
器来对N个状态进行编码,每个状态都由他独立的寄存器 位,并且在任意
时候,其 中只有一位有效。
例如: 自然状态码为:,,,,,
独热编码为:,,,,,
可以这样理解,对于每一个特征,如果它有m个可能值,那么经过独 热编码
后,就变成了m个二元特征。并且,这些特征互斥,每次只有 一个激活。因
此,数据会变成稀疏的。
这样做的好处主要有:
解决了分类器不好处理属性数据的问题
在一定程度上也起到了扩充特征的作用

One-hot encoding maps a column of label indices to a column of binary vectors, with at most a single one-value. This encoding allows algorithms which expect continuous features, such as Logistic Regression, to use categorical features.

//onehotencoder前需要转换为string->numerical
Dataset indexedDf=new StringIndexer()
.setInputCol("category")
.setOutputCol("indexCategory")
.fit(df)
.transform(df);
//对随机分布的类别进行OneHotEncoder,转换后可以当成连续数值输入
Dataset coderDf=new OneHotEncoder()
.setInputCol("indexCategory")
.setOutputCol("ontHotCategory")//不需要fit
.transform(indexedDf);

Bucketizer

分箱(分段处理):将连续数值转换为离散类别
比如特征是年龄,是一个连续数值,需要将其转换为离散类别(未成年人、青年人、中年人、老年人),就要用到Bucketizer了。
分类的标准是自己定义的,在Spark中为split参数,定义如下:
double[] splits = {0, 18, 35,50, Double.PositiveInfinity}
将数值年龄分为四类0-18,18-35,35-50,55+四个段。
如果左右边界拿不准,就设置为,Double.NegativeInfinity, Double.PositiveInfinity,不会有错的。

Bucketizer transforms a column of continuous features to a column of
feature buckets, where the buckets are specified by users.
//
double[] splits={,,,,Double.POSITIVE_INFINITY};Dataset bucketDf=new Bucketizer()
.setInputCol("ages")
.setOutputCol("bucketCategory")
.setSplits(splits)//设置分段标准
.transform(df);
//输出
/*
+---+----+--------------+
|id |ages|bucketCategory|
+---+----+--------------+
|0.0|2.0 |0.0 |
|1.0|67.0|3.0 |
|2.0|36.0|2.0 |
|3.0|14.0|0.0 |
|4.0|5.0 |0.0 |
|5.0|98.0|3.0 |
|6.0|65.0|3.0 |
|7.0|23.0|1.0 |
|8.0|37.0|2.0 |
|9.0|76.0|3.0 |
+---+----+--------------+
*/

QuantileDiscretizer

分位树为数离散化,和Bucketizer(分箱处理)一样也是:将连续数值特征转换为离散类别特征。实际上Class QuantileDiscretizer extends (继承自) Class(Bucketizer)。

参数1:不同的是这里不再自己定义splits(分类标准),而是定义分几箱(段)就可以了。QuantileDiscretizer自己调用函数计算分位数,并完成离散化。
-参数2: 另外一个参数是精度,如果设置为0,则计算最精确的分位数,这是一个高时间代价的操作。另外上下边界将设置为正负无穷,覆盖所有实数范围。

QuantileDiscretizer takes a column with continuous features and outputs a column with binned categorical features. The number of bins is set by the numBuckets parameter.
The bin ranges are chosen using an approximate algorithm (see the documentation for approxQuantile for a detailed description).
The precision of the approximation can be controlled with the relativeError parameter. When set to zero, exact quantiles are calculated (Note: Computing exact quantiles is an expensive operation).
The lower and upper bin bounds will be -Infinity and +Infinity covering all real values.
new QuantileDiscretizer()
.setInputCol("ages")
.setOutputCol("qdCategory")
.setNumBuckets()//设置分箱数
.setRelativeError(0.1)//设置precision-控制相对误差
.fit(df)
.transform(df)
.show(,false);
//例子:
+---+----+----------+
|id |ages|qdCategory|
+---+----+----------+
|0.0|2.0 |0.0 |
|1.0|67.0|3.0 |
|2.0|36.0|2.0 |
|3.0|14.0|1.0 |
|4.0|5.0 |0.0 |
|5.0|98.0|3.0 |
|6.0|65.0|2.0 |
|7.0|23.0|1.0 |
|8.0|37.0|2.0 |
|9.0|76.0|3.0 |
+---+----+----------+

转载自:https://blog.csdn.net/shenxiaoming77/article/details/63715525

Spark ML 中 VectorIndexer, StringIndexer等用法(转载)的更多相关文章

  1. html5+css3中的background: -moz-linear-gradient 用法 (转载)

    转载至-->http://www.cnblogs.com/smile-ls/archive/2013/06/03/3115599.html 在CSS中background: -moz-linea ...

  2. R中apply等函数用法[转载]

    转自:https://www.cnblogs.com/nanhao/p/6674063.html 1.apply函数——对矩阵 功能是:Retruns a vector or array or lis ...

  3. JS中数组Array的用法{转载}

    js数组元素的添加和删除一直比较迷惑,今天终于找到详细说明的资料了,先给个我测试的代码^-^var arr = new Array();arr[0] = "aaa";arr[1] ...

  4. Spark机器学习中ml和mllib中矩阵、向量

    1:Spark ML与Spark MLLIB区别? Spark MLlib是面向RDD数据抽象的编程工具类库,现在已经逐渐不再被Spark团队支持,逐渐转向Spark ML库,Spark ML是面向D ...

  5. Spark ML源码分析之一 设计框架解读

    本博客为作者原创,如需转载请注明参考           在深入理解Spark ML中的各类算法之前,先理一下整个库的设计框架,是非常有必要的,优秀的框架是对复杂问题的抽象和解剖,对这种抽象的学习本身 ...

  6. 使用spark ml pipeline进行机器学习

    一.关于spark ml pipeline与机器学习 一个典型的机器学习构建包含若干个过程 1.源数据ETL 2.数据预处理 3.特征选取 4.模型训练与验证 以上四个步骤可以抽象为一个包括多个步骤的 ...

  7. Spark ML 几种 归一化(规范化)方法总结

    规范化,有关之前都是用 python写的,  偶然要用scala 进行写, 看到这位大神写的, 那个网页也不错,那个连接图做的还蛮不错的,那天也将自己的博客弄一下那个插件. 本文来源 原文地址:htt ...

  8. spark ml 的例子

    一.关于spark ml pipeline与机器学习 一个典型的机器学习构建包含若干个过程 1.源数据ETL 2.数据预处理 3.特征选取 4.模型训练与验证 以上四个步骤可以抽象为一个包括多个步骤的 ...

  9. spark ml pipeline构建机器学习任务

    一.关于spark ml pipeline与机器学习一个典型的机器学习构建包含若干个过程 1.源数据ETL 2.数据预处理 3.特征选取 4.模型训练与验证 以上四个步骤可以抽象为一个包括多个步骤的流 ...

随机推荐

  1. 微信小程序~map组件z-index无效

    因项目需要,以map为背景,上面悬浮有其他组件.微信开发者工具测试时一切正常,但是真机测试时地图组件却把所有的组件覆盖,检查z-index设置,一切正常,地图组件层级也在这些组件的下面,为什么会被覆盖 ...

  2. codevs 1341 与3和5无关的数

    题目描述 Description 有一正整数a,如果它能被x整除,或者它的十进制表示法中某位上的数字为x,则称a与x相关.现求所有小于等于n的与3或5无关的正整数的平方和. 输入描述 Input De ...

  3. 关于使用scipy.stats.lognorm来模拟对数正态分布的误区

    lognorm方法的参数容易把人搞蒙.例如lognorm.rvs(s, loc=0, scale=1, size=1)中的参数s,loc,scale, 要记住:loc和scale并不是我们通常理解的对 ...

  4. C语言蓝桥杯比赛原题和解析

    蓝桥杯:在计算机编程领域,是具有一定含金量的竞赛,用于选拔信息技术人才. 一般分为多个领域,其中包含了C/C#/C++/Java/Python等编程语言的测试题,多为算法的设计题. 下面,在搜题过程中 ...

  5. Vue模板语法(一)

    Vue模板语法 一 vue简介 Vue.js是一套构建用户界面的渐进式框架. 与其他重量级框架不同的是,Vue 采用自底向上增量开发的设计. Vue 的核心库只关注视图层,并且非常容易学习,非常容易与 ...

  6. nginx优化、负载均衡、rewrite

    nginx优化 # 普通用户启动 (useradd nginx -s /sbin/nologin -M) user nginx; # 配置nginx worker进程个数 #worker_proces ...

  7. Linux 内存Cache和Buffer理解

    在 Linux 系统中,我们经常用 free 命令来查看系统内存的使用状态.在一个 RHEL6 的系统上,free 命令的显示内容大概是这样一个状态:   [root@tencent64 ~]# fr ...

  8. PHP命令行执行文件或代码

    Linux环境 1.执行代码 php -r "echo 'hello';" (注意加分号,与PHP文件一样) 2.执行文件 php -f  文件所在路径(/var/www/xxx. ...

  9. Python3正则表达式

    正则表达式是一个特殊的字符序列,他能帮助你方便的检查一个字符串是否与某种模式匹配.   re.match函数 re.match尝试从字符串的起始位置匹配一个模式,如果不是起始位置匹配成功的话,matc ...

  10. 《挑战30天C++入门极限》新手入门:C++中的函数重载

        新手入门:C++中的函数重载 函数重载是用来iostream>  using namespace std;  int test(int a,int b);  float test(flo ...