缺失值必須被標記為NaN,且可以被用統計方法計算出的列的值來替代。
如何載入一份帶有缺失值的CSV文件,用NaN來標識缺失值,展現出每一列的缺失值數量和百分比。
如何用統計量來填充缺失值,作為數據準備方法中的一個步驟,用於評估模型和用最終模型和新數據來擬合預測結果。
教程綜述1. SimpleImputer 數據轉換
2. SimpleImputer 和模型評估
3. 比較不同的插補統計量
4. 在預測時進行SimpleImputer轉換
統計插補缺失值是指一行數據中某一項或者多項的數據值沒有意義。有可能是值為空,也有可能是用一些特殊的字符或值來表示,例如問號「?」。「這些值有可能以多種形式來表示。我見過的形式比如有完全為空,一個空的字符串,「NULL」欄位、「N/A」或「NaN」,再就是數字0等等。不管它們以什麼樣的形式出現在你的數據集裡,你要清楚自己的目的,並且確定這些數據的作用匹配達到你的預期,這樣將會使你在開始使用數據時減少問題的存在。」
——源自2012年出版的《Bad Data Handbook》,第10頁書籍地址:https://amzn.to/3b5yutA2,1,530101,38.50,66,28,3,3,?,2,5,4,4,?,?,?,3,5,45.00,8.40,?,?,2,2,11300,00000,00000,21,1,534817,39.2,88,20,?,?,4,1,3,4,2,?,?,?,4,2,50,85,2,2,3,2,02208,00000,00000,22,1,530334,38.30,40,24,1,1,3,1,3,3,1,?,?,?,1,1,33.00,6.70,?,?,1,2,00000,00000,00000,11,9,5290409,39.10,164,84,4,1,6,2,2,4,4,1,2,5.00,3,?,48.00,7.20,3,5.30,2,1,02208,00000,00000,1...https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csvhttps://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.names我們不需要下載該數據集,因為在接下來的代碼樣例中會自動下載。在使用Python語言來載入數據集時,將所有的缺失值標記為NaN(而不是使用一個數字),是一種很好的做法。我們可以使用Pandas庫中的read_csv()函數來加載數據集,然後指定「na_values」來載入用「?」符號表示的缺失值。...# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')在加載之後,我們來檢查一下數據,確定所有的「?」都已被標註為NaN。
我們可以列舉出數據集的每一列,觀察下每一列缺失值的數量。...# summarize the number of rows with missing values for each columnfor i in range(dataframe.shape[1]): # count number of rows with missing values n_miss = dataframe[[i]].isnull().sum() perc = n_miss / dataframe.shape[0] * 100 print('> %d, Missing: %d (%.1f%%)' % (i, n_miss, perc))試試下面這一整段的代碼,用來完成數據樣本的載入,並對整個數據集進行概述。# summarize the horse colic datasetfrom pandas import read_csv# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# summarize the first few rowsprint(dataframe.head())# summarize the number of rows with missing values for each columnfor i in range(dataframe.shape[1]): # count number of rows with missing values n_miss = dataframe[[i]].isnull().sum() perc = n_miss / dataframe.shape[0] * 100 print('> %d, Missing: %d (%.1f%%)' % (i, n_miss, perc))我們可以看到所有標記為「?」的缺失值已經被NaN所替代。0 1 2 3 4 5 6 ... 21 22 23 24 25 26 270 2.0 1 530101 38.5 66.0 28.0 3.0 ... NaN 2.0 2 11300 0 0 21 1.0 1 534817 39.2 88.0 20.0 NaN ... 2.0 3.0 2 2208 0 0 22 2.0 1 530334 38.3 40.0 24.0 1.0 ... NaN 1.0 2 0 0 0 13 1.0 9 5290409 39.1 164.0 84.0 4.0 ... 5.3 2.0 1 2208 0 0 14 2.0 1 530255 37.3 104.0 35.0 NaN ... NaN 2.0 2 4300 0 0 2[5 rows x 28 columns]接下來,我們可以看一下關於數據所有列的清單,以及每一列中缺失值的數量和所佔的百分比。
我們可以看到有些列(比如說第1和第2列)沒有缺失值,而有些列(比如說第15和第21列)有很多缺失值,甚至是缺失值佔了大多數。> 0, Missing: 1 (0.3%)> 1, Missing: 0 (0.0%)> 2, Missing: 0 (0.0%)> 3, Missing: 60 (20.0%)> 4, Missing: 24 (8.0%)> 5, Missing: 58 (19.3%)> 6, Missing: 56 (18.7%)> 7, Missing: 69 (23.0%)> 8, Missing: 47 (15.7%)> 9, Missing: 32 (10.7%)> 10, Missing: 55 (18.3%)> 11, Missing: 44 (14.7%)> 12, Missing: 56 (18.7%)> 13, Missing: 104 (34.7%)> 14, Missing: 106 (35.3%)> 15, Missing: 247 (82.3%)> 16, Missing: 102 (34.0%)> 17, Missing: 118 (39.3%)> 18, Missing: 29 (9.7%)> 19, Missing: 33 (11.0%)> 20, Missing: 165 (55.0%)> 21, Missing: 198 (66.0%)> 22, Missing: 1 (0.3%)> 23, Missing: 0 (0.0%)> 24, Missing: 0 (0.0%)> 25, Missing: 0 (0.0%)> 26, Missing: 0 (0.0%)> 27, Missing: 0 (0.0%)現在我們知道了病馬數據集中含有缺失值,接下來看看如何使用統計插補。
用SimpleImputer來進行統計插補scikit-learn機器學習工具庫提供SimpleImputer類來支持數據缺失值插補。在這一章節,我們會探索如何高效地使用SimpleImputer。SimpleImputer數據轉換SimpleImputer 是一個數據轉換工具,基於每一列所計算出的統計量類型進行初始配置,例如平均值。...# define imputerimputer = SimpleImputer(strategy='mean')接下來這個插補器會適配數據集,並計算每一列的統計量。...# fit on the datasetimputer.fit(X)這個適配的插補器會被應用於數據集上,創建一個數據集複本,複本中每一列的缺失值都已經被統計量值所替換。...# transform the datasetXtrans = imputer.transform(X)我們可以將這一工具用在病馬數據集上,先後顯示下轉換前和轉換後的缺失值總數,從而確認這個方法是有效的。# statistical imputation transform for the horse colic datasetfrom numpy import isnanfrom pandas import read_csvfrom sklearn.impute import SimpleImputer# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# split into input and output elementsdata = dataframe.valuesX, y = data[:, :-1], data[:, -1]# print total missingprint('Missing: %d' % sum(isnan(X).flatten()))# define imputerimputer = SimpleImputer(strategy='mean')# fit on the datasetimputer.fit(X)# transform the datasetXtrans = imputer.transform(X)# print total missingprint('Missing: %d' % sum(isnan(Xtrans).flatten()))執行示例代碼,首次加載數據集時缺失值的總數為1605。
當轉換工具完成配置、適配和執行三步後,新數據集的結果中已經不再存在缺失值,這說明這個功能達到了我們的預期。
SimpleImputer 和模型評估
在評估機器學習模型方面,使用K折交叉驗證是一種不錯的方法。為了正確地使用缺失值插補方法,避免出現數據洩露的情況,這要求被計算的統計量範圍僅僅針對訓練集的每一列,然後再應用於每一折的訓練數據和測試數據上。如果我們利用重採樣的方法來調參,或者用於評估模型的性能,缺失值插補需要包含在重採樣過程之內。——源自2013年出版的《Applied Predictive Modeling》,第42頁書籍地址:https://amzn.to/3b2LHTL這可以在創造建模流水線(Pipeline)過程中完成,其中第一步就是缺失值插補,第二步才是模型。這一過程可以利用Pipeline類。比如說,下面的Pipeline 使用了 SimpleImputer 方法,將平均值作為統計策略,隨後利用了隨機森林模型。...# define modeling pipelinemodel = RandomForestClassifier()imputer = SimpleImputer(strategy='mean')pipeline = Pipeline(steps=[('i', imputer), ('m', model)])針對病馬數據集,利用平均值進行缺失值插補和隨機森林模型的建模流水線,外加使用10折交叉驗證,我們可以評估下上述內容結合後所呈現的效果。# evaluate mean imputation and random forest for the horse colic datasetfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.impute import SimpleImputerfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.pipeline import Pipeline# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# split into input and output elementsdata = dataframe.valuesX, y = data[:, :-1], data[:, -1]# define modeling pipelinemodel = RandomForestClassifier()imputer = SimpleImputer(strategy='mean')pipeline = Pipeline(steps=[('i', imputer), ('m', model)])# define model evaluationcv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1)# evaluate modelscores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1, error_score='raise')print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))正確地執行上面的示例,每一折交叉驗證過程中都有使用缺失值插補。
流水線用來評估三次重複10折交叉驗證的效果,得到的結果是三次分類的準確率平均值約為84.2%,成績不錯。Mean Accuracy: 0.842 (0.049)
比較不同的插補統計量
我們利用「均值」的統計策略來插補缺失值,這個方法對於該數據集來說是好是壞呢?答案是,如果我們是隨意選擇一種方法的話,我們肯定無法來評價它的好壞。我們可以設計一個實驗,檢測每種統計策略,通過比較均值、中位數、眾數(更常用)和常數(0)四種策略,得出哪種策略對這個數據集是最好的策略。每個方法的平均準確率可以用作比較的依據。# compare statistical imputation strategies for the horse colic datasetfrom numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.impute import SimpleImputerfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.pipeline import Pipelinefrom matplotlib import pyplot# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# split into input and output elementsdata = dataframe.valuesX, y = data[:, :-1], data[:, -1]# evaluate each strategy on the datasetresults = list()strategies = ['mean', 'median', 'most_frequent', 'constant']for s in strategies: # create the modeling pipeline pipeline = Pipeline(steps=[('i', SimpleImputer(strategy=s)), ('m', RandomForestClassifier())]) # evaluate the model cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=1) scores = cross_val_score(pipeline, X, y, scoring='accuracy', cv=cv, n_jobs=-1) # store results results.append(scores) print('>%s %.3f (%.3f)' % (s, mean(scores), std(scores)))# plot model performance for comparisonpyplot.boxplot(results, labels=strategies, showmeans=True)pyplot.xticks(rotation=45)pyplot.show()執行上面的示例代碼,利用重複交叉驗證方法,評估作用在病馬數據集的每種統計插補策略。
你所得到的特定結果可能會非常多樣化,這歸咎於學習算法的隨機性。你可以嘗試去多次執行這段代碼。每一種統計策略所得到的平均準確率結果如下。結果顯示利用常數(例如0)作為填充值的效果最佳,準確率為86.7%,優於其他結果。>mean 0.851 (0.053)>median 0.844 (0.052)>most_frequent 0.838 (0.056)>constant 0.867 (0.044)在執行完代碼之後,繪製一個盒須圖來表示所對應的結果集,讓我們來看一下結果的分布,從而用對其進行比較。
我們可以清楚地看到用常數來進行缺失值填充的統計策略,所得到的準確率優於其他策略。在病馬數據集上利用不同統計策略的缺失值填充後所得模型結果的盒須圖
在進行預測時的SimpleImputer轉換我們可能希望創作一個最終的模型流水線,利用的是常數填充缺失值的方式,使用隨機森林算法,對新數據進行預測。我們可以先定義一個流水線,然後在所有可用數據上進行擬合,最後用predict() 函數進行轉換,把新數據作為一個參數。重要的是,新數據中每一行的缺失值必須用NaN來表示。...# define new datarow = [2,1,530101,38.50,66,28,3,3,nan,2,5,4,4,nan,nan,nan,3,5,45.00,8.40,nan,nan,2,2,11300,00000,00000]# constant imputation strategy and prediction for the hose colic datasetfrom numpy import nanfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.impute import SimpleImputerfrom sklearn.pipeline import Pipeline# load dataseturl = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# split into input and output elementsdata = dataframe.valuesX, y = data[:, :-1], data[:, -1]# create the modeling pipelinepipeline = Pipeline(steps=[('i', SimpleImputer(strategy='constant')), ('m', RandomForestClassifier())])# fit the modelpipeline.fit(X, y)# define new datarow = [2,1,530101,38.50,66,28,3,3,nan,2,5,4,4,nan,nan,nan,3,5,45.00,8.40,nan,nan,2,2,11300,00000,00000]# make a predictionyhat = pipeline.predict([row])# summarize predictionprint('Predicted Class: %d' % yhat[0])針對一行帶有以NaN來標識缺失值的新數據,分類預測順利完成。
總結在這篇教程中,你找到了如何使用統計策略在機器學習中進行數據缺失值填充。缺失值必須以NaN來標識,可以計算出一列數據的統計值,然用其來替換缺失值。
如何載入一份帶有缺失值的CSV文件,並用NaN來標識缺失值,展現出每一列的缺失值數量和百分比。
如何用統計策略來填充缺失值,作為數據準備方法中的一個步驟,用於評估模型和用最終模型和新數據來擬合預測結果。
作者簡介Jason Brownlee,機器學習專業博士,通過親自動手寫教程的方式來指導開發人員如何使用現代機器學習方法來取得結果。原文標題:
Statistical Imputation for Missing Values in Machine Learning
原文連結:
https://machinelearningmastery.com/statistical-imputation-for-missing-values-in-machine-learning/
吳振東,法國洛林大學計算機與決策專業碩士。現從事人工智慧和大數據相關工作,以成為數據科學家為終生奮鬥目標。來自山東濟南,不會開挖掘機,但寫得了Java、Python和PPT。
工作內容:需要一顆細緻的心,將選取好的外文文章翻譯成流暢的中文。如果你是數據科學/統計學/計算機類的留學生,或在海外從事相關工作,或對自己外語水平有信心的朋友歡迎加入翻譯小組。
你能得到:定期的翻譯培訓提高志願者的翻譯水平,提高對於數據科學前沿的認知,海外的朋友可以和國內技術應用發展保持聯繫,THU數據派產學研的背景為志願者帶來好的發展機遇。
其他福利:來自於名企的數據科學工作者,北大清華以及海外等名校學生他們都將成為你在翻譯小組的夥伴。
點擊文末「閱讀原文」加入數據派團隊~
轉載須知
如需轉載,請在開篇顯著位置註明作者和出處(轉自:數據派ID:DatapiTHU),並在文章結尾放置數據派醒目二維碼。有原創標識文章,請發送【文章名稱-待授權公眾號名稱及ID】至聯繫郵箱,申請白名單授權並按要求編輯。
發布後請將連結反饋至聯繫郵箱(見下方)。未經許可的轉載以及改編者,我們將依法追究其法律責任。
點擊「閱讀原文」擁抱組織