5、分類變量:自動化時代的數據計數
- 分類變量是用來表示類別或標記的,又稱爲無序變量
- 大型分類變量,分箱計數
5.1 分類變量的編碼
分類變量中的類別通常不是數值型的。例如,眼睛的顏色可以是“黑色”“藍色”和“褐 色”,等等。因此,需要一種編碼方法來將非數值型的類別轉換爲數值。如果簡單地爲 k 個可能類別中的每個類別分配一個整數,如從 1 到 k,但這樣做的結果是 使類別彼此之間有了順序,這在分類變量中是不允許的。
- 三個不同城市的公寓價格數據集
5.1.1 one-hot 編碼
使用一組比特位,每個比特位表示一種可能的類別。如果變量不能同時屬於 多個類別,那麼這組值中就只有一個比特位是“開”的。這就是 one-hot 編碼,它可以通 過scikit-learn
中 的 sklearn.preprocessing.OneHotEncoder
實 現。 每 個 比 特 位 表 示 一 個 特 徵,因此,一個可能有 k 個類別的分類變量就可以編碼爲一個長度爲 k 的特徵向量。
- 對3個城市的類別進行獨熱編碼
5.1.2 虛擬編碼
one-hot 編碼的問題是它允許有 k 個自由度,而變量本身只需要 k-1 個自由度。虛擬編碼在進行表示時只使用 k-1 個特徵,除去了額外的自由度。沒有被使用的那個特徵通過一個全零向量來表示,它稱爲參照類。虛擬編碼和 one-hot 編碼都可以通過 Pandas 包中的pandas.get_dummies
來實現。
-
對3個城市的類別進行dummy編碼
-
eg:在獨熱編碼上的線性迴歸
>>> import pandas
>>> from sklearn import linear_model
# 定義一個模擬數據集,表示紐約、舊金山和西雅圖的公寓租金
>>> df = pd.DataFrame({'City': ['SF', 'SF', 'SF', 'NYC', 'NYC', 'NYC','Seattle', 'Seattle', 'Seattle'],
'Rent': [3999, 4000, 4001, 3499, 3500, 3501, 2499, 2500, 2501]})
>>> df['Rent'].mean()
3333.3333333333335
# 將數據框中的分類變量轉換爲one-hot編碼並擬合一個線性迴歸模型
>>> one_hot_df = pd.get_dummies(df, prefix=['city'])
>>> one_hot_df
Rent city_NYC city_SF city_Seattle
0 3999 0 1 0
1 4000 0 1 0
2 4001 0 1 0
3 3499 1 0 0
4 3500 1 0 0
5 3501 1 0 0
6 2499 0 0 1
7 2500 0 0 1
8 2501 0 0 1
model = linear_model.LinearRegression()
model.fit(one_hot_df[['city_NYC', 'city_SF', 'city_Seattle']],
one_hot_df[['Rent']])
>>> model.coef_
array([[ 166.66666667, 666.66666667, -833.33333333]])
>>> model.intercept_
array([ 3333.33333333])
- eg:在虛擬變量上進行線性迴歸
dummy_df = pd.get_dummies(df, prefix=['city'], drop_first=True)
>>> dummy_df
Rent city_SF city_Seattle
0 3999 1 0
1 4000 1 0
2 4001 1 0
3 3499 0 0
4 3500 0 0
5 3501 0 0
6 2499 0 1
7 2500 0 1
8 2501 0 1
>>> model.fit(dummy_df[['city_SF', 'city_Seattle']], dummy_df['Rent'])
>>> model.coef_
array([ 500., -1000.])
>>> model.intercept_
3500.0
使用 one-hot 編碼時,截距項表示目標變量 Rent 的整體均值,每個線性係數表示相應城市的租金均值與整體均值有多大差別。
使用虛擬編碼時,偏差係數表示響應變量 y 對於參照類的均值,本例中參照類是紐約。第 i個特徵的係數等於第 i 個類別的均值與參照類均值的差。
- 線性迴歸係數差距
5.1.3 效果編碼
分類變量編碼的另一種變體稱爲Effect編碼。 Effect編碼與虛擬編碼非常相似,區別在於參考類別現在由所有-1的向量表示。
- Effect編碼表示3個城市
Effect編碼與虛擬編碼非常相似,但是在線性迴歸中更容易被擬合。截距項表示目標變量的整體均值,各個係數表示了各個類別的均值與整體均值之間的差。one-hot 編碼實際上也可以得到同樣的截距和係數,但它的每個城市都有一個線性係數。在 效果編碼中,沒有單獨的特徵來表示參照類,所以參照類的效果需要單獨計算,它是所有其他類別的係數的相反數之和。
- 使用效果編碼的線性迴歸
>>> effect_df = dummy_df.copy()
>>> effect_df.ix[3:5, ['city_SF', 'city_Seattle']] = -1.0
>>> effect_df
Rent city_SF city_Seattle
0 3999 1.0 0.0
1 4000 1.0 0.0
2 4001 1.0 0.0
3 3499 -1.0 -1.0
4 3500 -1.0 -1.0
5 3501 -1.0 -1.0
6 2499 0.0 1.0
7 2500 0.0 1.0
8 2501 0.0 1.0
>>> model.fit(effect_df[['city_SF', 'city_Seattle']], effect_df['Rent'])
>>> model.coef_
array([ 666.66666667, -833.33333333])
>>> model.intercept_
3333.3333333333335
5.1.4 各種分類變量編碼的優缺點
one-hot 編碼、虛擬編碼和效果編碼彼此之間非常相似,它們都有各自的優缺點。one-hot 編碼有冗餘,這會使得同一個問題有多個有效模型,這種非唯一性有時候比較難以解釋。 它的優點是每個特徵都明確對應一個類別,而且可以把缺失數據編碼爲全零向量,模型輸 出也是目標變量的總體均值。
虛擬編碼和效果編碼沒有冗餘,它們可以生成唯一的可解釋的模型。虛擬編碼的缺點是不 太容易處理缺失數據,因爲全零向量已經映射爲參照類了。它還會將每個類別的效果表示 爲與參照類的相對值,這看上去有點不直觀。
效果編碼使用另外一種編碼表示參照類,從而避免了這個問題,但是全由 -1 組成的向量 是個密集向量,計算和存儲的成本都比較高。正是因爲這個原因,像 Pandas 和 scikit-learn 這樣的常用機器學習軟件包更喜歡使用虛擬編碼或 one-hot 編碼,而不是效果編碼。
當類別的數量變得非常大時,這 3 種編碼方式都會出現問題,所以需要另外的策略來處理 超大型分類變量。
5.2 處理大型分類變量
5.2.1 特徵散列化
- demo : 使用
scikit-learn
的FeatureHasher
函數
>>> from sklearn.feature_extraction import FeatureHasher
>>> h = FeatureHasher(n_features=m, input_type='string')
>>> f = h.transform(review_df['business_id'])
5.2.2 分箱計數
分箱計數它不使用分類變量的值作爲特徵,而是使用目標變量取這 個值的條件概率。換句話說,我們不對分類變量的值進行編碼,而是要計算分類變量值與 要預測的目標變量之間的相關統計量。
小結
one-hot encoding
空間使用:O(n) 時間複雜度:O(nk)
優點:
- 容易實現
- 更高的精度
- 在線學習特別容易擴展
缺點
- 計算不足
- 如果類別增加則不能夠使用
- 對線性模型以外的任何其他方法都不可行
- 對於大數據集需要分佈式訓練
特徵散列化 Feature hashing
空間使用:O(n) 時間複雜度:O(nm)
優點:
- 容易實現
- 容易訓練
- 容易擴展到新類別
- 容易處理稀有類別
- 在線學習容易擴展
缺點
- 只能夠使用線性或核模型
- 哈希編碼很難解釋
- 精度有爭議
分箱計數 Bin-counting
空間使用:O(n+k) 時間複雜度:O(n)
優點:
- 訓練快
- 能夠使用樹模型
- 容易擴展到新列類別
- 容易處理稀有類別
- 可解釋
缺點
- 需要利用歷史信息
- 對於在線學習有困難
- 會有數據泄露
參考:《精通特徵工程》愛麗絲·鄭·阿曼達·卡薩麗
面向機器學習的特徵工程學習筆記:
【精通特徵工程】學習筆記(一)
【精通特徵工程】學習筆記(二)
【精通特徵工程】學習筆記(三)