sklearn KNeighborsClassifier predict与kneighbors结果不一致问题
问题排查结论
你的实现流程里核心错误出在手动统计近邻标签的步骤,两个问题直接导致结果和predict()输出不一致:
- 标签数组引用错误:
KNeighborsClassifier.kneighbors()返回的索引是训练集样本的下标,对应你调用fit()时传入的train_features_flatten和y_train的位置。你手动统计时写的是y_test[neighbors_index[i][j]],相当于用测试集标签去匹配训练集样本的位置,标签完全错位,这是结果差异的最主要原因。 - 平票逻辑不一致:你手动计票时加了
sorted(row, reverse=True)的逆序排序操作,当近邻中出现多个类别票数相同的平票情况时,这个排序会改变最终选中的类别,和sklearn内置的平票处理逻辑不匹配——sklearn KNN在uniform权重下遇到平票,会优先选择训练集中标签值排序更靠前的类别,逆序排序会直接反转这个选择结果。
修正后的手动计票代码
neighbors_dist, neighbors_index = KNN_classifier.kneighbors(test_features_flatten) # 注意这里用y_train匹配训练集索引,不要用y_test data2 = np.zeros(neighbors_index.shape, dtype=object) for i in range(neighbors_index.shape[0]): for j in range(neighbors_index.shape[1]): data2[i,j] = str(y_train[neighbors_index[i][j]]) # 去掉多余的逆序排序,保持和sklearn默认计票逻辑一致 from collections import Counter majority_class = np.array([Counter(row).most_common(1)[0][0] for row in data2])
修正后再运行对比,手动统计的结果就会和predict()的输出完全对齐。
额外校验点
如果修正后仍有微小差异,可以按以下点排查:
- 确认特征提取逻辑统一:训练集、测试集输入特征提取模型前的预处理(归一化、resize、通道顺序等)要和训练孪生网络时的预处理完全一致,不要出现预处理不统一导致特征分布偏移的问题
- 确认KNN参数对齐:如果你修改过KNN的默认参数,比如
weights='distance'(按距离加权投票)、p值(距离度量类型),手动计票时也要对应调整逻辑,比如加权投票时不能按等票数统计,要按距离倒数给每个近邻的票数加权 - 确认特征标签顺序一致:检查传入
fit()的训练特征和y_train的顺序完全一一对应,没有出现乱序、错位的情况
内容的提问来源于stack exchange,提问作者Borhan Uddin
相关产品推荐
相关产品推荐

