Extracting, transforming and selecting features - spark.ml

本节介绍了处理功能的算法,大致分为以下几组:


提取:从“原始”数据提取特征
转换:缩放,转换或修改要素

选择:从一组较大的要素中选择一个子集


Feature Extractors

TF-IDF (HashingTF and IDF)

字词的重要性随着它在文件中出现的次数成正比增加 ,但同时会 随着它在语料库中出现的频率成反比下降
词频率-逆文档频率(TF-IDF)是常见的文本预处理步骤。 在Spark ML中,TF-IDF分为两部分:TF(+hasing)和IDF。

TF:HashingTF是一个transfor,它使用term的集合并将这些集合转换成固定长度的特征向量。 在文本处理中,“一组term”可能是一组词的结合。 该算法将term频率(TF)计数与用于降维的散列技巧组合。

IDF:IDF是一种作用于数据集(fit method)并生成IDFModel的估计器。 IDFModel取特征向量(通常由HashingTF创建)并缩放每个列。 直观地,它会降低在语料库中频繁出现的列的权重。

在下面的代码段中,我们从一组句子开始。 我们使用Tokenizer将每个句子分成单词。 对于每个句子(词袋),我们使用HashingTF将句子散列成特征向量。 我们使用IDF重新缩放特征向量; 这通常会提高使用文本作为功能时的性能。 然后我们的特征向量可以被传递到学习算法。

Word2Vec

每个文本都是根据文本中的词生成的一个向量,可以用于预测,文本相似度。。。

CountVectorizer

用向量表示文档中每个词出现的次数

id | texts                           | vector
----|---------------------------------|---------------
 0  | Array("a", "b", "c")            | (3,[0,1,2],[1.0,1.0,1.0])
 1  | Array("a", "b", "b", "c", "a")  | (3,[0,1,2],[2.0,2.0,1.0])

Feature Transformers

Tokenizer

就是按照各种姿势分词
标记化是获取文本(例如句子)并将其分解成单个术语(通常是单词)的过程。 一个简单的Tokenizer类提供了这个功能。 下面的例子显示了如何将句子分成单词序列。

RegexTokenizer允许基于正则表达式(regex)匹配的更高级的符号化。 默认情况下,参数“pattern”(regex,default:\ s +)用作分隔符以分隔输入文本。 或者,用户可以将参数“gap”设置为false,指示正则表达式“模式”表示“令牌”,而不是分割间隙,并且找到所有匹配的出现作为令牌化结果。

import org.apache.spark.ml.feature.{RegexTokenizer, Tokenizer}

val sentenceDataFrame = sqlContext.createDataFrame(Seq(
  (0, "Hi I heard about Spark"),
  (1, "I wish Java could use case classes"),
  (2, "Logistic,regression,models,are,neat")
)).toDF("label", "sentence")

val tokenizer = new Tokenizer().setInputCol("sentence").setOutputCol("words")
val regexTokenizer = new RegexTokenizer()
  .setInputCol("sentence")
  .setOutputCol("words")
  .setPattern("\\W") // alternatively .setPattern("\\w+").setGaps(false)

val tokenized = tokenizer.transform(sentenceDataFrame)
tokenized.select("words", "label").take(3).foreach(println)
val regexTokenized = regexTokenizer.transform(sentenceDataFrame)
regexTokenized.select("words", "label").take(3).foreach(println)

StopWordsRemover

移除停用词

Examples

Assume that we have the following DataFrame with columns id and raw:

 id | raw
----|----------
 0  | [I, saw, the, red, baloon]
 1  | [Mary, had, a, little, lamb]

Applying StopWordsRemover with raw as the input column and filtered as the output column, we should get the following:

 id | raw                         | filtered
----|-----------------------------|--------------------
 0  | [I, saw, the, red, baloon]  |  [saw, red, baloon]
 1  | [Mary, had, a, little, lamb]|[Mary, little, lamb]

In filtered, the stop words “I”, “the”, “had”, and “a” have been filtered out.


n-gram

该模型基于这样一种假设,第n个词的出现只与前面N-1个词相关,而与其它任何词都不相关,整句的概率就是各个词出现概率的乘积。这些概率可以通过直接从语料中统计N个词同时出现的次数得到。常用的是二元的Bi-Gram和三元的Tri-Gram。

NGram将字符串序列(例如,Tokenizer的输出)作为输入。 参数n用于确定每个nn-gram中的项的数量。 输出将包括一个nn-gram序列,其中每个n-gram由nn个连续字的空格分隔的字符串表示。 如果输入序列包含少于n个字符串,则不会生成输出。

Binarizer

二值化是将数字特征阈值为二进制(0/1)特征的过程。
Binarizer接受通用参数inputCol和outputCol以及二进制阈值。 大于阈值的特征值被二进制化为1.0; 等于或小于阈值的值被二进制化为0.0。

import org.apache.spark.ml.feature.Binarizer

val data = Array((0, 0.1), (1, 0.8), (2, 0.2))
val dataFrame: DataFrame = sqlContext.createDataFrame(data).toDF("label", "feature")

val binarizer: Binarizer = new Binarizer()
  .setInputCol("feature")
  .setOutputCol("binarized_feature")
  .setThreshold(0.5)

val binarizedDataFrame = binarizer.transform(dataFrame)
val binarizedFeatures = binarizedDataFrame.select("binarized_feature")
binarizedFeatures.collect().foreach(println)

PCA

用来降低维度

PCA是一种统计过程,其使用正交变换将可能相关的变量的观察值的集合转换成称为主分量的线性不相关变量的值的集合。 PCA类训练模型使用PCA将向量投影到低维空间。 下面的示例显示了如何将5维特征向量投影到3维主成分中。

import org.apache.spark.ml.feature.PCA
import org.apache.spark.mllib.linalg.Vectors

val data = 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)
)
val df = sqlContext.createDataFrame(data.map(Tuple1.apply)).toDF("features")
val pca = new PCA()
  .setInputCol("features")
  .setOutputCol("pcaFeatures")
  .setK(3)
  .fit(df)
val pcaDF = pca.transform(df)
val result = pcaDF.select("pcaFeatures")
result.show()

PolynomialExpansion

多项式扩展

多项式展开是将特征扩展到多项式空间的过程,该多项式空间由原始尺寸的n度组合表示。 PolynomialExpansion类提供此功能。 下面的示例显示了如何将您的要素扩展到3度多项式空间。

Discrete Cosine Transform (DCT)

离散余弦变换(DCT)压缩算法,降低空间冗余度


StringIndexer

根据某个列生成index,比如category

StringIndexer将标签的字符串列编码为标签索引列。 索引在[0,numLabels)中,按标签频率排序。 因此,最常见的标签获取索引0.如果输入列是数字,我们将其转换为字符串并索引字符串值。 当下游管道组件(例如Estimator或Transformer)使用此字符串索引标签时,必须将组件的输入列设置为此字符串索引的列名称。 在许多情况下,可以使用setInputCol设置输入列。

Examples

Assume that we have the following DataFrame with columns id and category:

 id | category
----|----------
 0  | a
 1  | b
 2  | c
 3  | a
 4  | a
 5  | c

category is a string column with three labels: “a”, “b”, and “c”. Applying StringIndexer with category as the input column and categoryIndex as the output column, we should get the following:

 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在一个数据集上,然后使用它来转换另一个:


抛出异常(这是默认值)
请完全跳过包含未看见标签的行

Examples

Let’s go back to our previous example but this time reuse our previously defined StringIndexer on the following dataset:

 id | category
----|----------
 0  | a
 1  | b
 2  | c
 3  | d

If you’ve not set how StringIndexer handles unseen labels or set it to “error”, an exception will be thrown. However, if you had called setHandleInvalid("skip"), the following dataset will be generated:

 id | category | categoryIndex
----|----------|---------------
 0  | a        | 0.0
 1  | b        | 2.0
 2  | c        | 1.0

Notice that the row containing “d” does not appear.

import org.apache.spark.ml.feature.StringIndexer

val df = sqlContext.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")

val indexed = indexer.fit(df).transform(df)
indexed.show()

IndexToString

对称到StringIndexer,IndexToString将一列标签索引映射回包含原始标签的列作为字符串。 常见的用例是使用StringIndexer从标签生成索引,使用这些索引训练模型,并使用IndexToString从预测索引列中检索原始标签。 但是,您可以自由提供您自己的标签。

把index转换成之前的string category


Examples

Building on the StringIndexer example, let’s assume we have the following DataFrame with columns id and categoryIndex:

 id | categoryIndex
----|---------------
 0  | 0.0
 1  | 2.0
 2  | 1.0
 3  | 0.0
 4  | 0.0
 5  | 1.0

Applying IndexToString with categoryIndex as the input column, originalCategory as the output column, we are able to retrieve our original labels (they will be inferred from the columns’ metadata):

 id | categoryIndex | originalCategory
----|---------------|-----------------
 0  | 0.0           | a
 1  | 2.0           | b
 2  | 1.0           | c
 3  | 0.0           | a
 4  | 0.0           | a
 5  | 1.0           | c

OneHotEncoder

单热编码将一列标签索引映射到二进制向量列,最多具有单个一值。 此编码允许期望连续特征(例如逻辑回归)的算法使用分类特征

将前面的stringindex 转变成 向量

VectorIndexer

VectorIndexer帮助索引矢量数据集中的分类特征。 它可以自动决定哪些特征是分类的,并将原始值转换为类别索引。 具体来说,它执行以下操作:
取一个Vector类型的输入列和一个参数maxCategories。
基于不同值的数量确定哪些特征应是分类的,其中最多maxCategories的特征被声明为分类。
为每个分类特征计算基于0的类别索引。
索引分类特征并将原始特征值转换为索引。

在下面的例子中,我们读取一个标记点的数据集,然后使用VectorIndexer来决定哪些特征应该被视为分类。 我们将分类特征值转换为它们的索引。 然后,该转换的数据可以传递到诸如DecisionTreeRegressor的处理分类特征的算法。

Normalizer

StandardScaler

MinMaxScaler

上面3个对特征进行规范化就是,可以限定范围什么的

ElementwiseProduct

就是向量乘法
mport org.apache.spark.ml.feature.ElementwiseProduct
import org.apache.spark.mllib.linalg.Vectors

// Create some vector data; also works for sparse vectors
val dataFrame = sqlContext.createDataFrame(Seq(
  ("a", Vectors.dense(1.0, 2.0, 3.0)),
  ("b", Vectors.dense(4.0, 5.0, 6.0)))).toDF("id", "vector")

val transformingVector = Vectors.dense(0.0, 1.0, 2.0)
val transformer = new ElementwiseProduct()
  .setScalingVec(transformingVector)
  .setInputCol("vector")
  .setOutputCol("transformedVector")

// Batch transform the vectors to create new column:
transformer.transform(dataFrame).show()

Bucketizer

对一个列的值就行分段,比如一个age,按照年龄划分区间
import org.apache.spark.ml.feature.Bucketizer

val splits = Array(Double.NegativeInfinity, -0.5, 0.0, 0.5, Double.PositiveInfinity)

val data = Array(-0.5, -0.3, 0.0, 0.2)
val dataFrame = sqlContext.createDataFrame(data.map(Tuple1.apply)).toDF("features")

val bucketizer = new Bucketizer()
  .setInputCol("features")
  .setOutputCol("bucketedFeatures")
  .setSplits(splits)

// Transform original data into its bucket index.
val bucketedData = bucketizer.transform(dataFrame)
bucketedData.show()

SQLTransformer

可以直接写sql语句,感觉没什么用

Assume that we have the following DataFrame with columns idv1 and v2:

 id |  v1 |  v2
----|-----|-----
 0  | 1.0 | 3.0  
 2  | 2.0 | 5.0

This is the output of the SQLTransformer with statement "SELECT *, (v1 + v2) AS v3, (v1 * v2) AS v4 FROM __THIS__":

 id |  v1 |  v2 |  v3 |  v4
----|-----|-----|-----|-----
 0  | 1.0 | 3.0 | 4.0 | 3.0
 2  | 2.0 | 5.0 | 7.0 |10.0

Refer to the SQLTransformer Scala docs for more details on the API.

import org.apache.spark.ml.feature.SQLTransformer

val df = sqlContext.createDataFrame(
  Seq((0, 1.0, 3.0), (2, 2.0, 5.0))).toDF("id", "v1", "v2")

val sqlTrans = new SQLTransformer().setStatement(
  "SELECT *, (v1 + v2) AS v3, (v1 * v2) AS v4 FROM __THIS__")

sqlTrans.transform(df).show()

VectorAssembler

logistic regression and decision trees
VectorAssembler是一个变换器,它将给定的列列表组合成一个单一的向量列。 它有用于将由不同特征变换器生成的原始特征和特征组合成单个特征向量,以便训练ML模型,如逻辑回归和决策树。 VectorAssembler接受以下输入列类型:所有数字类型,布尔类型和向量类型。 在每一行中,输入列的值将以指定的顺序连接到向量中。
就是讲多个列的值,合并成一个向量

QuantileDiscretizer

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

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




Feature Selectors

VectorSlicer

就是从原向量列中提取子向量

RFormula

线性预测,将多个column变成向量,如果colum的值是string,会被one-hot-encoder

ChiSqSelector

卡方独立检验

从特征向量中提取最具有预测能力的特征值





  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值