前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住给大家分享一下。点击跳转到网站:https://www.captainai.net/dongkelun
前言
最近在学习总结机器学习常用算法,在看spark机器学习决策树的官方示例时,发现用到了几个特征处理的类,之前没学习过,所以查了一下,感觉spark在特征处理方面的类还是挺多的,所以准备总结记录一下相关的用法,首先总结一下决策树中用到的几种。
1、VectorIndexer
根据源码注释,VectorIndexer是用于在“向量”的数据集中索引分类特征列的类(Class for indexing categorical feature columns in a dataset of Vector),这看起来不太好理解,直接看用法,举例说明就好了。
1.1 数据
我们用普通的数据格式即可:
data1.txt
1 | 1,-1.0 1.0 |
其中第一列为label,后面的为features
spark读取数据程序(供参考):
1 | import spark.implicits._ |
结果:
1 | +-----+----------+ |
1.2 代码
用法一:通过设置MaxCategories
1 | import org.apache.spark.ml.feature.VectorIndexer |
结果
1 | Chose 1 categorical features: 0 |
可以看出选择了一个分类特征索引0,即第一个特征,设置MaxCategories为2,因为特征1只有两个值[-1.0,0.0]小于等于2所以会被索引,索引从零开始,而第二个特征有三个值[1.0,3.0,5.0],所以被认为是连续值,不会被索引,即保留原值。
将MaxCategories设为5,重新跑一下上面的代码
1 | Chose 2 categorical features: 0, 1 |
这次选出两个特征都进行索引,这是因为每个特征值的数量都小于5,可以看出,索引值从0开始,依次加1,对应的原始特征值也是按大小排序对应的。
2、StringIndexer
StringIndexer和上面的VectorIndexer类似,是将label列进行重新编号,为了便于理解,我们重新造一个数据,只看label就好了
2.1 数据
data2.txt
1 | 10,-1.0 1.0 |
读数程序和上面的一样,我们直接看一下StringIndexer代码和效果吧~
2.2 代码
1 | import org.apache.spark.ml.feature.StringIndexer |
结果
1 | +-----+----------+------------+ |
从结果一眼可以看出,该类将label重新编号了,也是从零开始,但是不是按数值(因为StringIndexer从名字上就可以看出是将string类型的转出index)大小对应,是按label出现的频次排序的,出现频次最高索引为0,依次类推,如6出现了三次则索引后为0.0。
既然提到了是将string类型的进行索引,那么简单的造个数看下效果吧,我想实际分类中字符类型的label也很多吧,比如根据特征分类胖瘦等
名字还是data2.txt吧~
1 | thin,-1.0 1.0 |
将数据替换一下,重新跑一下上面的程序
1 | +-----+----------+------------+ |
2.3 注意
利用训练好的模型还转化新来的数据,可能会碰到异常,为了简单起见,还是用上面的thin,fat,假如新来的数据的label里有既不是thin也不是fat的咋办,比如middle(只是举例)或者异常数据。
data2new.txt
1 | thin,-1.0 1.0 |
spark 提供了两种解决方法
1 | val labelIndexer = new StringIndexer() |
1、默认设置,也就是.setHandleInvalid(“error”):会抛出异常
1 | Caused by: org.apache.spark.SparkException: Unseen label: middle |
2、.setHandleInvalid(“skip”) 忽略这些label所在行的数据,正常运行,将输出如下结果:
1 | +-----+----------+------------+ |
稍微有点啰嗦,附下完整代码吧~
2.4 完整代码(供参考理解)
1 | package com.dkl.blog.spark.ml.featureprocessing |
3、IndexToString
IndexToString 的作用是将StringIndexer转化的结果转回去,实际应用中大概是这样,将字符型的label转换为数值代入算法模型训练预测,这时候预测的结果是StringIndexer转化的数值型,为了便于直观展示,需要变换回去
3.1代码
接上面2.2的代码
1 | import org.apache.spark.ml.feature.IndexToString |
3.2 结果
1 | +-----+----------+------------+--------------+ |
根据结果可以看到该类又把indexedLabel转换为和原来的label一样的类型了
4、附录
当然在实际的算法中是要将预测后的数据进行转化的,所以为了便于理解,附上一个决策树分类的代码示例,因为这篇不是讲决策树的,所以这里不展开讲解了。
4.1 数据
data3.txt
1 | thin,1.5 50 |
其中第一个特征为身高,第二个特征为体重,数据来源于:用Python开始机器学习(2:决策树分类算法),(数据是作者主观臆断,具有一定逻辑性,但请无视其合理性)
4.2 代码及结果
该代码主要来自官方示例。
1 | package com.dkl.blog.spark.ml |
结果:
因为训练数据和测试数据是随机分的,所以每次跑的结果不太一样。
1 | +--------------+-----+----------+ |
参考资料
https://blog.csdn.net/shenxiaoming77/article/details/63715525