数据集可能存在缺失值,这会给许多机器学习算法带来问题。
因此,在对预测任务进行建模之前,最好识别并替换输入数据中每列的缺失值。这称为缺失数据插补,或简称插补。
一种复杂的方法是定义一个模型,将每个缺失特征作为所有其他特征的函数来预测,并多次重复此估计特征值过程。重复允许使用其他特征经过改进的估计值作为后续迭代中预测缺失值的输入。这通常被称为迭代填补。
在本教程中,您将学习如何在机器学习中使用迭代填补策略处理缺失数据。
完成本教程后,您将了解:
- 缺失值必须用 NaN 值标记,并可以用迭代估计的值替换。
- 如何加载带有缺失值的 CSV 文件,用 NaN 值标记缺失值,并报告每列的缺失值数量和百分比。
- 如何在评估模型时使用迭代模型作为数据预处理方法来填补缺失值,以及在拟合最终模型进行新数据预测时如何使用。
开始您的项目,阅读我的新书《机器学习数据准备》,其中包含分步教程和所有示例的Python源代码文件。
让我们开始吧。
- 2020年6月更新:更改了示例中用于预测的列。

机器学习中缺失值的迭代估算
照片由 Gergely Csatari拍摄,部分权利保留。
教程概述
本教程分为三个部分;它们是:
- 迭代填补
- 马疝气数据集
- 迭代填补与 IterativeImputer
- IterativeImputer 数据转换
- IterativeImputer 与模型评估
- IterativeImputer 与不同的填补顺序
- IterativeImputer 与不同的迭代次数
- 进行预测时 IterativeImputer 转换
迭代填补
一个数据集可能包含缺失值。
这些是数据行,其中一个或多个值或该行中的列不存在。这些值可能完全缺失,或者可能用特殊字符或值标记,例如问号“?”。
值可能因许多原因而缺失,通常特定于问题域,可能包括测量损坏或不可用等原因。
大多数机器学习算法需要数值输入,并且数据集中的每一行和每一列都需要存在一个值。因此,缺失值会给机器学习算法带来问题。
因此,识别数据集中缺失值并用数值替换它们是很常见的。这称为数据填补,或缺失数据填补。
填补缺失值的一种方法是使用迭代填补模型。
迭代填补是指一个过程,其中每个特征都作为其他特征的函数进行建模,例如,预测缺失值的回归问题。每个特征按顺序填补,一个接一个,允许使用先前填补的值作为模型的一部分来预测后续特征。
它是迭代的,因为这个过程会重复多次,允许随着所有特征的缺失值被估计,计算出不断改进的缺失值估计。
这种方法通常被称为完全条件规范 (FCS) 或链式方程多变量填补 (MICE)。
如果多元分布是数据的合理描述,则此方法很有吸引力。FCS 通过一组条件密度(每个不完整变量一个)逐个变量地指定多元填补模型。从初始填补开始,FCS 通过在条件密度之间迭代来绘制填补。少量迭代(例如 10-20 次)通常就足够了。
— mice: R 中的链式方程多变量填补,2009。
可以使用不同的回归算法来估计每个特征的缺失值,尽管为了简单起见,通常使用线性方法。该过程的迭代次数通常保持较小,例如 10 次。最后,可以考虑按顺序处理特征的顺序,例如从缺失值最少的特征到缺失值最多的特征。
现在我们熟悉了迭代缺失值填补方法,让我们来看看一个具有缺失值的数据集。
想开始学习数据准备吗?
立即参加我为期7天的免费电子邮件速成课程(附示例代码)。
点击注册,同时获得该课程的免费PDF电子书版本。
马疝气数据集
马疝气数据集描述了患有疝气的马匹的医学特征以及它们是存活还是死亡。
有300行和26个输入变量,一个输出变量。这是一个二元分类预测任务,涉及预测马匹存活为1,死亡为2。
在这个数据集中,我们可以选择预测许多字段。在这种情况下,我们将预测问题是否为手术(列索引23),使其成为一个二元分类问题。
该数据集的许多列都有许多缺失值,其中每个缺失值都用问号字符(“?”)标记。
下面提供了数据集中带有标记缺失值的行示例。
1 2 3 4 5 |
2,1,530101,38.50,66,28,3,3,?,2,5,4,4,?,?,?,3,5,45.00,8.40,?,?,2,2,11300,00000,00000,2 1,1,534817,39.2,88,20,?,?,4,1,3,4,2,?,?,?,4,2,50,85,2,2,3,2,02208,00000,00000,2 2,1,530334,38.30,40,24,1,1,3,1,3,3,1,?,?,?,1,1,33.00,6.70,?,?,1,2,00000,00000,00000,1 1,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 ... |
你可以在此处了解更多关于此数据集的信息:
无需下载数据集,我们将在工作示例中自动下载。
在加载的数据集中使用 Python 将缺失值标记为 NaN(非数字)是一种最佳实践。
我们可以使用 read_csv() Pandas 函数加载数据集,并指定“na_values”以将 '?' 的值加载为缺失值,并用 NaN 值标记。
1 2 3 4 |
... # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv' dataframe = read_csv(url, header=None, na_values='?') |
加载后,我们可以查看加载的数据,以确认“?”值已标记为 NaN。
1 2 3 |
... # 总结前几行 print(dataframe.head()) |
然后我们可以枚举每一列,并报告该列中带有缺失值的行数。
1 2 3 4 5 6 7 |
... # 汇总每列中具有缺失值的行数 for i in range(dataframe.shape[1]): # 计算缺失值行数 n_miss = dataframe[[i]].isnull().sum() perc = n_miss / dataframe.shape[0] * 100 print('> %d, Missing: %d (%.1f%%)' % (i, n_miss, perc)) |
总而言之,下面列出了加载和汇总数据集的完整示例。
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# 总结马疝气数据集 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] * 100 print('> %d, Missing: %d (%.1f%%)' % (i, n_miss, perc)) |
运行该示例首先加载数据集并总结前五行。
我们可以看到,原来用“?”字符标记的缺失值已经被NaN值取代了。
1 2 3 4 5 6 7 8 |
0 1 2 3 4 5 6 ... 21 22 23 24 25 26 27 0 2.0 1 530101 38.5 66.0 28.0 3.0 ... NaN 2.0 2 11300 0 0 2 1 1.0 1 534817 39.2 88.0 20.0 NaN ... 2.0 3.0 2 2208 0 0 2 2 2.0 1 530334 38.3 40.0 24.0 1.0 ... NaN 1.0 2 0 0 0 1 3 1.0 9 5290409 39.1 164.0 84.0 4.0 ... 5.3 2.0 1 2208 0 0 1 4 2.0 1 530255 37.3 104.0 35.0 NaN ... NaN 2.0 2 4300 0 0 2 [5 行 x 28 列] |
接下来,我们可以看到数据集中所有列的列表以及缺失值数量和百分比。
我们可以看到,有些列(例如列索引1和2)没有缺失值,而其他列(例如列索引15和21)有许多甚至大部分缺失值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 |
> 0,缺失:1 (0.3%) > 1,缺失:0 (0.0%) > 2,缺失:0 (0.0%) > 3,缺失:60 (20.0%) > 4,缺失:24 (8.0%) > 5,缺失:58 (19.3%) > 6,缺失:56 (18.7%) > 7,缺失:69 (23.0%) > 8,缺失:47 (15.7%) > 9,缺失:32 (10.7%) > 10,缺失:55 (18.3%) > 11,缺失:44 (14.7%) > 12,缺失:56 (18.7%) > 13,缺失:104 (34.7%) > 14,缺失:106 (35.3%) > 15,缺失:247 (82.3%) > 16,缺失:102 (34.0%) > 17,缺失:118 (39.3%) > 18,缺失:29 (9.7%) > 19,缺失:33 (11.0%) > 20,缺失:165 (55.0%) > 21,缺失:198 (66.0%) > 22,缺失:1 (0.3%) > 23,缺失:0 (0.0%) > 24,缺失:0 (0.0%) > 25,缺失:0 (0.0%) > 26,缺失:0 (0.0%) > 27,缺失:0 (0.0%) |
现在我们熟悉了具有缺失值的马匹疝气数据集,让我们看看如何使用迭代填补。
迭代填补与 IterativeImputer
scikit-learn 机器学习库提供了 IterativeImputer 类,它支持迭代填补。
在本节中,我们将探讨如何有效地使用IterativeImputer 类。
IterativeImputer 数据转换
它是一种数据转换,首先根据用于估计缺失值的方法进行配置。默认情况下,使用 BayesianRidge 模型,该模型使用所有其他输入特征的函数。特征按升序填充,从缺失值最少的特征到缺失值最多的特征。
1 2 3 |
... # 定义插补器 imputer = IterativeImputer(estimator=BayesianRidge(), n_nearest_features=None, imputation_order='ascending') |
然后将填补器拟合到数据集上。
1 2 3 |
... # 拟合数据集 imputer.fit(X) |
然后将拟合的填补器应用于数据集,创建数据集的副本,其中每列的缺失值都被估计值替换。
1 2 3 |
... # 转换数据集 Xtrans = imputer.transform(X) |
IterativeImputer 类不能直接使用,因为它尚处于实验阶段。
如果尝试直接使用它,您将收到如下错误:
1 |
ImportError: cannot import name 'IterativeImputer' |
相反,您必须添加一个额外的导入语句来添加对 IterativeImputer 类的支持,如下所示:
1 2 |
... from sklearn.experimental import enable_iterative_imputer |
我们可以通过在转换前后汇总数据集中缺失值的总数,来演示其在马疝气数据集上的用法并确认其有效性。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
# 马匹疝气数据集的迭代填补转换 from numpy import isnan from pandas import read_csv from sklearn.experimental import enable_iterative_imputer from 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.values ix = [i for i in range(data.shape[1]) if i != 23] X, y = data[:, ix], data[:, 23] # 打印总缺失值 print('Missing: %d' % sum(isnan(X).flatten())) # 定义插补器 imputer = IterativeImputer() # 拟合数据集 imputer.fit(X) # 转换数据集 Xtrans = imputer.transform(X) # 打印总缺失值 print('Missing: %d' % sum(isnan(Xtrans).flatten())) |
运行该示例首先加载数据集并报告数据集中缺失值的总数为1,605。
转换被配置、拟合和执行,结果的新数据集没有缺失值,确认了它的执行正如我们所预期的。
每个缺失值都被估计模型的值替换。
1 2 |
缺失:1605 缺失:0 |
IterativeImputer 与模型评估
使用k折交叉验证在数据集上评估机器学习模型是一种良好的实践。
要正确应用迭代缺失数据填补并避免数据泄露,需要仅在训练数据集上计算每个列的模型,然后为数据集的每个折叠应用于训练集和测试集。
这可以通过创建建模管道来实现,其中第一步是迭代填补,第二步是模型。这可以使用 Pipeline 类来实现。
例如,下面的Pipeline 使用具有默认策略的IterativeImputer,然后是随机森林模型。
1 2 3 4 5 |
... # 定义建模管道 model = RandomForestClassifier() imputer = IterativeImputer() pipeline = Pipeline(steps=[('i', imputer), ('m', model)]) |
我们可以使用重复的 10 折交叉验证来评估马匹疝气数据集的填补数据集和随机森林建模管道。
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 |
# 评估马匹疝气数据集的迭代填补和随机森林 from numpy import mean from numpy import std from pandas import read_csv from sklearn.ensemble import RandomForestClassifier from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from 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.values ix = [i for i in range(data.shape[1]) if i != 23] X, y = data[:, ix], data[:, 23] # 定义建模管道 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 折交叉验证的三次重复进行评估,并报告数据集的平均分类准确率约为 86.3%,这是一个不错的得分。
1 |
平均准确率:0.863 (0.057) |
我们如何知道使用默认的迭代策略对这个数据集是好的或最好的?
答案是我们不知道。
IterativeImputer 与不同的填补顺序
默认情况下,填补按升序进行,从缺失值最少的特征到缺失值最多的特征。
这是有道理的,因为当估计缺失值(对于值大部分缺失的列)时,我们希望拥有更完整的数据。
尽管如此,我们可以尝试不同的填补顺序策略,例如降序、从右到左(阿拉伯语)、从左到右(罗马语)和随机。
下面的示例评估并比较了每种可用的填补顺序配置。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# 比较马匹疝气数据集的迭代填补策略 from numpy import mean from numpy import std from pandas import read_csv from sklearn.ensemble import RandomForestClassifier from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline from matplotlib import pyplot # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv' dataframe = read_csv(url, header=None, na_values='?') # 分割输入和输出元素 data = dataframe.values ix = [i for i in range(data.shape[1]) if i != 23] X, y = data[:, ix], data[:, 23] # 评估数据集上的每种策略 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() |
运行此示例使用重复交叉验证在马匹疝气数据集上评估每个填补顺序。
注意:您的结果可能因算法或评估程序的随机性,或数值精度的差异而有所不同。请考虑多次运行示例并比较平均结果。
沿途报告了每个策略的平均准确率。结果表明大多数方法之间差异不大,其中降序(与默认相反)表现最佳。结果表明,对于此数据集,阿拉伯语(从右到左)或罗马语顺序可能更好,准确率约为 87.2%。
1 2 3 4 5 |
>ascending 0.867 (0.049) >descending 0.871 (0.052) >roman 0.872 (0.052) >arabic 0.872 (0.052) >random 0.870 (0.060) |
运行结束时,会为每组结果创建一个箱线图和须状图,以便比较结果的分布。

应用于马匹疝气数据集的填补顺序策略的箱形图
IterativeImputer 与不同的迭代次数
默认情况下,IterativeImputer 将重复迭代 10 次。
大量的迭代可能会开始使估计值产生偏差或倾斜,而很少的迭代可能是首选。可以通过“max_iter”参数指定过程的迭代次数。
评估不同的迭代次数可能很有趣。下面的示例比较了“max_iter”从 1 到 20 的不同值。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 |
# 比较马匹疝气数据集的迭代填补迭代次数 from numpy import mean from numpy import std from pandas import read_csv from sklearn.ensemble import RandomForestClassifier from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from sklearn.model_selection import cross_val_score from sklearn.model_selection import RepeatedStratifiedKFold from sklearn.pipeline import Pipeline from matplotlib import pyplot # 加载数据集 url = 'https://raw.githubusercontent.com/jbrownlee/Datasets/master/horse-colic.csv' dataframe = read_csv(url, header=None, na_values='?') # 分割输入和输出元素 data = dataframe.values ix = [i for i in range(data.shape[1]) if i != 23] X, y = data[:, ix], data[:, 23] # 评估数据集上的每种策略 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() |
运行此示例使用重复交叉验证在马匹疝气数据集上评估每个迭代次数。
注意:您的结果可能因算法或评估程序的随机性,或数值精度的差异而有所不同。请考虑多次运行示例并比较平均结果。
结果表明,对于此数据集,很少的迭代次数(例如 3 次)可能与 9-12 次迭代一样有效或更有效。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
>1 0.872 (0.053) >2 0.872 (0.052) >3 0.874 (0.051) >4 0.868 (0.050) >5 0.870 (0.050) >6 0.871 (0.051) >7 0.867 (0.055) >8 0.869 (0.054) >9 0.867 (0.054) >10 0.871 (0.051) >11 0.876 (0.047) >12 0.870 (0.053) >13 0.870 (0.056) >14 0.871 (0.053) >15 0.868 (0.057) >16 0.870 (0.053) >17 0.874 (0.051) >18 0.873 (0.054) >19 0.866 (0.054) >20 0.866 (0.051) |
运行结束时,会为每组结果创建一个箱线图和须状图,以便比较结果的分布。

应用于马匹疝气数据集的填补迭代次数的箱形图
进行预测时 IterativeImputer 转换
我们可能希望创建一个最终的建模管道,其中包含迭代填补和随机森林算法,然后对新数据进行预测。
这可以通过定义管道并将其拟合到所有可用数据,然后调用predict() 函数,并将新数据作为参数传递来实现。
重要的是,新数据行必须使用 NaN 值标记任何缺失值。
1 2 3 |
... # 定义新数据 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, 11300, 00000, 00000, 2] |
完整的示例如下所示。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
# 马匹疝气数据集的迭代填补策略和预测 from numpy import nan from pandas import read_csv from sklearn.ensemble import RandomForestClassifier from sklearn.experimental import enable_iterative_imputer from sklearn.impute import IterativeImputer from 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.values X, y = data[:, :-1], data[:, -1] # 创建建模管道 pipeline = 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, 11300, 00000, 00000, 2] # 进行预测 yhat = pipeline.predict([row]) # 总结预测 print('Predicted Class: %d' % yhat[0]) |
运行该示例会在所有可用数据上拟合建模管道。
定义了一个新的数据行,其中缺失值标记为 NaN,并进行了分类预测。
1 |
预测类别:2 |
进一步阅读
如果您想深入了解,本节提供了更多关于该主题的资源。
相关教程
论文
- mice: R 中的链式方程多变量填补, 2009.
- 一种适合用电子计算机使用的多变量数据缺失值估计方法, 1960.
API
数据集 (Dataset)
总结
在本教程中,您学习了如何在机器学习中使用迭代填补策略处理缺失数据。
具体来说,你学到了:
- 缺失值必须用 NaN 值标记,并可以用迭代估计的值替换。
- 如何加载带有缺失值的 CSV 文件,用 NaN 值标记缺失值,并报告每列的缺失值数量和百分比。
- 如何在评估模型时使用迭代模型作为数据预处理方法来填补缺失值,以及在拟合最终模型进行新数据预测时如何使用。
你有什么问题吗?
在下面的评论中提出你的问题,我会尽力回答。
嗨,Jason,
您不知道我有多享受这一切。我正在学习机器学习,这为我的数据清理知识增添了很多内容。非常感谢!
谢谢!
你好 Jason,
我有一个关于线性回归的问题。
有没有办法一步步解决线性回归:即有没有一个流程
来处理线性回归问题(从何开始到结束)。
您有简单的线性回归示例吗?
谢谢,
Marco
是的,这个通用过程
https://machinelearning.org.cn/start-here/#process
通过这篇文章学习了一种新的数据填补技术。非常感谢 Jason。以前我只用可用值的平均值或中位数来替换缺失值。我一定会将这项技术应用到我即将进行的项目中。
谢谢,很高兴听到这个!
感谢您关于 IterativeImputer 的教程,我从这篇帖子中学到了很多。
我有一个关于缺失值主题的问题:与模式或平均值相比,使用 IterativeImputer 填充缺失值通常(在大多数情况下)效果更好吗?
我尝试了 horse_colic 数据集,但在我的案例中,
mode
和mean
的效果比IterativeImputer
更好。尽管如此,我看到很多帖子选择IterativeImputer
作为处理缺失值的默认工具。我认为人们使用它一定是因为它效果更好。以防万一您感兴趣,我尝试在数据上使用
xgboost
。使用IterativeImputer
我获得了0.831(0.048)
的准确率得分,而使用mean
获得了0.848 (0.061)
。python
model = xgboost.XGBClassifier()
imputer = IterativeImputer()
pipeline = Pipeline(steps=[('i', imputer), ('m', model)])
cv = RepeatedStratifiedKFold(n_splits=10, n_repeats=3, random_state=0)
干得好!
不客气。
这取决于数据集和模型。尝试一系列方法,找出最适合您数据集的方法。
谢谢 Jason。一如既往地富有启发性。我对这个的理解是,通过填补缺失值,你可以保留训练行,从而加强原始存在的数值信号。你填补的目的是创建对训练相关参数贡献中性的数值吗?否则,似乎你会冒着过拟合的风险。我想验证指标是衡量你选择正确的填补方法的最佳方式。正如你在其他文章中给我灌输的,并在上面的例子中得到证实,填补是在“折叠内”应用的。
是的,你应该进行测试以确认它能为你的预测任务带来好处。
它可以帮助训练,也可以帮助测试数据,以及需要进行预测的新数据。
是的,始终在折叠内进行,以避免数据泄露和对模型性能的乐观估计。
Jason,非常感谢您提供的这份有用的指南!但我有一个问题。在缺失数据填补之前应用缩放更好吗?为了估计 NaN,使用的是线性回归方法,而线性回归方法更倾向于缩放数据。
可能之后。
感谢您的教程,我从这篇文章中学到了很多。这真是一篇非常有信息量的文章。
很高兴听到这个消息。
嗨,Jason,
我从您的文章中学到了很多。我尝试将此应用于“非正式投票问题”数据集。该数据集有许多缺失值。我已同时使用 KNN 填补和迭代填补来填充缺失值。但我只能获得 68% 的准确率,可以应用分类算法来预测测试数据的准确率吗?
谢谢!
也许可以尝试另一种算法、配置或数据准备方案?
我很想知道,但似乎找不到任何文档。迭代填补器如何处理完全缺失的行——所有值都是 NaN?
可能什么都没有或出错。在这种情况下,应该先删除该列。
感谢您的教程。我正在对整数数据使用这个迭代填补器,但出现了一个错误,如“ufunc ‘isnan’ 不支持输入类型,并且根据‘safe’转换规则,输入无法安全地强制转换为任何支持的类型”。我该如何纠正?我的猜测是我需要更改 dtype!无法弄清楚如何做到。
也许确认一下您的库是最新的?
也许确认一下您的数据中没有 NaN?
感谢您的本教程。
但我有一个问题
如果类别列中存在缺失值,例如“工作”,并且值 1~6 代表不同的工作级别。我该如何使用模型?我可以使用线性模型吗?
第二。如果每列中的缺失值接近 40%……但我认为这很重要,而且我无法删除它。有什么有用的方法吗?
数据是时间序列数据,但缺失值都出现在类别列中,例如人的年龄、邮政编码、收入水平、工作级别。
请帮助我,谢谢!
如果您有缺失值,也许可以尝试使用统计量、knn 或迭代填补来填补它们。
将结果与删除具有缺失值的行或列的数据拟合的模型进行比较。
感谢提供信息丰富的教程。
我正在使用这个 IterativeImputer,我有一些问题。
如果我使用 OneHotEncoder 对分类变量进行编码,imputer.fit() 会给出错误“设置具有序列的数组元素”,可能是什么可能的解决方案?
当没有响应变量时,目标只是填补缺失值(而不是预测任何内容),是否有方法可以衡量 IterativeImputer 在填补缺失值方面的表现如何?
再次感谢您的教程。它在弄清楚过程方面帮助很大。
不客气。
也许使用序数编码器并比较结果?
嗨 Jason,谢谢。您的建议奏效了。现在我有一个新的问题。如果您能给我一些建议,那就太好了。
当我对分类变量进行填补(编码后)时,数据类型从 object 变为 float。为了在填补后找到准确率,我将其四舍五入以便与编码后的标签进行比较。我在这里错过了什么吗?或者填补迭代填补器后所有数据类型都转换为 float 了吗?
请注意,我没有进行任何预测,只是填补缺失值。所以没有 Y 变量。另外,数据集中没有任何缺失值。我通过随机删除一些单元格值来添加缺失值,以便在填补后计算准确率。
不客气。
机器学习中的所有输入变量都是 float,即使是整数——至少在 Python/sklearn 中是这样。
如果您不进行建模,在数据准备后将数据类型转换为您喜欢的类型是一个好主意。
嗨,Jason
感谢您提供如此棒的信息。
根据 sklearn.impute.IterativeImputer 用户指南,估计器参数可以是不同类型的回归算法,例如 BayesianRidge、DecisionTreeRegressor 等。我的问题是,我们是否可以使用像 SVC、KNN 分类器这样的分类算法而不是回归作为估计器参数?
是的,也许可以尝试一下,并与结果进行比较,看看它在您的数据集上是否会有很大差异。
又一个很棒的教程!谢谢 Jason!我只想问一下。我们何时以及如何决定在 IterativeImputer() 中放入什么估计器?默认估计器 (BayesianRidge()) 经常使用吗?
谢谢。
也许你可以尝试一下,找出最适合你数据集的方法。
嗨,Jason,
感谢这篇精彩的文章。我学到了很多。传统上,我使用 sklearn 的 train_test_split 函数运行我的 RF pipeline,你这里没有用到,因为你后面使用了 k-fold CV。我的理解是,填补应该分别在训练和测试数据上进行——这是正确的吗?有没有简单的方法可以做到这一点?
谢谢!
是的,填补应该在训练集上进行拟合,并应用于训练集和测试集,请看这里。
https://machinelearning.org.cn/data-preparation-without-data-leakage/
嗨,Jason,
非常感谢这个分步教程,它解释得很详细,非常感谢。
在“使用 IterativeImputer 进行迭代填补”段落中,“23”这个值是从哪里来的?
# 分割输入和输出元素
data = dataframe.values
ix = [i for i in range(data.shape[1]) if i != 23]
X, y = data[:, ix], data[:, 23]
另外,数据框最初包含 28 列,但数组 Xtrans 只包含 27 个列表(或转换为数据框后为 27 列),是我错过了什么,还是我们丢失了 1 列?
非常感谢您的反馈,祝您有美好的一天。
我们从数据集中删除一个无用的变量。
嗨 Jason,再次感谢您发表这篇很棒的文章。
我尝试使用 IterativeImputer 与 R 的 MICE 进行比较,我发现了一个有趣但令人不安的结果。当我预测填补后的测试集时,AUC 比仅预测完整案例分析(约 50% 的行)显著更高(0.85 对 0.81)。
我尝试查找数据泄露,我在填补之前拆分了测试集,并在测试集上使用了 transform,当然,没有将目标变量包含在填补数据框中。
R 的 MICE 没有出现这个问题,填补后的测试集和完整案例分析的 AUC 大致相同。
谢谢你
嗨,Jason,
好文!
我有几个问题
1. 当我们同时拥有分类和数值列的缺失值时,如何使用迭代填补器?
1.1. 应该分开填补值吗?
1.2 在每种情况下,我们如何选择要用于填补的特征?
嗨 Bipin… 下面是一个很好的起点来回答你的问题
https://scikit-learn.cn/stable/modules/impute.html
迭代填补器会替换数据框中的列标题,请注意这一点。它在 transform 步骤中进行,您需要保存列标题,然后在 transform 之后再放回去。
嘿,我们可以对分类特征进行填补吗?
嗨 Ceo… 下面的内容可能很有趣
https://www.analyticsvidhya.com/blog/2021/04/how-to-handle-missing-values-of-categorical-variables/