您的位置:首页 > 其它

特征的选择_01:特征向量的切分

2017-02-07 15:57 316 查看
笔记整理时间:2017年1月11日

笔记整理者:王小草

今日记事:

发现自己普通话越来越不标准了。喜马拉雅频道放的音频有人给我留言说发音不准。难道真的写程序会退化语言功能吗。而且有的时候就是不想说话,不是性格内向而是舌头不想动了。快救我。。。咳咳咳

关于特征的选择,基于SPARK 2.1.0官方提供了3类方法:VectorSlicer,RFormula,ChiSqSelector。

我感觉Spark这样去归类文档有一点问题,有点混淆了“特征的选择”的两个概念。

1.VectorSlicer,RFormula这两个方法讲的是在你知道了要选择什么特征之后,它提供了简易的方法让你很方便地把你想要用的特征个取出来,并形成新的一组特征。注意,使用这个方法的前提是你已经知道要选择哪些特征。

2.ChiSqSelector是一种选择特征的统计学上的方法。也就是说在众多特征中,我还不知道哪些特征有用,所以可以通过卡方检验来计算每个特征对目标变量的预测能力的强度,从而根据卡方检验计算后的指标去选出最优的特征。SparkML提供的ChiSqSelector接口可以帮助我们去计算卡方检验,并且选择最优的特征。

也就是说前者提供的是一个选择特征的动作;后者提供的是选择特征的方法+动作,与模型的优化有关。

本文先介绍下VectorSlicer的用法。因为只是一个选择的动作,所以也没有什么理论可以解释,下面直接介绍如何使用这个方法和接口。

1. 特征向量的切分

VectorSlicer其实是一个转换器,输入一组特征,可以输出原特征数组的子集。

如果我们发现数据集中的特征并不是都具备预测模型的价值,或是由于一些原因(比如过多缺失值)不得不舍弃一些特征,此时我们可以直接调用这个方法选出那些我们需要的特征形成一组新的备用特征。

那么如何选择呢?每个特征都需要带有一个索引,进来一组原始的特征,根据索引选择需要的特征,然后生成新的特征集即可。索引有两类:

1.整型索引,代表特征的索引,可以通过setIndices()设置

2.字符串索引,代表特征的名称,可以用过setNames()设置。

使用时有以下注意点:

可以同时使用整型索引与字符串索引。

至少需要选择一个特征。

不能出现重复的特征。

输出的新的特征数组将会自动根据给定的索引顺序排序,先根据整型索引排序,再根据字符串索引排序。

来看个小例子:

假设我们有这样一组特征,并且是dataframe形式的:

userFeatures
------------------
[0.0, 10.0, 0.5]


上面有3个特征,但是由于第一个特征有太多缺失值所以想去掉。因此可以根据所以来选择后两个特征形成新的特征集setIndices(1, 2):

userFeatures     | features
------------------|-----------------------------
[0.0, 10.0, 0.5] | [10.0, 0.5]


假设每个特征都有名字,那么就可以通过名字来选择后两个特征setNames(“f2”, “f3”):

userFeatures     | features
------------------|-----------------------------
[0.0, 10.0, 0.5] | [10.0, 0.5]
["f1", "f2", "f3"] | ["f2", "f3"]


2. SparkML代码

官方文档的案例:

import java.util.Arrays

import org.apache.log4j.{Level, Logger}
import org.apache.spark.ml.attribute.{Attribute, AttributeGroup, NumericAttribute}
import org.apache.spark.ml.feature.VectorSlicer
import org.apache.spark.ml.linalg.Vectors
import org.apache.spark.sql.types.StructType
import org.apache.spark.{SparkConf, SparkContext}
import org.apache.spark.sql.{Row, SparkSession}

/**
* Created by cc on 17-1-11.
*/
object FeatureSelection {

def main(args: Array[String]) {

Logger.getLogger("org.apache.spark").setLevel(Level.WARN)

val conf = new SparkConf().setAppName("FeatureSelection").setMaster("local")
val sc = new SparkContext(conf)

val spark = SparkSession
.builder()
.appName("Feature Extraction")
.config("spark.some.config.option", "some-value")
.getOrCreate()

//1.VectorSlicer
// 人为创建2行3列的list,即两个样本,3个特征,第一行是用稀疏向量创建,第二行是用稠密向量创建的
val data = Arrays.asList(
Row(Vectors.sparse(3, Seq((0, -2.0), (1, 2.3)))),
Row(Vectors.dense(-2.0, 2.3, 0))
)

// 将以上list转换成带有特征名称的AttributeGroup格式的特征列
val defaultAttr = NumericAttribute.defaultAttr
val attr = Array("f1", "f2", "f3").map(defaultAttr.withName)
val attrGroup = new AttributeGroup("userFeature", attr.asInstanceOf[Array[Attribute]])

val dataSet = spark.createDataFrame(data, StructType(Array(attrGroup.toStructField())))
dataSet.show(false)

// 切分特征集
val slicer = new VectorSlicer().setInputCol("userFeature").setOutputCol("feature")
slicer.setIndices(Array(1)).setNames(Array("f3")) //根据索引或名称都可以选择

val output = slicer.transform(dataSet)
output.show(false)

spark.close()
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: