【Python機器學習】109:當數據集含有遺漏值的處理方法與未經過訓練的分類預測器

Methods dealing with missing values ​​in training data and Dummy Classifiers

張育晟 Eason Chang
展開數據人生
8 min readSep 6, 2020

--

端到端的分類問題:

A computer program is said to learn from experience E with respect to some class tasks T and performance measure P if its performance at tasks in T, as measured by P, improves with experience E

分類問題跟回歸問題最大的差別就在於y的性質不同,先前的y都是連續性的數值,但如果是分類型的問題,它的y是屬於離散型的資料。

如上述範例中,如果我們想要預測鐵達尼號的乘客是否存活,y的值只有0(死亡)或1(存活),這就是一個分類問題。但是在介紹分類模型(Logistic Regression)之前,我們先試著用 “Age” 代替 “Pclass” 跑跑看:

如果大家有試著在自己電腦跑跑看了話就會跳出error,為什麼換了X會跳出錯誤訊息呢?原因是輸入的training data含有遺漏值NaN(not a number)。

如果我們單純用比較運算符號(=)來看是否有跟NaN一樣的東西是比較不出來的,得使用np.isnan()偵測遺漏值個數:

np.nan()函數會一個一個row去檢查,碰到有nan值就會回傳True,反之則False,最後再用sum()就能得知在titanic資料中的 “Age” 變數中有多達177個遺漏值。

遇到遺漏值有2種做法:

第一種也是最單純的做法是直接把有遺漏值的資料剔除捨棄掉,如果training data數量很多了話建議這樣做:

把有遺漏值的資料都刪掉後,可以看到原始資料titanic只剩下714筆

對array取not使用 ~ (tilt),如此一來我就能得到非缺漏值的True/False array,把遺漏值都丟掉後,就可以繼續對資料做後續處理。

如果原始資料個數較少,不想把資料丟掉了話,而是希望把資料補起來,以np.where()進行簡單遺漏值填補,可以用平均數或是中位數去補。

使用平均數去補:

這邊需要注意的是,如果你需要對含有遺漏值的資料去算平均數,得使用nanmean()函數。

算出平均數之後,要怎麼去做填補呢?在Numpy裡面有一個函數叫np.where(),用起來很像excel中的if-else函數,先傳一個condition,當這個condition為true的時候,做第二個參數的事情,反之則做第三個;如上述範例,np.where()一樣一個個row去檢查,假如該值是nan,就用平均數去補,不然就延用原本的值。

如果多做了資料預處理(第2、3行程式碼),資料就可以順利的跑動:

接下來要介紹深度學習前的最後一個transformer了,先前介紹有,增加高次項變數的PolynomialFeatures、處理類別變數的 OneHotEncoder,最後一個則是處理遺漏值的:

以sklearn.impute.SimpleImputer()進行簡單遺漏值填補:

SimpleImputer()在始化時一樣需要傳2個參數。第一個參數是告訴函數missing-value要怎麼判斷,它的預設值是檢查值是否為np.nan,第二個參數是告訴函數需要用什麼值去填補,預設值為資料的平均數。剛剛好這兩個參數的預設值和我們的方式是契合的,所以上圖範例中初始化的小掛號才什麼都不填。假如我們未來想要填補的值為中位數,則初始化就要寫成:

因為補了很多平均數(or 中位數)的值,所以中間值數量會變的非常多,畫圖檢查會發現中間值的bar特別高,這樣其實有個隱憂:X的遺漏值都是填同一個值。那能不能用更均勻的方式去填補遺漏值?

我們使用另外一種方式,以df.map()進行簡單遺漏值填補:用 “Pclass” 來對 “Age” 做分組,“Pclass”為乘客的社經地位,有1、2、3,3種數值。每一組有不一樣的平均年齡,這樣就可以分層填補值,就不會全部遺漏值都填同一個值。

用這種方法填補遺漏值之後,整個資料就會變的平均許多。

未經訓練的分類器(Dummy Classifiers)

使用簡單守則對資料進行分類,像是許多的 if 條件式

提供了分類的baseline:如果這些未經訓練的分類器表現的都比我訓練過後的分類器來的好的話,那就應該換一個分類器了。

常見未經過訓練的分類器:

硬幣

專家意見

…etc.

那為什麼回歸問題沒有所謂的dummy regression呢?因為連續數值的 y 太難猜了,在無限大的空間幾乎不可能用未經訓練的模型預測。

投擲硬幣來分類 Titanic 乘客的生死:

如果我是完全靠擲硬幣來決定生死,training data對我來說就完全沒有參考價值了,我完全不需要看X。我需要丟銅板的次數由validation的長度來決定,y_validation有多少個數字我就丟幾次,這樣我的y-prediction就預測做完了。

使用random模組隨機產生預測

投擲硬幣分類 Titanic 乘客的生死準不準?

我們需要透過 Confusion Matrix 來判斷我的分類準不準。之前呼叫的accuracy-score就是從confusion matrix衍生出來的。分類器常使用的評估指標比迴歸模型為多,像是準確率(Accuracy)、精確率(Precision)、召回率(Recall)與 F1-score 等。

正確分類𝑦(𝑣𝑎𝑙𝑖𝑑)=𝑦̂(𝑣𝑎𝑙𝑖𝑑)與錯誤分類𝑦(𝑣𝑎𝑙𝑖𝑑)≠𝑦̂(𝑣𝑎𝑙𝑖𝑑)各自都還能拆解成兩種情境:

True Positive (TP)「真陽性」:真實情況是「有」,模型說「有」的個數。
True Negative(TN)「真陰性」:真實情況是「沒有」,模型說「沒有」的個數。
False Positive (FP)「偽陽性」:真實情況是「沒有」,模型說「有」的個數。
False Negative(FN)「偽陰性」:真實情況是「有」,模型說「沒有」的個數。

這四種情境能夠以一個被稱作混淆矩陣(Confusion matrix)的 2×2 矩陣表達:

我們現階段只需要算猜對的百分比為多少即可,因此只需拿 y-pred 和 y-validation 是否相等做判斷。

聽聞專家意見分類Titanic乘客的生死

Although there was some element of luck involved in surviving the sinking, some groups of people were more likely to survive than others, such as women, children, and the upper-class.

根據上述專家意見,如果該乘客為女生、小孩或上層階級,則生存機率較高。接下來我們將針對這個法則(rule-based)做分類。

先把特徵資料準備好:

此特徵資料分別為性別、年齡與階級

接著,我們依據專家意見給的準則,做一個分類函數:如果該乘客的性別特徵為女性或小孩(年齡小於12歲)或為上層階級(Pclass為1),則該乘客為生存(y =1),其他乘客則為死亡(y = 0):

聽聞專家意見分類Titanic乘客的生死準不準?

同樣算accuracy檢查準確率,可以看到專家的意見比起擲硬幣呈現大幅度的躍進,原本只有50%的準確率來到了78%。

感謝你閱讀完這篇文章,如果你覺得這些文章對你有幫助請在底下幫我拍個手(長按最多可以拍50下手)。

上一章:【Python機器學習】108:資料標準化與進階梯度遞減的實用技巧

下一章:【Python機器學習】110:單純貝氏分類器

--

--

張育晟 Eason Chang
展開數據人生

在不斷變動中努力思索自己的定位,想做的事情很多,但最希望的是不要變成無趣的人。 Linkedin: https://www.linkedin.com/in/stareason1997