关于scikit-learn中KNeighborsClassifier使用预计算距离矩阵的疑问
关于KNeighborsClassifier使用预计算距离矩阵的疑问解答
一、为什么fit传训练样本间距离矩阵,predict传测试-训练距离矩阵?
KNN是惰性学习模型,本身没有传统意义上的“训练参数”过程,但当指定metric='precomputed'时,fit()和predict()对输入矩阵的要求是由KNN的工作逻辑决定的:
fit(distances_train, y_train):这里的distances_train必须是训练样本两两之间的距离矩阵(形状为(n_train, n_train))。模型在fit阶段会将这个矩阵与训练标签绑定,确认训练样本的数量,为后续查找最近邻建立基础——简单说,模型需要先明确训练样本之间的距离关系,才能在预测时对比测试样本到训练样本的距离,筛选出最近的k个邻居。predict(distances_test):这里的distances_test必须是每个测试样本到所有训练样本的距离矩阵(形状为(n_test, n_train))。预测时,模型会针对每个测试样本,在这个矩阵里找到距离最小的k个训练样本,再通过投票得到预测类别。
二、全量距离矩阵下的子矩阵提取方法
如果已经有全量数据集的距离矩阵distances_all(形状为(n_total, n_total)),只需根据训练集和测试集的索引提取对应子矩阵:
- 先划分训练集和测试集的索引(比如用
train_test_split) - 提取训练样本间的距离矩阵:
distances_train = distances_all[train_idx][:, train_idx]——取全量矩阵中行和列都属于训练样本的部分 - 提取测试-训练的距离矩阵:
distances_test = distances_all[test_idx][:, train_idx]——取全量矩阵中行是测试样本、列是训练样本的部分
修正后的完整代码(含全量矩阵拆分示例)
from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import pairwise_distances from sklearn.model_selection import train_test_split # 全量数据集 X_all = [[0, 0], [1, 1], [2, 2], [3, 3], [1, 2], [1, 3]] y_all = [0, 0, 1, 1, 0, 1] # 划分训练集和测试集,获取索引 train_idx, test_idx, y_train, y_test = train_test_split( range(len(X_all)), y_all, test_size=0.3, random_state=42 ) # 生成全量距离矩阵 distances_all = pairwise_distances(X_all) # 提取训练样本间的距离矩阵 distances_train = distances_all[train_idx][:, train_idx] # 提取测试-训练的距离矩阵 distances_test = distances_all[test_idx][:, train_idx] # 初始化KNN分类器(使用预计算距离) knn = KNeighborsClassifier(n_neighbors=3, metric='precomputed') # 训练(绑定训练距离矩阵和标签) knn.fit(distances_train, y_train) # 预测 prediction = knn.predict(distances_test) print("训练样本间距离矩阵:") print(distances_train) print("\n测试-训练距离矩阵:") print(distances_test) print("\n预测结果:") print(prediction)
补充:你代码中的小错误修正
你提供的代码里有几处变量名拼写错误,会导致运行报错,修正后才能正常执行:
distances_traint→distances_trainprint(distances)→print(distances_train)print(distances1)→print(distances_test)
内容的提问来源于stack exchange,提问作者Rirro Romeu
相关产品推荐
相关产品推荐

