数据缺失处理的一些技术
作者:互联网
本文参考自:https://www.kaggle.com/code/residentmario/simple-techniques-for-missing-data-imputation/data
数据亦来源该页
样本中的数据缺失是ML界非常常见的问题,本文就这问题进行讨论。
使用 MissingNo 查看数据
import pandas as pd
import numpy as np
import tensorflow as tfimport missingno as msno
df = pd.read_csv('../../datasets/recipeData.csv', encoding='latin-1').set_index("BeerID")
MissingNo
是常用的观察缺失数据的库,包含了多种图可以观测缺失数据情况。
msno.matrix(df)
msno.bar(df)
drop
处理缺失数据的一个最简单思路就是把缺失的行drop掉,对于非常小样本的缺失可以这么做。
可以用dropna()
丢掉缺失行
len(df), len(df.dropna())
(73861, 757)
可以看到对于本数据,dropna会丢掉绝大多数行,并不适用。
还有一种思路,对于数据缺失非常严重的feature,往往不再具有参考意义,可以drop掉
df.drop(['PrimingMethod', 'PrimingAmount'], axis='columns')
简单插补
简单的数据插补有均值插补,众数插补,pandas自带的方法就能很简单地实现。
df['MashThickness'].isnull().sum(), df['MashThickness'].fillna(df['MashThickness'].mean()).isnull().sum()
df['MashThickness'].mean(), df['MashThickness'].fillna(df['MashThickness'].mean()).mean()
除此之外,sklearn.preprocessing
也带了简单的插补方法。
from sklearn.preprocessing import Imputer
imputer = Imputer(strategy="median")
imputer.fit(df)
sklearn提供了SimpleImputer
,impute.IterativeImputer
,MissingIndicator
(用于二进制),KNNImputer
4种插补模型
模型插补
数据用于机器学习,而机器学习同样可以用于数据填补。
!如果我们以缺失数据的列作为目标变量,以完整数据的现有列作为预测变量,那么我们可以以完整记录作为训练和测试数据集,以不完整数据的记录作为泛化目标,构建一个机器学习模型。这是一个完全确定的机器学习问题。
用Linear Regression做该数据的插补:
# Format the data for applying ML to it.
popular_beer_styles = (pd.get_dummies(df['Style']).sum(axis='rows') > (len(df) / 100)).where(lambda v: v).dropna().index.values
dfc = (df
.drop(['PrimingMethod', 'PrimingAmount', 'UserId', 'PitchRate', 'PrimaryTemp', 'StyleID', 'Name', 'URL'], axis='columns')
.dropna(subset=['BoilGravity'])
.pipe(lambda df: df.join(pd.get_dummies(df['BrewMethod'], prefix='BrewMethod')))
.pipe(lambda df: df.join(pd.get_dummies(df['SugarScale'], prefix='SugarScale')))
.pipe(lambda df: df.assign(Style=df['Style'].map(lambda s: s if s in popular_beer_styles else 'Other')))
.pipe(lambda df: df.join(pd.get_dummies(df['Style'], prefix='Style')))
.drop(['BrewMethod', 'SugarScale', 'Style'], axis='columns')
)
c = [c for c in dfc.columns if c != 'MashThickness']
X = dfc[dfc['MashThickness'].notnull()].loc[:, c].values
y = dfc[dfc['MashThickness'].notnull()]['MashThickness'].values
yy = dfc[dfc['MashThickness'].isnull()]['MashThickness'].values
# Apply a regression approach to imputing the mash thickness.
from sklearn.linear_model import LinearRegression
from sklearn.model_selection import KFold
from sklearn.metrics import r2_score
import numpy as np
np.random.seed(42)
kf = KFold(n_splits=4)
scores = []
for train_index, test_index in kf.split(X):
X_train, X_test = X[train_index], X[test_index]
y_train, y_test = y[train_index], y[test_index]
clf = LinearRegression()
clf.fit(X_train, y_train)
y_test_pred = clf.predict(X_test)
scores.append(r2_score(y_test, y_test_pred))
print(scores)
[0.012942533393265787, 0.009359944248067964, 0.00924054218885928, -0.00039579117668386843]
其中r2_score
是一个可以评价Linear Regression较baseline的拟合效果的评价指标,其绝对值约接近于0代表拟合效果更好。
Maximum Likelihood Estimator(MLE)
简单的方法容易实现,但可能导致高偏差。模型imputation方法更有挑战性,但它仍然是现成的,它在向数据集引入偏差方面仍然存在问题。
在统计学中,Maximum Likelihood Estimator是对感兴趣的分布的任何统计估计器,其特性是使该数据的“似然函数”最大化。
回想一下,统计估计值取随机样本数据,并试图通过从样本中一般化来解释总体分布。例如,∑(y)/len(y)
是一组数据y平均值的估计值。它是MLE,因为它没有任何偏差:它收敛于分布的真实均值(给定足够多的样本)。对于大多数问题,MLE估计器是构建最简单的估计器。但有时MLE估计器是不可能的,在其他情况下,估计器中的一些偏差是有用的(如果你知道一些模型不知道的东西;见如正则化)。
最大似然估计是对缺失数据进行的最大似然估计。首先,用数据集中的完整记录作为预测变量,用包含缺失值的变量作为目标,构建一个最大似然估计器。然后,对于每个包含缺失数据的记录,从您生成的分布中提取一个值,该值使用数据的已知依赖值进行参数化。
这种解决这个问题的纯统计方法在更普遍的情况下具有统计模型的缺点,因为它依赖于你在估计器中使用的概率分布。如果你期望数据是正态分布,你可能会拟合一个正态分布的数据。如果是伯努利分布,你可以拟合伯努利分布。
MultiImpute - fancyimpute
上述讨论的插补都是"SimpleImpute",而Impute可以用Multiple Impute的思路,融合多个插补器达到更好的Impute效果。
其中一个广泛使用的方法称为MICE,以下是它的执行方法:
-
对数据集中每一个缺失的值进行简单的估算,例如估算平均值。这些平均imputation可以被认为是“占位符”。
-
“占位符”对一个变量(“var”)的平均imputation设置为"Missing"。
-
将步骤2中变量var的观测值对归算模型中的其他变量进行回归,该模型可能包含也可能不包含数据集中的所有变量。也就是说,“var”是回归模型中的因变量,其他变量都是回归模型中的自变量。
-
然后,“var”的缺失值被回归模型的预测(imputation)所取代。当“var”随后被用作其他变量回归模型中的自变量时,观察值和这些估算值都将被使用。
-
然后对每个缺少数据的变量重复步骤2-4。通过每个变量的循环构成了一次迭代或“循环”。在一个周期结束时,所有缺失的值都被反映数据中观察到的关系的回归预测所取代。
-
步骤2到步骤4重复若干个周期,每一个周期都更新估算。在这些循环结束时,保留最后的imputation,得到一个imputation数据集。一般来说10个周期;但对于不同条件下的数据输入,如何确定最优循环数还需要研究。这个想法是,在周期结束时,控制imputations的参数分布(例如,回归模型中的系数)应该在趋于稳定的意义上趋于收敛。
fancyimpute
fancyimpute
是一个可以用于插补的库,包含了均值,众数,KNN,Iterative,MICE等多种插补方法。
from fancyimpute import KNN, NuclearNormMinimization, SoftImpute, BiScaler
# X is the complete data matrix
# X_incomplete has the same values as X except a subset have been replace with NaN
# Use 3 nearest rows which have a feature to fill in each row's missing features
X_filled_knn = KNN(k=3).fit_transform(X_incomplete)
# matrix completion using convex optimization to find low-rank solution
# that still matches observed values. Slow!
X_filled_nnm = NuclearNormMinimization().fit_transform(X_incomplete)
# Instead of solving the nuclear norm objective directly, instead
# induce sparsity using singular value thresholding
X_incomplete_normalized = BiScaler().fit_transform(X_incomplete)
X_filled_softimpute = SoftImpute().fit_transform(X_incomplete_normalized)
# print mean squared error for the imputation methods above
nnm_mse = ((X_filled_nnm[missing_mask] - X[missing_mask]) ** 2).mean()
print("Nuclear norm minimization MSE: %f" % nnm_mse)
softImpute_mse = ((X_filled_softimpute[missing_mask] - X[missing_mask]) ** 2).mean()
print("SoftImpute MSE: %f" % softImpute_mse)
knn_mse = ((X_filled_knn[missing_mask] - X[missing_mask]) ** 2).mean()
print("knnImpute MSE: %f" % knn_mse)
标签:处理,df,MashThickness,test,import,数据,缺失 来源: https://www.cnblogs.com/Asp1rant/p/16372310.html