- Python機器學習(原書第3版)
- (美)塞巴斯蒂安·拉施卡 瓦希德·米爾賈利利
- 1921字
- 2021-06-11 16:13:45
4.2 處理類別數據
到目前為止只研究了數值特征。然而,現實世界中含一個或多個類別特征列的數據集并不少見。我們將在本節以簡單而有效的示例來討論如何用數值計算庫處理這類數據。
在討論類別數據時,我們必須進一步區分序數(ordinal)特征和標稱(nominal)特征。序數特征可以理解為可以排序的類別值。例如,T恤尺寸是一個有序特征,因為我們可以定義XL>L>M。相反,標稱特征并不蘊涵任何順序,例如T恤的顏色是標稱特征,因為說紅色比藍色大沒有什么意義。
4.2.1 用pandas實現類別數據的編碼
在探討處理這樣的類別數據的不同技術之前,讓我們創建一個新的DataFrame
來說明這個問題:

從前面的輸出可以看到,新創建的DataFrame
包含一個標稱特征(color
)列、一個序數特征(size
)列和一個數值特征(price)列。分類標簽存儲在最后一列。本書所討論的分類學習算法并均不使用有序信息作為分類標簽。
4.2.2 映射序數特征
為了確保機器學習算法能夠正確地解讀序數特征,我們需要將類別字符串值轉換為整數。不幸的是,沒有方便函數可以自動導出size
特征標簽的正確順序,因此需要人工定義映射關系。在下面的簡單例子中,假設我們知道特征之間的數值差異,例如XL=L+1=M+2:

如果想在以后再把整數值轉換回原來字符串的形式,我們可以簡單地定義一個反向映射字典inv_size_mapping={v: k for k, v in size_mapping.items()}
(類似之前使用過的size-mapping
字典),然后可以通過pandas的map
方法用在變換后的特征列上,如下所示:

4.2.3 為分類標簽編碼
許多機器學習庫都要求分類標簽的編碼為整數值。雖然大多數scikit-learn的分類估計器可以在內部實現整數分類標簽的轉換,但是通過將分類標簽作為整數數組能夠從技術角度避免某些問題的產生,在實踐中這被認為是一個很好的做法。我們可以采用與之前討論過的序數特征映射相似的方法為分類標簽編碼。需要記住的是,分類標簽并不是有序的,具體哪個整數匹配特定的字符串標簽無關緊要。因此,可以從0
開始簡單地枚舉:

接下來,可以用映射字典將分類標簽轉換為整數:

可以在字典中反向映射鍵值對,將轉換后的分類標簽匹配到原來的字符串,如下所示:

另外,也可以在scikit-learn中非常方便地直接調用LabelEncoder
類來實現:

請注意,fit_transform
方法只是分別調用fit
和transform
的一種快捷方式,可以使用inverse_transform
方法將分類的整數型分類標簽轉換回原來的字符串形式:

4.2.4 為名義特征做獨熱編碼
4.2.2節我們用簡單的字典映射方法將序數size
特征轉換為整數。由于scikit-learn分類估計器把分類標簽當成無序的標稱特征數據進行分類,我們可以用方便的LabelEncoder
把字符串標簽編碼為整數。我們可以用類似的方法轉換數據集中的標稱特征color
列,所實現的代碼如下:

執行上述代碼之后,NumPy數組x
的第一列現在就有了新的color
值,其編碼格式為:

如果就此打住,并把數組提供給分類器,那么我們就會犯處理類別數據中最常見的錯誤。你知道問題所在嗎?雖然顏色值并沒有任何的特定順序,但機器學習算法會假設green
大于blue
、red
大于green
。盡管該假設并不正確,但是算法仍然可以產生有用的結果。然而這并不是最優的結果。
解決這個問題的常見方案是采用一種被稱為獨熱編碼(one-hot encoding)的技巧。該方法背后的邏輯是為標稱特征列的每個唯一值創建一個新的虛擬特征。于是將把color
特征轉換為blue
、green
和red
三個新特征。然后用二進制值表示樣本的特定color
;例如,一個blue
樣本可以編碼為blue=1
,green=0
,red=0
。我們可以使用scikit-learn的preprocessing
模塊中的OneHotEncoder
來實現這種轉換:

請注意,我們僅將OneHotEncoder
應用于單列(X[:,0].reshape(-1, 1))
,以避免再修改數組中的其他兩列。如果想要選擇性地轉換多特征數組中的列,則可以使用ColumnTransformer
,它接受(name, transformer, column(s))
元組的列表,如下所示:

在前面的代碼示例中,我們通過定義'passthrough'
參數指定只修改第一列,而保持其他兩列不變。
通過獨熱編碼創建虛擬特征有一個更方便的方法,即使用pandas中實現的get_dummies
方法。把get_dummies
方法應用到DataFrame
,只轉換字符串列,而保持其他所有列不變:

當用獨熱編碼技術為數據集編碼時,必須小心它會帶來多重共線性,對某些方法來說這可能是個問題(例如那些需要矩陣求逆的方法)。如果特征高度相關那么矩陣求逆是很難計算的,這可能會導致數值估計不穩定。為了減少變量之間的相關性,可以直接從獨熱編碼數組中刪除一個特征列。請注意,盡管我們刪除了一個特征列,但并沒失去任何重要的信息。例如,如果刪除color_blue
列,那么特征信息仍然可以得到保留,因為如果我們觀察到color_green=0
和color_red=0
,這意味著余下的觀察結果一定是blue
。
在調用get_dummies
函數時,可以通過給drop_first
傳遞True
參數來刪除第一列,如下面的代碼示例所示:

如果要用獨熱編碼方法刪除冗余列,我們就需要定義drop='first'
,并設置categories='auto'
,如下所示:

可選項:序數特征編碼
如果我們不確定序數特征類別之間的數值差異,或者未定義兩個序數值之間的差異,我們可以使用0/1閾值對它們進行編碼。例如我們可以將具有M、L和XL值的特征size
拆分為兩個新特征,即“x>M”和“x>L”。讓我們考慮原始DataFrame:

我們可以用pandas DataFrame的apply
方法編寫自定義的lambda
表達式,以便調用value-threshold方法對這些變量進行編碼:

- Android開發精要
- Java Web開發之道
- 數據結構習題精解(C語言實現+微課視頻)
- C語言程序設計
- Learning SQLite for iOS
- Visual C
- TypeScript項目開發實戰
- Learning Hunk
- Learning FuelPHP for Effective PHP Development
- 微信小程序開發與實戰(微課版)
- Hands-On JavaScript for Python Developers
- 汽車人機交互界面整合設計
- JavaScript+jQuery網頁特效設計任務驅動教程
- Java程序設計實用教程(第2版)
- Three.js權威指南:在網頁上創建3D圖形和動畫的方法與實踐(原書第4版)