
在機器學習中,一旦我們的資料集缺少了值,這就可能直接導緻我們的算法出現問題,甚至會影響我們的模型準确率。
是以,在對預測任務模組化之前,最好識别并替換輸入資料中每個列的缺失值。這稱為缺失資料插補,簡稱插補。
一種複雜的方法包括定義一個模型,将每個缺失的特征作為所有其他特征的函數進行預測,并多次重複這一估計特征值的過程。重複允許在預測缺失值的後續疊代中使用其他特征的優化估計值作為輸入。這通常被稱為疊代插補。
在本文中,你将學會如何在機器學習中使用疊代插補政策來處理缺失的資料。
看完本文後,你将知道:
- 缺少的值必須用NaN值标記,并且可以用疊代估計值替換。
- 如何加載缺少值的CSV值,并用NaN值标記缺少的值,并報告每列缺少值的數量和百分比。
- 在評估模型和拟合最終模型對新資料進行預測時,如何用疊代模型估算缺失值作為資料準備方法。
概述
本文分為三部分:
- 疊代插補
- Horse Colic 資料集
- IterativeImputer類的疊代插補
IterativeImputer 資料轉換
IterativeImputer與模型評估
IterativeImputer與不同的進位順序
IterativeImputer與不同的疊代次數
預測時的IterativeImputer變換
疊代插補
資料集可能缺少值。
這些資料行中不存在該行中的一個或多個值或列。也有可能這些值完全丢失了,或者可能标記有特殊字元或值,例如問号“?”.
值可能由于許多原因丢失,但是,通常都是特定于問題域的,并且可能包括諸如損壞的度量或不可用的原因。
大多數機器學習算法都需要數字輸入值,并且資料集中的每一行和每一列都有一個值。是以,缺少值可能會導緻機器學習算法出現很多問題。
是以,識别資料集中缺少的值并用數值替換它們,這是很常見的方法。這稱為資料插補或缺失資料插補。
一種估算缺失值的方法是使用疊代估算模型。
疊代插補是指将每個特征模組化為其他特征函數的過程,例如預測缺失值的回歸問題。每個特征都是依次輸入的,允許在預測後續特征時将先前的輸入值用作模型的一部分。
這就是疊代的過程,因為這個過程需要重複多次,允許在估計所有特征的丢失值時計算丢失值的不斷改進的估計值。
這種方法通常被稱為完全條件規範(FCS)或鍊式方程(MICE)的多元插補。
如果多元分布是資料的合理描述,這種方法是有吸引力的。FCS通過一組條件密度逐變量指定多變量插補模型,每個條件密度對應一個不完全變量。從初始插補開始,FCS通過疊代條件密度得出插補。隻需要很少的疊代次數(比如10-20次)就足夠了。
可以使用不同的回歸算法來估計每個特征的缺失值,盡管使用線性方法是為了簡單起見。過程的疊代通常要保持較小的次數,例如10次。最後,可以考慮按順序處理特征的順序,例如從缺失值最少的特征到缺失值最多的特征。
現在我們已經熟悉了缺少值插補的疊代方法,接下來讓我們看看缺少值的資料集。
Horse Colic 資料集
Horse Colic資料集描述了患有疝氣的馬的醫學特征以及它們是生是死。
有300行,26個輸入變量和一個輸出變量。這是一個二進制分類預測任務,包括預測1如果馬活着,2如果馬死了。
一個簡單的模型可以達到67%的分類準确率,一個性能最好的模型可以通過三次重複10倍的交叉驗證達到85.2%的準确率。這定義了資料集上的預期模組化性能範圍。
對于許多列,資料集都有許多缺少的值,其中每個缺少的值都用問号字元(“?”).
下面提供了資料集中帶有标記的缺失值的行的示例。
2,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...
有關資料集的更多資訊可以通過下方連結了解:
Horse Colic 資料集:https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-
colic.csvHorse Colic 資料集描述:https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.names
不需要下載下傳資料集,因為我們可以在代碼中自動下載下傳。
使用Python在加載的資料集中使用NaN(不是數字)值标記丢失的值是一種最佳實踐。
我們可以使用read_csv()Pandas函數加載資料集,并指定“na_values”來加載'?'丢失,用NaN值标記。
...# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')
加載後,我們可以檢視加載的資料以确認“?“值标記為NaN。
...# 總結前幾行print(dataframe.head())
然後,我們可以枚舉每一列并報告該列缺少值的行數。
...# 總結每列缺少值的行數for i in range(dataframe.shape[1]):# 計算缺少值的行數n_miss = dataframe[[i]].isnull().sum()perc = n_miss / dataframe.shape[0] * 100print('> %d, Missing: %d (%.1f%%)' % (i, n_miss, perc))
下面是加載和彙總資料集的完整代碼示例。
# 總結horse colic資料集from pandas import read_csv# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 總結前幾行print(dataframe.head())# 彙總每列缺少值的行數for i in range(dataframe.shape[1]):# 計算缺少值的行數n_miss = dataframe[[i]].isnull().sum()perc = n_miss / dataframe.shape[0] * 100print('> %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%)
現在我們已經熟悉了缺少值的horse colic資料集,讓我們看看如何進行疊代插補。
IterativeImputer類的疊代插補
scikit-learn 機器學習庫提供了支援疊代插補的 IterativeImputer 類。
在本節中,我們将探讨如何有效地使用 IterativeImputer 類。
1、IterativeImputer類資料轉換
它是一個資料轉換,首先根據用于估計缺失值的方法進行配置。預設情況下,使用BayesianRidge模型,該模型使用所有其他輸入特征的函數。特征按升序填充,從缺失值最少的特征到缺失值最多的特征。
...# 定義imputerimputer = IterativeImputer(estimator=BayesianRidge(), n_nearest_features=None, imputation_order='ascending')
然後,将imputer拟合到資料集。
...# 适配資料集imputer.fit(X)
然後,将imputer應用于資料集中,用于建立資料集的副本,用估計值替換每個列的所有缺失值。
...# 轉換資料集Xtrans = imputer.transform(X)
IterativeImputer 類不能直接使用,因為它是實驗性的。
如果你直接進行使用,會得到如下錯誤:
ImportError: cannot import name 'IterativeImputer'
相反,您必須添加一個額外的import語句,來添加對IterativeImputer類的支援,如下所示:
...from sklearn.experimental import enable_iterative_imputer
我們可以在horse colic資料集上示範它的用法,并通過彙總轉換前後資料集中丢失的值的總數來确認它的作用。
以下為完整的代碼示例:
# horse colic資料集的疊代插補變換from numpy import isnanfrom pandas import read_csvfrom sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputer# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 分成輸入和輸出元素data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# 輸出缺失值print('Missing: %d' % sum(isnan(X).flatten()))# 定義imputerimputer = IterativeImputer()# 适配資料集imputer.fit(X)# 轉換資料集Xtrans = imputer.transform(X)# 輸出全部缺失值print('Missing: %d' % sum(isnan(Xtrans).flatten()))
運作該示例,在加載資料集後,我們發現資料集中丢失的值的總數報告為1,605。
通過配置、調整并執行轉換,生成新的資料集沒有缺少的值。
把每個缺失的值都替換成模型預估的值。
Missing: 1605Missing: 0
2、IterativeImputer類與模型評估
使用k-fold交叉驗證在資料集上評估機器學習模型是一個很好的辦法。
為了正确地應用疊代缺失資料插補,避免資料洩漏,要求每一列的模型僅在訓練資料集上計算,然後應用到資料集中每一個折疊的訓練和測試集上。
這可以通過建立一個模組化通道來實作,第一步是疊代插補,第二步是模型。這可以通過使用Pipeline類來實作。
例如,下面的通道使用具有預設政策的疊代輸入,然後是随機林模型。
...# 定義模組化通道model = RandomForestClassifier()imputer = IterativeImputer()pipeline = Pipeline(steps=[('i', imputer), ('m', model)])
通過重複10次交叉驗證,我們可以對horse colic資料集的輸入資料集和随機森林模組化通道進行評估。
以下為完整的代碼示例:
# horse colic資料集的疊代插補和随機森林評估from numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputerfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.pipeline import Pipeline# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 分成輸入和輸出元素data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# 定義模組化通道model = RandomForestClassifier()imputer = IterativeImputer()pipeline = Pipeline(steps=[('i', imputer), ('m', 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, error_score='raise')print('Mean Accuracy: %.3f (%.3f)' % (mean(scores), std(scores)))
正确運作該示例,将資料插補應用于交叉驗證過程的各個方面。
使用三次重複的10倍交叉驗證對通道進行評估,并得出資料集上的平均分類精度約為81.4%,這是一個不錯的分數。
Mean Accuracy: 0.814 (0.063)
我們如何知道使用預設的疊代政策對這個資料集是好還是差?
答案是我們沒有。
3、IterativeImputer類與不同的插補順序
預設情況下,插補按從缺失值最少的特征到缺失值最多的特征的升序進行。
這是有意義的,因為我們希望在估計大多數值丢失的列的丢失值時有更完整的資料。
然而,我們可以嘗試不同的歸責順序政策,如降序、從右向左(阿拉伯語)、從左向右(羅馬語)和随機。
下面的示例評估并比較每個可用的估算順序配置。
# horse colic資料集疊代插補政策的比較from numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputerfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.pipeline import Pipelinefrom matplotlib import pyplot# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 分成輸入和輸出元素data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# 在資料集上評估每個政策results = list()strategies = ['ascending', 'descending', 'roman', 'arabic', 'random']for s in strategies:# 建立模組化通道pipeline = Pipeline(steps=[('i', IterativeImputer(imputation_order=s)), ('m', RandomForestClassifier())])# 評估模型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)# 存儲結果results.append(scores)print('>%s %.3f (%.3f)' % (s, mean(scores), std(scores)))# 用于比較的繪圖模型性能pyplot.boxplot(results, labels=strategies, showmeans=True)pyplot.xticks(rotation=45)pyplot.show()
通過運作該示例,我們用重複的交叉驗證來評估horse colic資料集上的估算順序。
考慮到學習算法的随機性,你得到的具體結果可能會有所不同,記得多運作幾次。
每種政策得到的平均精度相差不大。結果表明,大多數方法之間的差别不大,降序(與預設相反)效果最好。從右到左(阿拉伯語)順序對該資料集可能更好,準确率約為80.4%。
>ascending 0.801 (0.071)>descending 0.797 (0.059)>roman 0.802 (0.060)>arabic 0.804 (0.068)>random 0.802 (0.061)
在運作結束後,将為每個結果集建立一個框線圖,比較結果如下圖所示。
4、IterativeImputer類與不同的疊代次數
預設情況下, IterativeImputer類需要重複疊代10次。
有可能大量的疊代可能開始偏向或傾斜估計,并且可能優選很少的疊代。過程的疊代次數可以通過“max_iter”參數指定。
評估不同數量的疊代可能很有趣。下面的示例比較“max_iter”從1到20的不同值。
# 比較horse colic資料集的疊代插補次數from numpy import meanfrom numpy import stdfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputerfrom sklearn.model_selection import cross_val_scorefrom sklearn.model_selection import RepeatedStratifiedKFoldfrom sklearn.pipeline import Pipelinefrom matplotlib import pyplot# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 分成輸入和輸出元素data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# 在資料集上評估每個政策results = list()strategies = [str(i) for i in range(1, 21)]for s in strategies:# 建立模組化通道pipeline = Pipeline(steps=[('i', IterativeImputer(max_iter=int(s))), ('m', RandomForestClassifier())])# 評估模型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)# 儲存結果results.append(scores)print('>%s %.3f (%.3f)' % (s, mean(scores), std(scores)))# 用于比較的繪圖模型性能pyplot.boxplot(results, labels=strategies, showmeans=True)pyplot.xticks(rotation=45)pyplot.show()
通過運作該示例,使用重複的交叉驗證來評估 horse colic資料集上的每個疊代次數。
考慮到學習算法的随機性,得出的具體結果可能會有所不同,記得多運作幾次。
結果表明,在這個資料集上,9-12次疊代更有效。
>1 0.820 (0.072)>2 0.813 (0.078)>3 0.801 (0.066)>4 0.817 (0.067)>5 0.808 (0.071)>6 0.799 (0.059)>7 0.804 (0.058)>8 0.809 (0.070)>9 0.812 (0.068)>10 0.800 (0.058)>11 0.818 (0.064)>12 0.810 (0.073)>13 0.808 (0.073)>14 0.799 (0.067)>15 0.812 (0.075)>16 0.814 (0.057)>17 0.812 (0.060)>18 0.810 (0.069)>19 0.810 (0.057)>20 0.802 (0.067)
在運作結束時,将為每個結果集建立一個框線圖,檢視比較的結果。
5、預測時的IterativeImputer變換
我們希望使用疊代插補和随機森林算法建立最終的模組化通道,然後對新資料進行預測。
這可以通過定義通道并在所有可用資料上進行拟合,然後調用predict()函數,将新資料作為參數傳入來實作。
新資料行必須使用NaN值标記任何缺少的值。
...# 定義新資料row = [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]
以下為完整的代碼示例:
# hose-colic資料集的疊代插補政策與預測from numpy import nanfrom pandas import read_csvfrom sklearn.ensemble import RandomForestClassifierfrom sklearn.experimental import enable_iterative_imputerfrom sklearn.impute import IterativeImputerfrom sklearn.pipeline import Pipeline# 加載資料集url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv'dataframe = read_csv(url, header=None, na_values='?')# 分成輸入和輸出元素data = dataframe.valuesX, y = data[:, :-1], data[:, -1]# create the modeling pipelinepipeline = Pipeline(steps=[('i', IterativeImputer()), ('m', RandomForestClassifier())])# 适配模型pipeline.fit(X, y)# 定義新資料row = [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]# 作出預測yhat = pipeline.predict([row])# 總結預測print('Predicted Class: %d' % yhat[0])
運作所示代碼,可以讓模組化通道适配所有可用資料。
定義了一個新的資料行,該行的缺失值用NaNs标記,并進行了分類預測。
Predicted Class: 2
總結
通過學習本文,你将學會如何在機器學習中對丢失的資料使用疊代插補政策。
具體來說,你學到了:
- 缺少的值必須用NaN值标記,并且可以用疊代估計值替換。
- 如何加載缺少值的CSV值,并用NaN值标記缺少的值,并報告每列缺少值的數量和百分比。
- 在評估模型和拟合最終模型對新資料進行預測時,如何用疊代模型估算缺失值作為資料準備方法。
在機器學習的模型中,資料是最關鍵的一環,任何一個資料缺失,最終我們辛辛苦苦做出來的模型,可能得到的結論也會發生天翻地覆的變化,希望以上内容能幫助因為資料問題而煩惱脫發的你!
參考連結:https://machinelearningmastery.com/iterative-imputation-for-missing-values-in-machine-learning/
--END--
喜歡本文的同學,記得轉發+收藏哦~
也歡迎大家關注我們的公衆号:為AI呐喊(weainahan),學習更多AI知識!