天天看點

Spark MLlib中的OneHot啞變量實踐

在機器學習中,線性回歸和邏輯回歸算是最基礎入門的算法,很多書籍都把他們作為第一個入門算法進行介紹。除了本身的公式之外,邏輯回歸和線性回歸還有一些必須要了解的内容。一個很常用的知識點就是虛拟變量(也叫做啞變量)—— 用于表示一些無法直接應用到線性公式中的變量(特征)。

舉個例子:

通過身高來預測體重,可以簡單的通過一個線性公式來表示,

y=ax+b

。其中x為身高,y為體重。

現在想要多加一些特征(參數),比如性别。

那麼問題來了:如何在一個公式中表示性别呢?

這就是啞變量的作用,它可以通過擴充特征值的個數來表示一些無法被直接數值化的參數。

執行個體示範

下面是一組資料,第一清單示體重,第二清單示身高,第三清單示性别

體重 身高 性别
60 170 F
45 163 M
80 183
70 175
52 167

現在首先需要把第三列轉換成數值類型

1.0
0.0

然後使用多元的資料表示這個參數

性别男 性别女

即,性别這一列會通過兩列來辨別。

一般來說,有多少種情況出現,就會出現多少列。當然會有很多不同的表現形式,比如有的是通過N-1清單示(為空時表示一種情況),有的是通過n清單示。

代碼實踐

在Spark MLlib中已經提供了處理啞變量的方法,叫做OneHotEncoder,翻譯過來叫做 一位有效編碼,即把可能出現多個值的某列轉變成多列,同時隻有一列有效。MLlib提供了兩個方法一個是

StringIndex

方法,這個方法可以把不同的字元串轉換成數值,比如

F``M

分别用

0.0``1.0

表示。還有一個是

OneHotEncoder

方法,這個方法可以把不同的數值轉變成稀疏向量。

什麼是稀疏向量

在MLlib中,向量有兩種表示方法,一種是密集向量,一種是稀疏向量。

  • 密集向量很好了解,[1,2,3,4],代表這個向量有四個元素,分别是1 2 3 4
  • 稀疏向量則可以根據下表表示,(3,[4,5,6],[1,2,3]),第一個值代表大小,第二個代表下标數組,第二個是下标對應的值。

然後話說回來,

OneHotEncoder

方法可以把不同的數值變成稀疏向量,這樣一列就相當于可以用多列來表示。

下面我們具體的看一下代碼吧!

object encoderTest {
  def main(args: Array[String]) {
    val conf = new SparkConf().setAppName("MovieLensALS-Test").setMaster("local[2]")
    val sc = new SparkContext(conf)
    sc.setLogLevel("WARN")
    val sqlContext = new SQLContext(sc)
    val df = sqlContext.createDataFrame(Seq(
      (60, 170,"F","長春"),
      (45, 163,"M","長春"),
      (80, 183,"F","沈陽"),
      (70, 175,"F","大連"),
      (52, 167,"M","哈爾濱")
    )).toDF("weight", "height","sex","address")

    //把性别這一列數值化
    val indexer = new StringIndexer()
      .setInputCol("sex")
      .setOutputCol("sexIndex")
      .fit(df)
    val indexed = indexer.transform(df)
    //對性别這列進行 有效位編碼
    val encoder = new OneHotEncoder()
      .setInputCol("sexIndex")
      .setOutputCol("sexVec")
    val encoded = encoder.transform(indexed)
    //對位址這一列數值化
    val indexer1 = new StringIndexer()
      .setInputCol("address")
      .setOutputCol("addressIndex")
      .fit(encoded)
    val indexed1 = indexer1.transform(encoded)
    //對位址進行有效位編碼
    val encoder1 = new OneHotEncoder()
      .setInputCol("addressIndex")
      .setOutputCol("addressVec")
    val encoded1 = encoder1.transform(indexed1)

    encoded1.show()
  }
}
           

輸出的内容為:

+------+------+---+-------+--------+-------------+------------+-------------+
|weight|height|sex|address|sexIndex|       sexVec|addressIndex|   addressVec|
+------+------+---+-------+--------+-------------+------------+-------------+
|    60|   170|  F|     長春|     0.0|(1,[0],[1.0])|         0.0|(3,[0],[1.0])|
|    45|   163|  M|     長春|     1.0|    (1,[],[])|         0.0|(3,[0],[1.0])|
|    80|   183|  F|     沈陽|     0.0|(1,[0],[1.0])|         3.0|    (3,[],[])|
|    70|   175|  F|     大連|     0.0|(1,[0],[1.0])|         2.0|(3,[2],[1.0])|
|    52|   167|  M|    哈爾濱|     1.0|    (1,[],[])|         1.0|(3,[1],[1.0])|
+------+------+---+-------+--------+-------------+------------+-------------+
           

這樣有什麼用呢?

得到了

weight``height``sexVec``addressVec

,就相當于得到了一組資料,基于這組資料,就可以來訓練線性回歸,得到模型後,就可以根據一個人的身高、性别、位址來預測這個人的身高了。

參考

1 MLlib OneHotEncoder官方文檔:http://spark.apache.org/docs/1.6.0/ml-features.html#onehotencoder

2 虛拟變量定義:http://wiki.mbalib.com/wiki/虛拟變量

作者:xingoo

出處:http://www.cnblogs.com/xing901022

本文版權歸作者和部落格園共有。歡迎轉載,但必須保留此段聲明,且在文章頁面明顯位置給出原文連接配接!