機器學習 第4篇:資料預處理(sklearn 插補缺失值)

悅光陰發表於2020-12-29

由於各種原因,現實世界中的許多資料集都包含缺失值,通常把缺失值編碼為空白,NaN或其他佔位符。但是,此類資料集與scikit-learn估計器不相容,這是因為scikit-learn的估計器假定陣列中的所有值都是數字,並且都存在有價值的含義。如果必須使用不完整資料集,那麼處理缺失資料的基本策略是丟棄包含缺失值的整個行和/或列,但是,這是以丟失有價值的資料為代價的(即使資料不完整),更好的策略是估算缺失值,從資料的已知部分推斷出缺失值,這就是插補(imputation)。

單變數插補法(univariate imputation),僅使用第i個特徵維度中的非缺失值來插補第i個特徵維度中的值。相比之下,多變數插補演算法(multivariate imputation)會使用整個可用特徵維度集來估算缺失值。

一,單變數插補

在sklearn包中,使用SimpleImputer估算器來實現單變數插補,單變數插補的處理策略(由strategy引數制定)有四個:mean,median,most_frequent和constant(搭配fill_value引數使用)。其中,mean和median分別表示使用均值和中位數來插補缺失值;對於定性資料,可以使用most_frequent(眾數)來插補缺失值。

>>> import numpy as np
>>> from sklearn.impute import SimpleImputer
>>> imp = SimpleImputer(missing_values=np.nan, strategy='mean')
>>> imp.fit([[1, 2], [np.nan, 3], [7, 6]])
SimpleImputer()
>>> X = [[np.nan, 2], [6, np.nan], [7, 6]]
>>> print(imp.transform(X))
[[4.          2.        ]
 [6.          3.666...]
 [7.          6.        ]]

二,多變數插補

在scikit-learn包中,多變數插補使用IterativeImputer估算器來實現,該估算器把含有缺失值的每個特徵建模為其他特徵的函式,並使用該估算值進行插補。

多變數插補法以迭代迴圈的方式進行:

  • 在每個步驟中,將特徵列指定為輸出y,將其他特徵列視為輸入X。
  • 把迴歸器擬合到已知的y的(X,y)上。
  • 然後,使用迴歸器預測y的缺失值。
  • 針對每個特徵以迭代方式完成此操作,然後在max_iter插補回閤中重複此操作。
  • 返回最後一輪估算的結果。

注意:多變數插補估算器目前仍處於試驗階段:預設引數或行為可能會更改。 解決以下問題將有助於穩定IterativeImputer:

  • 收斂標準(#14338):IterativeImputer不會收斂,事實上,收斂準則似乎不會隨著迭代而下降。
  • 預設估計量(#13286):使用正則化最小二乘模型進行迭代插補與使用NMF進行插補大致相同。 取而代之的是,至少在sample_posterior = False的情況下,否則,我們應該使用RandomForestRegressor作為IterativeImputer中的預設迴歸器。
  • 隨機狀態的使用 (#15611):通過random_state指定RandomState物件,來保證結果可重複,有些跟scikit-learn相相容的模組可能不相容RandomState物件。

要使用多變數插補,需要顯式匯入enable_iterative_imputer。

>>> import numpy as np
>>> from sklearn.experimental import enable_iterative_imputer
>>> from sklearn.impute import IterativeImputer
>>> imp = IterativeImputer(max_iter=10, random_state=0)
>>> imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]])
IterativeImputer(random_state=0)
>>> X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]]
>>> # the model learns that the second feature is double the first
>>> print(np.round(imp.transform(X_test)))
[[ 1.  2.]
 [ 6. 12.]
 [ 3.  6.]]

注意,IterativeImputer 返回單個插補而不是多個插補,但是,當設定sample_posterior = True時,通過把IterativeImputer重複應用於具有不同隨機種子的同一資料集,也可以將其用於多個插補。

三,最鄰近插補

KNNImputer 類提供了使用k最近鄰方法來填充缺失值的插補。預設情況下,使用nan_euclidean_distances作為從存在缺失值的特徵中計算歐氏距離的度量標準,用歐氏距離來查詢最近的鄰居。從存在缺失值的特徵中選取最鄰近的n_neighbors個鄰居,使用這n_neighbors個鄰居的值估算特徵缺失的值。鄰居的特徵被均勻地平均,或通過到每個鄰居的距離加權。如果一個樣本有多個特徵缺失,那麼該樣本的鄰居可能會有所不同,具體取決於要插補的特定特徵。當可用鄰居的數量小於n_neighbors,並且與訓練集之間沒有定義的距離時,在插補過程中將使用該特徵的訓練集的平均值。如果存在至少一個具有定義距離的鄰居,則在插補期間將使用其餘鄰居的加權或未加權平均值。如果訓練中始終缺少某個特徵,則在變換過程中將其刪除。

以下程式碼段演示瞭如何使用具有缺失值的樣本的兩個最近鄰居的平均特徵值替換編碼為np.nan的缺失值:

>>> import numpy as np
>>> from sklearn.experimental import enable_iterative_imputer
>>> from sklearn.impute import IterativeImputer
>>> imp = IterativeImputer(max_iter=10, random_state=0)
>>> imp.fit([[1, 2], [3, 6], [4, 8], [np.nan, 3], [7, np.nan]])
IterativeImputer(random_state=0)
>>> X_test = [[np.nan, 2], [6, np.nan], [np.nan, 6]]
>>> # the model learns that the second feature is double the first
>>> print(np.round(imp.transform(X_test)))
[[ 1.  2.]
 [ 6. 12.]
 [ 3.  6.]]

 

參考文件:

6.4. Imputation of missing values

相關文章