Spark:特征处理之数据标准化

数据标准化

先定义一个df

import org.apache.spark.ml.linalg.Vectors
val df = spark.createDataFrame(Seq(
  (0, Vectors.dense(1.0, 0.5, -1.0)),
  (1, Vectors.dense(2.0, 1.0, 1.0)),
  (2, Vectors.dense(4.0, 10.0, 2.0))
)).toDF("id", "features")
df.show
+---+--------------+
| id|      features|
+---+--------------+
|  0|[1.0,0.5,-1.0]|
|  1| [2.0,1.0,1.0]|
|  2|[4.0,10.0,2.0]|
+---+--------------+

再介绍四种数据标准化方法

Normalizer(行缩放)

处理的对象是每一行,也就是每一组特征:将行向量的范数变换为单位范数(范数的阶通过参数指定)。
变换前后向量方向不变,也就是向量各维度的比例不变。
实际就是将每一组行向量的各个维度除以其指定阶的范数值(缩放)。
如其中一组行向量为[a, b, c],它的n阶范数值为m,则用setP(n)设置参数后,标准化得到向量[a/m, b/m, c/m]。

import org.apache.spark.ml.feature.Normalizer
//正则化行向量的1阶范数为一个单位,向量的1阶范数等于向量每个维度的绝对值的和。
//默认为2阶范数。即所有维度的平方和再开方的值。(欧几里德距离)
val normalizer = new Normalizer()
  .setInputCol("features")
  .setOutputCol("normFeature")
  .setP(1) 
normalizer.transform(df).show
+---+--------------+------------------+
| id|      features|       normFeature|
+---+--------------+------------------+
|  0|[1.0,0.5,-1.0]|    [0.4,0.2,-0.4]|
|  1| [2.0,1.0,1.0]|   [0.5,0.25,0.25]|
|  2|[4.0,10.0,2.0]|[0.25,0.625,0.125]|
+---+--------------+------------------+ 

补充:

  • 向量n阶范数等于向量各维度的绝对值的n次方之和,再开n次方。
  • 正无穷范数等于向量各维度绝对值的最大值,负无穷范数等于各维度绝对值最小值。

StandardScaler(列缩放、平移)

处理的对象是每一列,也就是每一维特征:将每一维的特征列向量标准化为样本标准差为1,或者平均值为0。
这里求样本标准差的公式为:
s=1n1i=1n(xixˉ)2s = \sqrt {\dfrac 1{n-1} \sum_{i=1}^n{(x_i - \bar x )^2}}

主要有两个参数可以设置:

  • withStd: 默认为true。将数据标准化到单位标准差。
    实际就是将每维特征的各特征值除以这一维特征的标准差(缩放)。
    如其中一组特征列向量为[a, b, c],它的样本标准差为m,则用setWithStd(true)设置参数后,标准化得到向量[a/m, b/m, c/m]。

  • withMean: 默认为false。是否变换为0均值。
    实际就是将每维特征的各特征值减去这一维特征的平均值(平移)。
    如其中一组特征列向量为[a, b, c],它的平均值为m,则用用setWithMean(true)设置参数后,标准化得到向量[a-m, b-m, c-m]。

若两个参数都设置为true,则可以先平移再缩放(因为平移不会改变样本的标准差)。
StandardScaler需要fit数据,获取每一维的均值和标准差,再变换每一维的特征。

import org.apache.spark.ml.feature.StandardScaler
val scaler = new StandardScaler()
  .setInputCol("features")
  .setOutputCol("scaledFeatures")
  .setWithStd(true)
  .setWithMean(false)
val scalerModel = scaler.fit(df)
scalerModel.transform(df).show(false)
+---+--------------+------------------------------------------------------------+
|id |features      |scaledFeatures                                              |
+---+--------------+------------------------------------------------------------+
|0  |[1.0,0.5,-1.0]|[0.6546536707079772,0.09352195295828244,-0.6546536707079771]|
|1  |[2.0,1.0,1.0] |[1.3093073414159544,0.1870439059165649,0.6546536707079771]  |
|2  |[4.0,10.0,2.0]|[2.618614682831909,1.870439059165649,1.3093073414159542]    |
+---+--------------+------------------------------------------------------------+

MinMaxScaler(列先缩放后平移)

处理的对象是每一列:将每一维特征线性地映射到指定的区间,默认是[0, 1]。
实际就是将每维特征的各特征值进行先缩放再平移,缩放比例是原向量的跨度(最大值减最小值)除以(max-min),平移距离为缩放完之后所得中间向量的元素最小值减去min。

主要有两个参数可以设置:

  • min: 默认为0。指定区间的下限。
  • max: 默认为1。指定区间的上限。

需要fit数据,获取每一维的最大值和最小值,再变换每一维的特征。

import org.apache.spark.ml.feature.MinMaxScaler
val scaler = new MinMaxScaler()
  .setInputCol("features")
  .setOutputCol("scaledFeatures")
  .setMin(0)
  .setMax(1)
val scalerModel = scaler.fit(df)
scalerModel.transform(df).show(false)
+---+--------------+-----------------------------------------------------------+
|id |features      |scaledFeatures                                             |
+---+--------------+-----------------------------------------------------------+
|0  |[1.0,0.5,-1.0]|[0.0,0.0,0.0]                                              |
|1  |[2.0,1.0,1.0] |[0.3333333333333333,0.05263157894736842,0.6666666666666666]|
|2  |[4.0,10.0,2.0]|[1.0,1.0,1.0]                                              |
+---+--------------+-----------------------------------------------------------+

MaxAbsScaler(列缩放)

处理的对象是每一列:将每一维的特征线性变换到[-1, 1]闭区间上。
实际就是通过将每一维特征值除以列向量上的最大值的绝对值(缩放),它不会平移,所以不会破坏原来每一组行特征向量的稀疏性。
此变换没有额外参数,需要fit数据,获取每一维的最大值,再变换每一维的特征。

import org.apache.spark.ml.feature.MaxAbsScaler
val scaler = new MaxAbsScaler()
  .setInputCol("features")
  .setOutputCol("scaledFeatures")
val scalerModel = scaler.fit(df)
scalerModel.transform(df).show(false)
+---+--------------+----------------+
|id |features      |scaledFeatures  |
+---+--------------+----------------+
|0  |[1.0,0.5,-1.0]|[0.25,0.05,-0.5]|
|1  |[2.0,1.0,1.0] |[0.5,0.1,0.5]   |
|2  |[4.0,10.0,2.0]|[1.0,1.0,1.0]   |
+---+--------------+----------------+
posted @ 2019-01-04 17:25  xuejianbest  阅读(1171)  评论(0编辑  收藏  举报