Transformer: 是一個抽象類包含特征轉換器, 和最終的學習模型, 需要實現transformer方法 通常transformer為一個RDD增加若干列, 最終轉化成另一個RDD, 1. 特征轉換器通常處理一個dataset, 把其中一列數據轉化成一列新的數據。 並且把新的數據列添加到dataset后面,產生一個新的dataset輸出。 2. 一個學習模型轉換器用來處理一個數據集, 讀取包含特征向量的那一列數據, 為每一個特征向量預測一個結果標簽, 把預測結果標簽作為一個新的數據列里添加到數據集合后面, 並且輸出結果。
Estimator: 機器學習算法抽象類, 需要實現fit()方法, fit方法會處理一個RDD, 產生一個Transformer。 例如LogistricRegression是一個Estimator, 調用fit方法訓練出來一個logistricRegressionModel對象, 這個是一個Transformer. Transformer和Estimator都是無狀態的。 每個實例都有一個唯一ID 流水線作業 機器學習領域, 普遍采用一組算法來處理和學習數據, 例如一個簡單的文本文檔處理過程包括以下幾個步驟 分詞 把文本詞轉換成數字特征向量 用特征向量和標簽訓練一個模型出來。
Spark ML可以用PipeLine表示這些過程。PipeLine是工程性質的東西, 感覺類似於工廠模式,可以把整個過程, 還有每個步驟上的transformer, estimator拼裝起來。
在spark-shell命令行里直接輸入下面的代碼, 就可以執行了。StringIndexer可以把一個屬性列里的值映射成數值類型。但是邏輯回歸分類器默認數據數據是連續的,並且是有序的, 所以StringIndexer生成的數字, 還需要進一步處理。 這里用OneHotEncoder,獨熱編碼即 One-Hot 編碼,又稱一位有效編碼,其方法是使用N位狀態寄存器來對N個狀態進行編碼,每個狀態都由他獨立的寄存器位,並且在任意時候,其中只有一位有效。
可以這樣理解,對於每一個特征,如果它有m個可能值,那么經過獨熱編碼后,就變成了m個二元特征。並且,這些特征互斥,每次只有一個激活。因此,數據會變成稀疏的。
這樣做的好處主要有:
-
解決了分類器不好處理屬性數據的問題
-
在一定程度上也起到了擴充特征的作用
import org.apache.spark.ml.feature._
import org.apache.spark.ml.classification.LogisticRegression
import org.apache.spark.mllib.linalg.{Vector, Vectors}
import org.apache.spark.mllib.regression.LabeledPoint
val df= sqlContext.createDataFrame(Seq(
(0, "a"),
(1, "b"),
(2, "c"),
(3, "a"),
(4, "a"),
(5, "c"),
(6, "d"))).toDF("id", "category")
val indexer = new StringIndexer().setInputCol("category").setOutputCol("categoryIndex").fit(df)
val indexed = indexer.transform(df)
indexed.select("category", "categoryIndex").show()
val encoder = new OneHotEncoder().setInputCol("categoryIndex").setOutputCol("categoryVec")
val encoded = encoder.transform(indexed)
val data = encoded.rdd.map { x =>
{
val featureVector = Vectors.dense(x.getAs[org.apache.spark.mllib.linalg.SparseVector]("categoryVec").toArray)
val label = x.getAs[java.lang.Integer]("id").toDouble
LabeledPoint(label, featureVector)
}
}
var result = sqlContext.createDataFrame(data)
scala> result.show()
+-----+-------------+
|label| features|
+-----+-------------+
| 0.0|[1.0,0.0,0.0]|
| 1.0|[0.0,0.0,1.0]|
| 2.0|[0.0,1.0,0.0]|
| 3.0|[1.0,0.0,0.0]|
| 4.0|[1.0,0.0,0.0]|
| 5.0|[0.0,1.0,0.0]|
| 6.0|[0.0,0.0,0.0]|
+-----+-------------+
整個features列就變成了一個稀疏矩陣。
