機器學習中數(shù)據(jù)缺失值這樣處理才香!
在日常工作中,數(shù)據(jù)在大多數(shù)情況下都有很多缺失數(shù)據(jù),每個值缺失的原因可能不同,但缺失的數(shù)據(jù)會降低模型的預測能力。
數(shù)據(jù)缺失類型
由于多種原因,可能會出現(xiàn)缺失數(shù)據(jù)。我們可以將它們分為三個主要組:完全隨機丟失、隨機丟失、隨機未丟失。
完全隨機缺失(MCAR)
當數(shù)據(jù)為 MCAR 時,數(shù)據(jù)缺失與任何值之間都沒有關系,也沒有特定的缺失值原因。
隨機缺失(MAR)
與 MCAR 不同,這里的數(shù)據(jù)在特定子集中缺失。當缺失不是隨機的,但缺失值與其他觀察到的數(shù)據(jù)之間存在系統(tǒng)關系。
非隨機缺失(NMAR)
假設調(diào)查的目的是衡量對社交媒體的過度使用,如果過度使用社交媒體的人故意沒有填寫調(diào)查表,那么我們就有一個 NMAR 案例。
檢測缺失數(shù)據(jù)
我們使用 Kaggle 的 Big Mart 銷售預測數(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ù)的行為和分布。
要使用這個庫,我們需要安裝和導入它
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 包還允許我們按選擇性列對圖表進行排序。讓我們按 Item_Weight 列對值進行排序,以檢測缺失值中是否存在模式。
sorted?=?train.sort_values('Item_Weight')
msno.matrix(sorted)
上圖顯示了 Item_Weight 和 Outlet_Size 之間的關系。
讓我們檢查一下與觀察到的數(shù)據(jù)是否有任何關系。
data?=?train.loc[(train["Outlet_Establishment_Year"]?==?1985)]
data

上圖顯示,Item_Weight 全部為空,屬于 1985 年成立年份。
Item_Weight 為空,屬于 Tier3 和 Tier1,其中 outlet_size 中、低,包含低脂肪和常規(guī)脂肪。這種缺失是一種隨機缺失(MAR),因為所有缺失的 Item_Weight 都與一個特定年份有關。
msno.heatmap(train)
Item_Weight 與 Outlet_Size 呈負相關(-0.3)
缺失數(shù)據(jù)處理
在對缺失值的模式進行分類后,需要對其進行處理。
1、列表刪除
當在隨機情況下完全丟失時,首選按列表刪除。
在 python 中,我們使用 dropna() 函數(shù)進行 Listwise 刪除。
train_1?=?train.copy()
train_1.dropna()
如果數(shù)據(jù)集很小,則不推薦按列表刪除,并且機器學習模型不會在小數(shù)據(jù)集上給出好的結(jié)果。
2、成對刪除
如果缺失完全隨機缺失,即 MCAR,則使用成對刪除。
首選成對刪除,以減少 Listwise 刪除中發(fā)生的損失,因為它只刪除空觀察,而不是整行。
3、刪除完整的列
如果一列有很多缺失值,比如超過 80%,并且該特征沒有意義,那么我們可以刪除整個列。
插補技術:
插補技術用替換值替換缺失值。根據(jù)數(shù)據(jù)的性質(zhì)及其問題,可以通過多種方式估算缺失值。插補技術可以大致分為以下幾類:
1、具有恒定值的插補
正如標題所暗示的那樣——它用零或任何常數(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)計插補
語法與使用常量的插補相同,只是 SimpleImputer 策略會改變。它可以是"平均值"或"中位數(shù)"或"最頻繁"。
在使用任何策略之前,最重要的一步是檢查數(shù)據(jù)類型和特征分布。
sns.distplot(train['Item_Weight'])
Item_Weight 列同時滿足數(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、高級插補技術
與以前的技術不同,高級插補技術采用機器學習算法來插補數(shù)據(jù)集中的缺失值。以下是有助于估算缺失值的機器學習算法。
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é)論
沒有單一的方法來處理缺失值。在應用任何方法之前,有必要了解缺失值的類型,然后檢查缺失列的數(shù)據(jù)類型和偏度,然后決定哪種方法最適合特定問題。
--end-- 掃碼即可加我微信
學習交流
老表朋友圈經(jīng)常有贈書/紅包福利活動
