https://www.deeplearn.me/1393.html
啞編碼概念
先來講解下啞編碼的概念吧,當你的變量不是定量特征的時候是無法拿去進行訓練模型的,啞編碼主要是針對定性的特征進行處理然后得到可以用來訓練的特征
關於定性和定量還是在這里也說明下,舉個例子就可以看懂了
定性:
博主很胖
博主很瘦
定量
博主有 80kg
博主有 60kg(ps:好難啊)
一般定性都會有相關的描述詞,定量的描述都是可以用數字來量化處理
現在假設給你的一個病人的病情描述,一般病情的描述包含以下幾個方面,將病情嚴重程度划分:
非常嚴重,嚴重,一般嚴重,輕微
現在有個病人過來了,要為他構造一個病情的特征,假設他的病情是嚴重情況,我們可以給他的啞編碼是
0 1 0 0
病情總共有四種情況因此使用四位來表示,第二位表示嚴重,這位病人是嚴重的病情因此將其置為 1,其余為 0
以上就是啞編碼的原理,看完這個解釋應該可以理解了,如果還是看不懂,我逃/(ㄒoㄒ)/~~
sklearn 代碼剖析
- from sklearn.preprocessing import OneHotEncoder
- enc = OneHotEncoder()
- enc.fit([[1, 1, 4], [2, 2, 1], [1, 3, 2], [2, 1, 3]])
- print enc.n_values_
- print enc.feature_indices_
- print enc.transform([[1, 1, 4], [2, 2, 1], [1, 3, 2], [2, 1, 3]])
- print enc.transform([[1, 2, 2]]).toarray()
輸出的結果
- #輸出 3,4,5 分別表示當前該維特征有三種、4 種和 5 種情況,案例只有 2,3,4,該問題可以看下一段解釋
- [3 4 5]
- #表示每個特征的啞編碼的索引范圍
- [ 0 3 7 12]
- #返回啞編碼的縮減版說明,舉個例子說明一下,(0,8)表示索引 0 和 8 1.0 表示在這兩個索引的數據都是 1
- (0, 8) 1.0
- (0, 2) 1.0
- (0, 0) 1.0
- (1, 5) 1.0
- (1, 3) 1.0
- (1, 1) 1.0
- (2, 6) 1.0
- (2, 4) 1.0
- (2, 0) 1.0
- (3, 7) 1.0
- (3, 2) 1.0
- (3, 1) 1.0
- [[ 1. 0. 0. 1. 0. 0. 1. 0. 0.]]
啞編碼的大小說明
- def _fit_transform(self, X):
- """Assumes X contains only categorical features."""
- X = check_array(X, dtype=np.int)
- if np.any(X < 0):
- raise ValueError("X needs to contain only non-negative integers.")
- n_samples, n_features = X.shape
- #這一步就是比較關鍵啦,我們傳入的參數是 auto,此時他會尋找特征列的最大值然后對其加 1 處理
- #然后將數據返回給 n_values,這就是我們剛才看到的數據 3,4,5,雖然我們第一維特征數字只有 1 和 2,但是取最大值加 1 就變為 3 了
- #這也就解釋了出現這種情況的原因,看到這里就頓悟了,遇到問題還是可以看看源碼,這樣可以理解的前提是代碼還是簡單點
- if (isinstance(self.n_values, six.string_types) and self.n_values == 'auto'):
- n_values = np.max(X, axis=0) + 1
- elif isinstance(self.n_values, numbers.Integral):
- if (np.max(X, axis=0) >= self.n_values).any():
- raise ValueError("Feature out of bounds for n_values=%d" % self.n_values)
- n_values = np.empty(n_features, dtype=np.int)
- n_values.fill(self.n_values)
- else:
- try:
- n_values = np.asarray(self.n_values, dtype=int)
- except (ValueError, TypeError):
- raise TypeError("Wrong type for parameter `n_values`. Expected"
- " 'auto', int or array of ints, got %r" % type(X))
- if n_values.ndim < 1 or n_values.shape[0] != X.shape[1]:
- raise ValueError("Shape mismatch: if n_values is an array,"" it has to be of shape (n_features,).")
- self.n_values_ = n_values
spark 代碼剖析
- <em class="property">class </em><tt class="descclassname">pyspark.ml.feature.</tt><tt class="descname">OneHotEncoder</tt><big>(</big><em>self</em>, <em>includeFirst=True</em>, <em>inputCol=None</em>, <em>outputCol=None</em><big>)</big>
- #不得不說 spark ml 受 sklearn 啟發,基本上二者的 api 定義基本一致,不過這樣也好,基本上記住其中一個,另外一個基本上套着用
- >>> from pyspark.ml.feature import StringIndexer
- >>> from pyspark.ml.feature import OneHotEncoder
- >>> from pyspark.sql import SQLContext
- >>> sq=SQLContext(sc)
- >>> data=sq.createDataFrame([(1, 1, 4),(2, 2, 1),(2, 1, 3),(3,4,5)], ["a","b","c"])
- >>> strmodel=StringIndexer(inputCol='a',outputCol='features')
- >>> model=strmodel.fit(data)
- >>> tdd=model.transform(data)
- >>> tdd.show()
- +---+---+---+--------+
- | a| b| c|features|
- +---+---+---+--------+
- | 1| 1| 4| 2.0|
- | 2| 2| 1| 0.0|
- | 2| 1| 3| 0.0|
- | 3| 4| 5| 1.0|
- +---+---+---+--------+
- >>> encoder = OneHotEncoder(inputCol="features", outputCol="feature")
- >>> aa=encoder.transform(tdd).show()
- +---+---+---+--------+-------------+
- | a| b| c|features| feature|
- +---+---+---+--------+-------------+
- | 1| 1| 4| 2.0| (2,[],[])|
- | 2| 2| 1| 0.0|(2,[0],[1.0])|
- | 2| 1| 3| 0.0|(2,[0],[1.0])|
- | 3| 4| 5| 1.0|(2,[1],[1.0])|
- +---+---+---+--------+-------------+
- #此時發現為什么 a 列有三類結果只顯示兩類,因為 spark 默認忽略了最后一位,現在我們
- #自定義參數讓其顯示出來
- >>> params = {encoder.dropLast: False, encoder.outputCol: "test"}
- >>> encoder.transform(tdd, params).show()
- +---+---+---+--------+-------------+
- | a| b| c|features| test|
- +---+---+---+--------+-------------+
- | 1| 1| 4| 2.0|(3,[2],[1.0])|
- | 2| 2| 1| 0.0|(3,[0],[1.0])|
- | 2| 1| 3| 0.0|(3,[0],[1.0])|
- | 3| 4| 5| 1.0|(3,[1],[1.0])|
- +---+---+---+--------+-------------+
備注:sklearn 的啞編碼與 spark 不一樣,sklearn 一次性編碼所有特征列,spark 不會