官术网_书友最值得收藏!

4.2 處理類別數據

到目前為止只研究了數值特征。然而,現實世界中含一個或多個類別特征列的數據集并不少見。我們將在本節以簡單而有效的示例來討論如何用數值計算庫處理這類數據。

在討論類別數據時,我們必須進一步區分序數(ordinal)特征和標稱(nominal)特征。序數特征可以理解為可以排序的類別值。例如,T恤尺寸是一個有序特征,因為我們可以定義XL>L>M。相反,標稱特征并不蘊涵任何順序,例如T恤的顏色是標稱特征,因為說紅色比藍色大沒有什么意義。

4.2.1 用pandas實現類別數據的編碼

在探討處理這樣的類別數據的不同技術之前,讓我們創建一個新的DataFrame來說明這個問題:

089-01

從前面的輸出可以看到,新創建的DataFrame包含一個標稱特征(color)列、一個序數特征(size)列和一個數值特征(price)列。分類標簽存儲在最后一列。本書所討論的分類學習算法并均不使用有序信息作為分類標簽。

4.2.2 映射序數特征

為了確保機器學習算法能夠正確地解讀序數特征,我們需要將類別字符串值轉換為整數。不幸的是,沒有方便函數可以自動導出size特征標簽的正確順序,因此需要人工定義映射關系。在下面的簡單例子中,假設我們知道特征之間的數值差異,例如XL=L+1=M+2:

089-02

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

089-03

4.2.3 為分類標簽編碼

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

090-01

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

090-02

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

090-03

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

090-04

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

090-05

4.2.4 為名義特征做獨熱編碼

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

090-06

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

090-07

如果就此打住,并把數組提供給分類器,那么我們就會犯處理類別數據中最常見的錯誤。你知道問題所在嗎?雖然顏色值并沒有任何的特定順序,但機器學習算法會假設green大于bluered大于green。盡管該假設并不正確,但是算法仍然可以產生有用的結果。然而這并不是最優的結果。

解決這個問題的常見方案是采用一種被稱為獨熱編碼(one-hot encoding)的技巧。該方法背后的邏輯是為標稱特征列的每個唯一值創建一個新的虛擬特征。于是將把color特征轉換為bluegreenred三個新特征。然后用二進制值表示樣本的特定color;例如,一個blue樣本可以編碼為blue=1green=0red=0。我們可以使用scikit-learn的preprocessing模塊中的OneHotEncoder來實現這種轉換:

091-01

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

091-02

在前面的代碼示例中,我們通過定義'passthrough'參數指定只修改第一列,而保持其他兩列不變。

通過獨熱編碼創建虛擬特征有一個更方便的方法,即使用pandas中實現的get_dummies方法。把get_dummies方法應用到DataFrame,只轉換字符串列,而保持其他所有列不變:

091-03

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

在調用get_dummies函數時,可以通過給drop_first傳遞True參數來刪除第一列,如下面的代碼示例所示:

092-01

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

092-02

008-01

可選項:序數特征編碼

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

092-03

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

092-04
主站蜘蛛池模板: 富民县| 天峨县| 乾安县| 龙井市| 鄯善县| 合山市| 西华县| 武穴市| 扎兰屯市| 蒙阴县| 尼玛县| 深圳市| 象山县| 莱州市| 通许县| 通州区| 和顺县| 米泉市| 资兴市| 进贤县| 循化| 旅游| 连州市| 五常市| 封开县| 涞水县| 利津县| 临泽县| 淮北市| 闽清县| 大荔县| 古蔺县| 宁城县| 固阳县| 聂荣县| 邵阳县| 佛坪县| 土默特右旗| 伊川县| 鄂州市| 林芝县|