特征处理1_StringIndexer与OneHotEncoder
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了特征处理1_StringIndexer与OneHotEncoder相关的知识,希望对你有一定的参考价值。
参考技术A 字符串-索引变换,就是将某些标签的字符串列编号变成标签索引项。标签索引项序列的取值范围就是
[0,numLabels](这里的numLabels是所有出现的单词去掉重复的词后的总和)。
这里的标签索引项顺序就是按照标签出现的频率来排序的,出现最多的标签索引就是0(倒序)。
如果输入是数值型,先将数值映射到字符串,再对字符串进行索引化 。
与StringIndexer对应,IndexToString是将索引化标签还原成原始的字符串。
使用场景:在通过StringIndexer产生索引化标签,然后使用索引化标签进行训练,最后对预测结果使用IndexToString来获取其原始的标签字符串。
结果显示:
StringIndexer还有一个setHandleInvalid()的方法,通常是因为构建了一个StringIndexer实例,对DataFrame1进行fit后,再对DataFrame2进行transform,DataFrame2中出现了DataFrame1中未曾出现的标签,这时候可以通过设置setHandleInvalid(“skip”)来忽略新标签的行;
当然setHandleInvalid(“keep”)则保留。
不过奇怪的是,在实际工作中,发现fit和transform同一个Dataframe时,也有可能报这个错
可以将离散特征通过one-hot编码映射到欧式空间,而我们常用的距离或相似度的计算都是基于欧式空间的。
将一列标签索引映射到一列二进制向量,最多只会有一个单值(只有一个1)。
如果是有4个标签索引:1,2,3,4
那么对应的One-hot为[1,0,0,0],[0,1,0,0],[0,0,1,0],[0,0,0,1]
结果显示:
注意:有一个方法 setDropLast,是否丢弃最后一个数,默认为true,观察上面的结果发现categoryIndex最大的2.0,经过OneHot得到的categoryVec为(2,[],[]),最大的categoryIndex被丢弃了。
不过在设置setDropLast(false)后,
Spark ml pipeline - transforming feature - StringIndexer
在spark ml pipeline的特征提取和转换阶段,有一种transformer可以将机器学习训练数据中常见的字符串列(例如表示各种分类)转换为数值索引列,以便于计算机处理。它就是StringIndexer。它支持的索引范围为[0, numLabels)(不支持的会编码为numLabels),并且支持四种排序方式,frequencyDesc(频率最高的索引赋值为0),frequencyAsc,alphabetDesc,alphabetAsc。
假设我们有dataframe
id | category ----|---------- 0 | a 1 | b 2 | c 3 | a 4 | a 5 | c
应用索引器 将category作为input 将categoryIndex作为output
id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 2 | c | 1.0 3 | a | 0.0 4 | a | 0.0 5 | c | 1.0
“a” gets index 0
because it is the most frequent, followed by “c” with index 1
and “b” with index 2
.
当StringIndexer遇到之前没有处理过的字符串时,对于新数据有三种处理策略
- 抛出异常 (默认)
- 跳过当前行
- 放置未知标签
如果我们使用之前生成的StringIndexer 应用于以下数据
id | category ----|---------- 0 | a 1 | b 2 | c 3 | d 4 | e
如果没有设置未知策略,或者设置为error策略,都会抛出异常,然后如果设置过setHandleInvalid("skip") 将会跳过d,e所在行
id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 2 | c | 1.0
如果调用setHandleInvalid("keep") 将会生成如下数据
id | category | categoryIndex ----|----------|--------------- 0 | a | 0.0 1 | b | 2.0 2 | c | 1.0 3 | d | 3.0 4 | e | 3.0
注意: “d” or “e” 所在行 都被映射为索引 “3.0”, keep设置了未知编码,而不是继续编码
scala代码示例:
import org.apache.spark.ml.feature.StringIndexer
//创建表 val df = spark.createDataFrame( Seq((0, "a"), (1, "b"), (2, "c"), (3, "a"), (4, "a"), (5, "c")) ).toDF("id", "category")
//创建新列索引器 val indexer = new StringIndexer() .setInputCol("category") .setOutputCol("categoryIndex")
//先fit让indexer编码df索引 然后对某一个表进行转换 这里还是本身 不会抛出异常 或者跳过 val indexed = indexer.fit(df).transform(df) indexed.show()
详细API见文档 https://spark.apache.org/docs/latest/api/scala/index.html#org.apache.spark.ml.feature.StringIndexer
ref: https://spark.apache.org/docs/latest/ml-features.html#stringindexer
以上是关于特征处理1_StringIndexer与OneHotEncoder的主要内容,如果未能解决你的问题,请参考以下文章
Spark2.0 特征提取转换选择之二:特征选择文本处理,以中文自然语言处理(情感分类)为例
spark过滤算子+StringIndexer算子出发的一个逻辑bug