SparkML⼏种归⼀化(规范化)⽅法总结
规范化,有关之前都是⽤ python写的,偶然要⽤scala 进⾏写,看到这位⼤神写的,那个⽹页也不错,那个连接图做的还蛮不错的,那天也将⾃⼰的博客弄⼀下那个插件。
本⽂来源原⽂地址:/spark-ml-feature-scaler/
下⾯是⼤神写的:
org.apache.spark.ml.feature包中包含了4种不同的归⼀化⽅法:
Normalizer
StandardScaler
MinMaxScaler
MaxAbsScaler
有时感觉会容易混淆,借助官⽅⽂档和实际数据的变换,在这⾥做⼀次总结。
0 数据准备
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18import org.apache.spark.ml.linalg.Vectors
val dataFrame = ateDataFrame(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")
dataFrame.show
// 原始数据
+---+--------------+
| id| features|
+---+--------------+
| 0|[1.0,0.5,-1.0]|
| 1| [2.0,1.0,1.0]|
| 2|[4.0,10.0,2.0]|
+---+--------------+
1 Normalizer
Normalizer的作⽤范围是每⼀⾏,使每⼀个⾏向量的范数变换为⼀个单位范数,下⾯的⽰例代码都来⾃加上少量改写和注释。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21import org.apache.spark.ml.feature.Normalizer
// 正则化每个向量到1阶范数
val normalizer = new Normalizer()
.setInputCol("features")
.setOutputCol("normFeatures")
.setP(1.0)
val l1NormData = ansform(dataFrame)
println("Normalized using L^1 norm")
l1NormData.show()
// 将每⼀⾏的规整为1阶范数为1的向量,1阶范数即所有值绝对值之和。+---+--------------+------------------+
| id| features| normFeatures|
+---+--------------+------------------+
| 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]|
+---+--------------+------------------+
21
22 23 24 25 26 27 28 29 30 31 32 33 34// 正则化每个向量到⽆穷阶范数
val lInfNormData = ansform(dataFrame, normalizer.p -> Double.PositiveInfinity) println("Normalized using L^inf norm")
lInfNormData.show()
// 向量的⽆穷阶范数即向量中所有值中的最⼤值
+---+--------------+--------------+
| id| features| normFeatures|
+---+--------------+--------------+
| 0|[1.0,0.5,-1.0]|[1.0,0.5,-1.0]|
| 1| [2.0,1.0,1.0]| [1.0,0.5,0.5]|
| 2|[4.0,10.0,2.0]| [0.4,1.0,0.2]|
+---+--------------+--------------+
2 StandardScaler
StandardScaler处理的对象是每⼀列,也就是每⼀维特征,将特征标准化为单位标准差或是0均值,或是0均值单位标准差。主要有两个参数可以设置:
withStd: 默认为真。将数据标准化到单位标准差。
withMean: 默认为假。是否变换为0均值。 (此种⽅法将产出⼀个稠密输出,所以不适⽤于稀疏输⼊。) StandardScaler需要fit数据,获取每⼀维的均值和标准差,来缩放每⼀维特征。
StandardScaler是⼀个Estimator,它可以fit数据集产⽣⼀个StandardScalerModel,⽤来计算汇总统计。
然后产⽣的模可以⽤来转换向量⾄统⼀的标准差以及(或者)零均值特征。
注意如果特征的标准差为零,则该特征在向量中返回的默认值为0.0。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23import org.apache.spark.ml.feature.StandardScaler
val scaler = new StandardScaler()
.setInputCol("features")
.setOutputCol("scaledFeatures")
.setWithStd(true)
.setWithMean(false)
// Compute summary statistics by fitting the StandardScaler.
val scalerModel = scaler.fit(dataFrame)
// Normalize each feature to have unit standard deviation.
val scaledData = ansform(dataFrame)
scaledData.show
// 将每⼀列的标准差缩放到1。
+---+--------------+------------------------------------------------------------+
|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] |
+---+--------------+------------------------------------------------------------+
3 MinMaxScaler
MinMaxScaler作⽤同样是每⼀列,即每⼀维特征。将每⼀维特征线性地映射到指定的区间,通常是[0, 1]。MinMaxScaler计算数据集的汇总统计量,并产⽣⼀个MinMaxScalerModel。
注意因为零值转换后可能变为⾮零值,所以即便为稀疏输⼊,输出也可能为稠密向量。
该模型可以将独⽴的特征的值转换到指定的范围内。
它也有两个参数可以设置:
min: 默认为0。指定区间的下限。
max: 默认为1。指定区间的上限。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22import org.apache.spark.ml.feature.MinMaxScaler
val scaler = new MinMaxScaler()
.setInputCol("features")
.setOutputCol("scaledFeatures")
// Compute summary statistics and generate MinMaxScalerModel
val scalerModel = scaler.fit(dataFrame)
// rescale each feature to range [min, max].
val scaledData = ansform(dataFrame)
println(s"Features scaled to range: [${Min}, ${Max}]") scaledData.select("features", "scaledFeatures").show
// 每维特征线性地映射,最⼩值映射到0,最⼤值映射到1。
+--------------+-----------------------------------------------------------+
|features |scaledFeatures |
+--------------+-----------------------------------------------------------+
|[1.0,0.5,-1.0]|[0.0,0.0,0.0] |
|[2.0,1.0,1.0] |[0.3333333333333333,0.05263157894736842,0.6666666666666666]| |[4.0,10.0,2.0]|[1.0,1.0,1.0] |
+--------------+-----------------------------------------------------------+
4 MaxAbsScaler
MaxAbsScaler将每⼀维的特征变换到[-1, 1]闭区间上,通过除以每⼀维特征上的最⼤的绝对值,它不会
平移整个分布,也不会破坏原来每⼀个特征向量的稀疏性。
因为它不会转移/集中数据,所以不会破坏数据的稀疏性。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21import org.apache.spark.ml.feature.MaxAbsScaler
val scaler = new MaxAbsScaler()
.setInputCol("features")
.setOutputCol("scaledFeatures")
// Compute summary statistics and generate MaxAbsScalerModel val scalerModel = scaler.fit(dataFrame)
// rescale each feature to range [-1, 1]
val scaledData = ansform(dataFrame) scaledData.select("features", "scaledFeatures").show()
/
/ 每⼀维的绝对值的最⼤值为[4, 10, 2]
+--------------+----------------+
| features| scaledFeatures|
+--------------+----------------+
|[1.0,0.5,-1.0]|[0.25,0.05,-0.5]|
| [2.0,1.0,1.0]| [0.5,0.1,0.5]|
|[4.0,10.0,2.0]| [1.0,1.0,1.0]|
+--------------+----------------+
总结
所有4种归⼀化⽅法都是线性的变换,当某⼀维特征上具有⾮线性的分布时,还需要配合其它的特征预处理⽅法。
补充:
其他特征转换
VectorIndexer
算法介绍:
VectorIndexer解决数据集中的类别特征Vector。它可以⾃动识别哪些特征是类别型的,并且将原始值转换为类别指标。它的处理流程如下:
1.获得⼀个向量类型的输⼊以及maxCategories参数。
2.基于原始数值识别哪些特征需要被类别化,其中最多maxCategories需要被类别化。
3.对于每⼀个类别特征计算0-based类别指标。
4.对类别特征进⾏索引然后将原始值转换为指标。
索引后的类别特征可以帮助决策树等算法处理类别型特征,并得到较好结果。
在下⾯的例⼦中,我们读⼊⼀个数据集,然后使⽤VectorIndexer来决定哪些特征需要被作为⾮数值类型处理,将⾮数值型特征转换为他们的索引。
调⽤⽰例:
Scala:
1. import org.apache.spark.ml.feature.VectorIndexer
2.
3. val data = ad.format("libsvm").load("data/mllib/sample_")
4.
5. val indexer = new VectorIndexer()
6.  .setInputCol("features")
7.  .setOutputCol("indexed")
8.  .setMaxCategories(10)
9.
10. val indexerModel = indexer.fit(data)
11.
12. val categoricalFeatures: Set[Int] = indexerModel.Set
13. println(s"Chose ${categoricalFeatures.size} categorical features: " +
14.  categoricalFeatures.mkString(", "))
15.
16. // Create new column "indexed" with categorical values transformed to indices
17. val indexedData = ansform(data)
18. indexedData.show()
Python:
1.  from pyspark.ml.feature import VectorIndexer
2.
3. data = ad.format("libsvm").load("data/mllib/sample_")
4. indexer = VectorIndexer(inputCol="features", outputCol="indexed", maxCategories=10)
5. indexerModel = indexer.fit(data)
6.
7. # Create new column "indexed" with categorical values transformed to indices
8. indexedData = ansform(data)
9. indexedData.show()
ElementwiseProduct
算法介绍:
ElementwiseProduct按提供的“weight”向量,返回与输⼊向量元素级别的乘积。即是说,按提供的权重分别对输⼊数据进⾏缩放,得到输⼊向量v以及权重向量w的Hadamard积。
下⾯例⼦展⽰如何通过转换向量的值来调整向量。
调⽤⽰例:
Scala:
1. import org.apache.spark.ml.feature.ElementwiseProduct
2. import org.apache.spark.ml.linalg.Vectors
3.
4. // Create some vector data; also works for sparse vectors
5. val dataFrame = ateDataFrame(Seq(
6.  ("a", Vectors.dense(1.0, 2.0, 3.0)),
7.  ("b", Vectors.dense(4.0, 5.0, 6.0)))).toDF("id", "vector")
8.
9. val transformingVector = Vectors.dense(0.0, 1.0, 2.0)
10. val transformer = new ElementwiseProduct()
11.  .setScalingVec(transformingVector)
12.  .setInputCol("vector")
13.  .setOutputCol("transformedVector")
14.
15. // Batch transform the vectors to create new column:
16. ansform(dataFrame).show()
Python:
1. from pyspark.ml.feature import ElementwiseProduct
2. from pyspark.ml.linalg import Vectors
3.
4. # Create some vector data; also works for sparse vectors
5. data = [(Vectors.dense([1.0, 2.0, 3.0]),), (Vectors.dense([4.0, 5.0,
6.0]),)]
6. df = ateDataFrame(data, ["vector"])
7. transformer = ElementwiseProduct(scalingVec=Vectors.dense([0.0, 1.0, 2.0]),
8.                                  inputCol="vector", outputCol="transformedVector")
9. # Batch transform the vectors to create new column:
10. ansform(df).show()
SQLTransformer
算法介绍:
正则化 归一化
SQLTransformer⼯具⽤来转换由SQL定义的陈述。⽬前仅⽀持SQL语法如"SELECT ...FROM __THIS__ ...",其中"__THIS__"代表输⼊数据的基础表。选择语句指定输出中展⽰的字段、元素和表达式,⽀持Spark SQL中的所有选择语句。⽤户可以基于选择结果使⽤Spark SQL建⽴⽅程或者⽤户⾃定义函数。SQLTransformer⽀持语法⽰例如下:
1. SELECTa, a + b AS a_b FROM __THIS__
2. SELECTa, SQRT(b) AS b_sqrt FROM __THIS__ where a > 5
3. SELECTa, b, SUM(c) AS c_sum FROM __THIS__ GROUP BY a, b
⽰例:
假设我们有如下DataFrame包含id,v1,v2列:
id |  v1 |  v2
----|-----|-----
0  | 1.0 | 3.0
2  | 2.0 | 5.0

版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。