機(jī)器學(xué)習(xí)中數(shù)據(jù)缺失值這樣處理才香!
在日常工作中,數(shù)據(jù)在大多數(shù)情況下都有很多缺失數(shù)據(jù),每個值缺失的原因可能不同,但缺失的數(shù)據(jù)會降低模型的預(yù)測能力。
數(shù)據(jù)缺失類型
由于多種原因,可能會出現(xiàn)缺失數(shù)據(jù)。我們可以將它們分為三個主要組:完全隨機(jī)丟失、隨機(jī)丟失、隨機(jī)未丟失。
完全隨機(jī)缺失(MCAR)
當(dāng)數(shù)據(jù)為 MCAR 時(shí),數(shù)據(jù)缺失與任何值之間都沒有關(guān)系,也沒有特定的缺失值原因。
隨機(jī)缺失(MAR)
與 MCAR 不同,這里的數(shù)據(jù)在特定子集中缺失。當(dāng)缺失不是隨機(jī)的,但缺失值與其他觀察到的數(shù)據(jù)之間存在系統(tǒng)關(guān)系。
非隨機(jī)缺失(NMAR)
假設(shè)調(diào)查的目的是衡量對社交媒體的過度使用,如果過度使用社交媒體的人故意沒有填寫調(diào)查表,那么我們就有一個 NMAR 案例。
檢測缺失數(shù)據(jù)
我們使用 Kaggle 的 Big Mart 銷售預(yù)測數(shù)據(jù),鏈接:https://www.kaggle.com/datasets/shivan118/big-mart-sales-prediction-datasets
import?pandas?as?pd
import?numpy?as?np
import?matplotlib.pyplot?as?plt
import?seaborn?as?sns
import?warnings?#?Ignores?any?warning
warnings.filterwarnings("ignore")
train?=?pd.read_csv("Train.csv")
mis_val?=train.isna().sum()
mis_val_per?=?train.isna().sum()/len(train)*100
mis_val_table?=?pd.concat([mis_val,?mis_val_per],?axis=1)
mis_val_table_ren_columns?=?mis_val_table.rename(columns?=?{0?:?'Missing?Values',?1?:?'%?of?Total?Values'})
mis_val_table_ren_columns?=?mis_val_table_ren_columns[mis_val_table_ren_columns.iloc[:,:]?!=?0].sort_values('%?of?Total?Values',?ascending=False).round(1)
mis_val_table_ren_columns
我們也可以使用 Missingno 庫直觀地檢測缺失值:
Missingno 是一個簡單的 Python 庫,它提供了一系列可視化來識別 Pandas 數(shù)據(jù)框中缺失數(shù)據(jù)的行為和分布。
要使用這個庫,我們需要安裝和導(dǎo)入它
pip?install?missingno?
import?missingno?as?msno
msno.bar(train)
我們可以觀察到 Item_Weight、Outlet_Size 列有缺失值。如果它能夠找出丟失數(shù)據(jù)的位置,那就有意義了。
msno.matrix() 是一個空值矩陣,有助于可視化空值觀測值的位置。
msno."parent.postMessage({'referent':'.missingno.matrix'},?'*')">matrix(train)
只要有缺失值,該圖就會顯示為白色。一旦你得到了丟失數(shù)據(jù)的位置,你就可以很容易地找出丟失數(shù)據(jù)的類型。
Item_Weight 和 Outlet_Size 列都有很多缺失值。missingno 包還允許我們按選擇性列對圖表進(jìn)行排序。讓我們按 Item_Weight 列對值進(jìn)行排序,以檢測缺失值中是否存在模式。
sorted?=?train.sort_values('Item_Weight')
msno.matrix(sorted)
上圖顯示了 Item_Weight 和 Outlet_Size 之間的關(guān)系。
讓我們檢查一下與觀察到的數(shù)據(jù)是否有任何關(guān)系。
data?=?train.loc[(train["Outlet_Establishment_Year"]?==?1985)]
data

上圖顯示,Item_Weight 全部為空,屬于 1985 年成立年份。
Item_Weight 為空,屬于 Tier3 和 Tier1,其中 outlet_size 中、低,包含低脂肪和常規(guī)脂肪。這種缺失是一種隨機(jī)缺失(MAR),因?yàn)樗腥笔У?Item_Weight 都與一個特定年份有關(guān)。
msno.heatmap(train)
Item_Weight 與 Outlet_Size 呈負(fù)相關(guān)(-0.3)
缺失數(shù)據(jù)處理
在對缺失值的模式進(jìn)行分類后,需要對其進(jìn)行處理。
1、列表刪除
當(dāng)在隨機(jī)情況下完全丟失時(shí),首選按列表刪除。
在 python 中,我們使用 dropna() 函數(shù)進(jìn)行 Listwise 刪除。
train_1?=?train.copy()
train_1.dropna()
如果數(shù)據(jù)集很小,則不推薦按列表刪除,并且機(jī)器學(xué)習(xí)模型不會在小數(shù)據(jù)集上給出好的結(jié)果。
2、成對刪除
如果缺失完全隨機(jī)缺失,即 MCAR,則使用成對刪除。
首選成對刪除,以減少 Listwise 刪除中發(fā)生的損失,因?yàn)樗粍h除空觀察,而不是整行。
3、刪除完整的列
如果一列有很多缺失值,比如超過 80%,并且該特征沒有意義,那么我們可以刪除整個列。
插補(bǔ)技術(shù):
插補(bǔ)技術(shù)用替換值替換缺失值。根據(jù)數(shù)據(jù)的性質(zhì)及其問題,可以通過多種方式估算缺失值。插補(bǔ)技術(shù)可以大致分為以下幾類:
1、具有恒定值的插補(bǔ)
正如標(biāo)題所暗示的那樣——它用零或任何常數(shù)值替換缺失值。我們將使用 sklearn 中的 SimpleImputer 類。
from?sklearn.impute?import?SimpleImputer
train_constant?=?train.copy()
#setting?strategy?to?'constant'?
mean_imputer?=?SimpleImputer(strategy='constant')?#?imputing?using?constant?value
train_constant.iloc[:,:]?=?mean_imputer.fit_transform(train_constant)
train_constant.isnull().sum()

2、使用統(tǒng)計(jì)插補(bǔ)
語法與使用常量的插補(bǔ)相同,只是 SimpleImputer 策略會改變。它可以是"平均值"或"中位數(shù)"或"最頻繁"。
在使用任何策略之前,最重要的一步是檢查數(shù)據(jù)類型和特征分布。
sns.distplot(train['Item_Weight'])
Item_Weight 列同時(shí)滿足數(shù)值類型且沒有偏態(tài)(遵循高斯分布),在這里,我們可以使用任何策略。
from?sklearn.impute?import?SimpleImputer
train_most_frequent?=?train.copy()
#setting?strategy?to?'mean'?to?impute?by?the?mean
mean_imputer?=?SimpleImputer(strategy='most_frequent')#?strategy?can?also?be?mean?or?median?
train_most_frequent.iloc[:,:]?=?mean_imputer.fit_transform(train_most_frequent)
train_most_frequent.isnull().sum()

3、高級插補(bǔ)技術(shù)
與以前的技術(shù)不同,高級插補(bǔ)技術(shù)采用機(jī)器學(xué)習(xí)算法來插補(bǔ)數(shù)據(jù)集中的缺失值。以下是有助于估算缺失值的機(jī)器學(xué)習(xí)算法。
KNN 算法通過使用歐幾里德距離度量找到具有缺失數(shù)據(jù)的觀測值的最近鄰居并根據(jù)鄰居中的非缺失值來估算缺失數(shù)據(jù),從而幫助估算缺失數(shù)據(jù)。
train_knn?=?train.copy(deep=True)
from?sklearn.impute?import?KNNImputer
knn_imputer?=?KNNImputer(n_neighbors=2,?weights="uniform")
train_knn['Item_Weight']?=?knn_imputer.fit_transform(train_knn[['Item_Weight']])
train_knn['Item_Weight'].isnull().sum()
結(jié)論
沒有單一的方法來處理缺失值。在應(yīng)用任何方法之前,有必要了解缺失值的類型,然后檢查缺失列的數(shù)據(jù)類型和偏度,然后決定哪種方法最適合特定問題。
--end-- 掃碼即可加我微信
學(xué)習(xí)交流
老表朋友圈經(jīng)常有贈書/紅包福利活動
