如何为自定义实现的KNN算法添加1/距离权重
你需要调整predict_labels方法的投票逻辑,同时补充距离为0的异常处理(避免除零错误),修改方案如下:
修改核心逻辑
- 给KNN类新增
weights参数,支持普通均匀投票(原有逻辑)和距离倒数加权投票两种模式 - 距离加权规则:样本权重为
1/(距离 + 极小值),其中极小值取1e-5用于规避距离为0时的无穷大问题 - 距离加权模式下不再统计样本出现频次,而是统计每个类别对应的总权重,取总权重最高的类别作为预测结果
完整修改后代码
import numpy as np import matplotlib.pyplot as plt from sklearn import neighbors, datasets import pandas as pd from sklearn.model_selection import train_test_split class KNearestNeighbor(): def __init__(self, k, weights='uniform'): self.k = k self.weights = weights # 新增权重参数,可选'uniform'或'distance' def train(self,X,y): self.X_train = X self.y_train = y def predict(self,X_test): distances= self.euclidean_distance(X_test) return self.predict_labels(distances) def euclidean_distance(self,X_test): num_test = X_test.shape[0] num_train= self.X_train.shape[0] distances= np.zeros((num_test,num_train)) for i in range(num_test): for j in range(num_train): distances[i,j]= np.sqrt( np.sum((X_test[i,:] - self.X_train[j,:])**2)) return distances def predict_labels(self,distances): num_test= distances.shape[0] y_pred= np.zeros(num_test) for i in range(num_test): # 取前k个最近样本的索引和距离 sorted_idx = np.argsort(distances[i,:]) k_idx = sorted_idx[:self.k] k_distances = distances[i, k_idx] k_classes = self.y_train[k_idx].astype(int) if self.weights == 'uniform': # 原有均匀投票逻辑 y_pred[i] = np.argmax(np.bincount(k_classes)) elif self.weights == 'distance': # 新增距离加权投票逻辑 weights = 1 / (k_distances + 1e-5) # 加极小值避免除零 # 按类别统计总权重 class_weights = {} for cls, w in zip(k_classes, weights): class_weights[cls] = class_weights.get(cls, 0) + w # 取总权重最大的类别 y_pred[i] = max(class_weights, key=class_weights.get) return y_pred if __name__ == '__main__': iris = datasets.load_iris() X = iris.data y = iris.target X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2,random_state=2) # 调用距离加权模式 KNN = KNearestNeighbor(k=10, weights='distance') KNN.train(X_train,y_train) y_pred = KNN.predict(X_test) print(f'加权KNN准确率: {sum(y_pred == y_test )/y_test.shape[0]}') # 原有普通KNN调用方式不变 KNN_uniform = KNearestNeighbor(k=10, weights='uniform') KNN_uniform.train(X_train,y_train) y_pred_uniform = KNN_uniform.predict(X_test) print(f'普通KNN准确率: {sum(y_pred_uniform == y_test )/y_test.shape[0]}')
内容的提问来源于stack exchange,提问作者Hoàng Ngọc Thành
相关产品推荐
相关产品推荐

