我在阅读它的文档时,看到这样一段描述:
每个样本的缺失值使用训练集中找到的n_neighbors个最近邻居的平均值进行填补。如果两个样本中都没有缺失的特征值接近,则认为这两个样本接近。
现在,我用一个玩具数据集进行实验,例如:
>>>X = [[1, 2, nan], [3, 4, 3], [nan, 6, 5], [8, 8, 7]]>>>X [[ 1., 2., nan], [ 3., 4., 3.], [nan, 6., 5.], [ 8., 8., 7.]]
我们创建一个 KNNImputer 如下:
imputer = KNNImputer(n_neighbors=2)
问题是,当两个列中都有nan
时,它是如何填补这些nan
的?例如,如果要填补第一行第三列的nan
,它会如何选择哪些特征是最接近的,因为其中一行在第一列也有nan
?当我执行imputer.fit_transform(X)
时,它返回如下结果:
array([[1. , 2. , 4. ], [3. , 4. , 3. ], [5.5, 6. , 5. ], [8. , 8. , 7. ]])
这意味着,对于填补第一行的nan
,最近的邻居是第二行和第三行。它是如何计算第一行和第三行之间的欧几里得距离的?
回答:
它是如何使用也包含
NaN
的行来填补NaN
的?
文档中似乎没有提到这一点。但通过深入研究源代码,发现对于每个正在填补的列,距离更小的所有捐赠者都被考虑,即使他们有缺失值。处理方式是将权重矩阵中缺失值设为0
,权重矩阵是根据使用的距离获得的,参见_get_weights
。
相关代码位于_calc_impute
,在找到所有潜在捐赠者的距离矩阵后,再找到上述提到的权重矩阵,然后进行填补,如下所示:
# 使用零填补nansif weight_matrix is not None: weight_matrix[np.isnan(weight_matrix)] = 0.0
这里,如果潜在捐赠者与接收者之间至少有一个非nan
距离,则考虑所有潜在捐赠者
dist_pot_donors : ndarray of shape (n_receivers, n_potential_donors) 接收者和训练集中潜在捐赠者之间的距离矩阵。 接收者和潜在捐赠者之间必须至少有一个非nan
距离。
我们可以用一个玩具例子来验证这一点;在下面的矩阵中,填补[nan, 7., 4., 5.]
中的缺失值时,最后一行(也包含两个NaN
)被选中(注意我设置了n_neighbors=1
)。这是因为与最后一行的距离为0
,因为对应于NaN
值的距离被设为0
。因此,只需与第2
行和第3
行有最小的差异,最后一行就被选中,因为它被视为相等:
X = np.array([[np.nan,7,4,5],[2,8,4,5],[3,7,4,6],[1,np.nan,np.nan,5]])print(X)array([[nan, 7., 4., 5.], [ 2., 8., 4., 5.], [ 3., 7., 4., 6.], [ 1., nan, nan, 5.]])from sklearn.impute import KNNImputerimputer = KNNImputer(n_neighbors=1)imputer.fit_transform(X)array([[1., 7., 4., 5.], [2., 8., 4., 5.], [3., 7., 4., 6.], [1., 7., 4., 5.]])