資料處理 | pandas入門專題——離散化與one-hot

TechFlow2019發表於2020-08-28

今天是pandas資料處理專題第7篇文章,可以點選上方專輯檢視往期文章。

在上一篇文章當中我們介紹了對dataframe進行排序以及計算排名的一些方法,在今天的文章當中我們來了解一下dataframe兩個非常重要的功能——離散化和one-hot

離散化

離散對應的反面是連續,離散化也就是將連續性的數值對映到一個離散的值。舉個很簡單的例子,比如說現在有一個特徵是使用者的收入,我們都知道貧富差距是非常巨大的,一個馬雲的收入頂的上成千上萬人收入之和。而最窮的人收入非常少,甚至每天不到一美元。

我們來設想一下,假設我們將收入這個值作為特徵放入模型,會發生什麼。如果是線性模型,很顯然模型會被這個特徵值給帶跑偏。我們來看下線性迴歸的公式:,這裡的W表示的樣本矩陣X的係數向量。假設某一維是收入,那麼它對應的係數顯然必須非常非常小,因為樣本當中有馬雲這種頂級大佬的收入存在,也就是說為了擬合這樣的極端資料,模型被帶跑偏了。

這種情況非常多,因為現實生活當中很多資料的分佈是非常不均勻的。往往不是正態分佈而是二八分佈,甚至更加兩極分化。那針對這種情況該怎麼處理呢?

比較簡單也比較常用的一種方法就是將它離散化,將原本連續的值對映成離散的變數。比如說收入,我們不再直接用收入這個值來作為特徵,而是將它分成幾個桶,比如分為低收入群體,中等收入群體,高收入群體。這樣對模型訓練來說,就不會被帶偏了,但是缺點是損失了部分資訊。比如說馬雲和東哥都是高收入群體,但是兩人的掙錢能力其實還是相差蠻遠的。如果採用這種方式就體現不出來了,所以離散化的設計也不是拍腦門的,也要根據實際情況具體分析。

那麼假設我們希望在dataframe當中做這樣離散化的操作,應該怎麼辦呢?

其實非常簡單,pandas的開發人員早就想到了這個需求,有現成且成熟的api可以使用。我們來看個例子,首先我們建立一批資料,表示一批使用者的年收入:

income = [2000100001500008000200003000050000100000020000000300000000]

然後我們再人為的設定分桶用來對收入進行劃分:

bins = [030000100000100000001000000000]

之後我們只需要呼叫pandas當中的cut方法,將income和bins陣列都傳入就可以了:

pandas返回的結果是Categorical的物件,表示一種類別。像是(0, 30000]既是這個分桶的值的範圍,也表示這個分桶的名字。我們也可以自己傳入我們定義的分桶名稱來替換這個範圍:

這裡要注意我們傳入的labels的數量要比bins也就是劃分範圍少一個,因為劃分的區間是半閉半開的,區間的數量是bins-1,所以我們指定的labels數量也應該是bins-1。在預設的劃分方法當中,採用的是左開右閉區間,和我們常用的左閉右開區間不同,我們可以通過right=False這個引數將它設定成左閉右開區間。

在使用cut的過程當中,如果我們希望按照值的範圍來進行均等劃分的話,我們也可以傳入我們希望劃分的分桶數量代替bins,這樣pandas會根據這一列值的範圍按照指定的數量進行均分進行劃分:

如果是採用均等劃分,想要對劃分的精度進行限定,可以通過precision引數進行限定。比如說我們希望精度保留兩位小數,那麼傳入precision=2即可。

離散化的方法除了cut之外,還有一個叫做qcut,和cut不同之處在於qcut是根據分位數進行劃分的。比如我們希望忽視具體的數值,按照資料的數量進行等分,就需要用到qcut了。

除了傳入想要得到的劃分數量之外,我們也可以指定想要劃分的分位數,是0到1之間的小數,包含端點:

one-hot

one-hot也是機器學習當中非常非常常用的一種資料處理方式,one-hot這個詞乍看不是很明白,也有地方翻譯成獨熱碼,也很費解。其實它的含義很簡單,就是將一系列非數值型的值進行類別分桶,

我們舉個很簡單的例子,假設我們把男生分為三種:高富帥、矮矬窮和理工男,我們現在有4個男生:[高富帥、矮矬窮、理工男、高富帥],這顯然是一個特徵,但問題是大部分模型是不接受字串型別的特徵的,我們必須將它轉化成數值才行。問題就在轉化這裡,我們很難做這個對映。

有人會說我們可以讓高富帥、矮矬窮這些標籤對應不同的數值,做一個對映不就可以了嗎?比如說矮矬窮等於1,高富帥等於2,這樣一對映不就變成數值了嗎?很可惜不行,原因也很簡單,因為我們單純地把它們對映成數值之後,它們就從一個抽象的概念變成數了。抽象的概念之間是沒有大小關係也沒有倍數關係的,但是數值有。比如說高富帥等於2,矮矬窮等於1,那在模型當中是否一個高富帥等於兩個矮矬窮?是否高富帥大於矮矬窮?

這些額外的資訊對模型是非常致命的,我們不希望模型得到這些資訊。最好的方法是我們生成一個列表,列表當中有三列分別是高富帥、矮矬窮和理工男。你是高富帥就高富帥那一列為1,其他列都為0,同理你是矮矬窮就矮矬窮那一列為1,其他列為0。在這個列表當中每一行只有一列為1,其他都為0,相當於只有一列熱,其他列都是冷的,one-hot就是這麼來的。

我們噼裡啪啦說了很多,但實際上one-hot的實現非常簡單,只有一行:

pd.get_dummies(dataframe)

預設得到的列表的名稱會加上這一列的列名作為字首,我們也可以自己通過prefix傳入我們想要的字首:

多列一起進行one-hot也沒有關係:

總結

離散化和one-hot都是非常常用的功能, 一般來說這兩個功能通常會連在一起使用,先將某一個值進行離散化,然後再將離散化的結果進行one-hot,從而適應模型。因此本文的內容非常實用,不要錯過哦。

今天的文章到這裡就結束了,如果喜歡本文的話,請來一波素質三連,給我一點支援吧(關注、轉發、點贊)。

- END -

原文連結,求個關注

相關文章