You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为自定义实现的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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.24 19:54:06