第三章 k-邻近(KNN) + 原理实现(python)(可直接套用) + 评论区有问必答

KNN是一种基于实例的监督学习算法,用于分类和回归任务。它通过计算新样本与训练数据的距离找到最近的k个邻居,依据邻居的标签进行预测。文章提供了两个简单的Python代码示例,展示了如何实现KNN算法,包括欧氏距离计算和kd树优化,并讨论了算法的优缺点及适用场景。
摘要由CSDN通过智能技术生成

1.KNN简介.

KNN(K-最近邻)算法是一种常用的基于实例的监督学习算法,用于分类和回归任务。在统计学习方法中,KNN算法属于一类称为“基于实例的学习”或“懒惰学习”(lazy learning)的算法。这种算法不需要显式地训练模型,而是在预测阶段根据训练数据进行实时计算。

KNN算法的基本思想是:对于一个新的输入样本,找到训练数据中与该样本最相似的k个邻居(通常使用欧氏距离或其他距离度量方法来衡量相似性),然后根据这k个邻居的标签来进行分类(对于分类问题)或回归(对于回归问题)。

KNN算法的模型策略如下:

1. 输入:训练样本集D = {(x1, y1), (x2, y2), ..., (xn, yn)},其中xi为样本特征,yi为样本标签;待预测样本x。
2. 计算输入样本x与训练样本集中所有样本xi之间的距离(通常使用欧氏距离等)。
3. 根据距离找到与输入样本x最近的k个训练样本,这些样本构成了x的k近邻。
4. 对于分类任务:根据k个近邻的标签,通过投票或权重投票的方式来确定输入样本x的类别。
   对于回归任务:根据k个近邻的标签,通过平均或加权平均的方式来确定输入样本x的输出值。
5. 返回预测结果。

KNN算法的特点
- 优点:简单易懂,易于实现,对于训练数据没有显式训练过程,适用于多分类和回归任务。
- 缺点:对于大规模数据集,计算复杂度较高,预测速度可能较慢。在特征空间维度较高的情况下,可能出现维度灾难,影响算法效果。对于不平衡的数据集和噪声较多的数据集,可能会导致预测结果不稳定。

在实际应用中,KNN算法可以通过调整k值来控制近邻的数量,从而影响算法的预测结果。较小的k值可以使模型更加灵敏,但容易受到噪声的影响;较大的k值可以降低噪声的影响,但可能忽略了样本之间的局部特征。

总结来说,KNN算法是一种简单而直观的分类和回归方法,适用于一些简单的问题或作为其他更复杂算法的基准。在实践中,我们通常使用距离加权KNN(distance-weighted KNN)或改进的KNN算法来提高算法性能,并结合特征选择、距离度量优化等技术来处理实际问题。

2.KNN1(Python).

代码实现的主要思想:

        1. 计算测试集到训练集样本的距离;

        2. 找出前k个点的多数y即作为该测试集的预测值.

from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split

""" KNN """
class KNN():
    def __init__(self, X_train, y_train, X_test, k):
        self.X_train = X_train
        self.y_train = y_train
        self.X_test  = X_test
        self.k = k
        
    def euclidean_distance(self, point1, point2):
        return np.sqrt(np.sum((point1 - point2) ** 2))
    
    def predict(self):
        y_pred = []
        for test_point in X_test:
            distances = [self.euclidean_distance(test_point, train_point) for train_point in self.X_train]
            k_nearest_indices = np.argsort(distances)[:self.k]
            k_nearest_labels = [self.y_train[i] for i in k_nearest_indices]
            counts = np.bincount(k_nearest_labels)
            predicted_label = np.argmax(counts)
            y_pred.append(predicted_label)
        return y_pred

    def score(self, y_pred, y_test):
        return 1 - np.count_nonzero(y_test-y_pred)/len(y_test)


if __name__ == '__main__':    
    
    # 数据集. 
    X, y = datasets.load_breast_cancer(return_X_y=True)
    X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)
    
    # KNN.
    knn = KNN(X_train, y_train, X_test, k=3)
    y_pred = knn.predict()
    print('Predict Values:', y_pred)
    pred_score = knn.score(y_pred, y_test)
    print("Predict Score:", pred_score)

3.KNN2(Python).

第一个代码更加简洁, 第二个代码主要参考以下文章,里面还加了kd树的实现, 感兴趣的可以去看他的代码,kd树概念不了解的同学可以去看学生视频-KD树_哔哩哔哩_bilibili这个视频讲的非常清楚K近邻(KNN)算法及python实现(含Kd树实现)_rosefunR的博客-CSDN博客

from sklearn import datasets
import numpy as np
from sklearn.model_selection import train_test_split

X, y = datasets.load_breast_cancer(return_X_y=True)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.3, random_state=42)

# my k-NN
class KNN():
    def __init__(self,data,K=3):
        self.X = data[0]
        self.y = data[1]
        self.K = K
    def fit(self, X_test):
        diffX = np.repeat(X_test, len(self.X), axis=0) - np.tile(self.X,(len(X_test),1))
        square_diffX = (diffX**2).sum(axis=1).reshape(len(X_test),len(self.X))
        sorted_index = square_diffX.argsort()
        predict = [0 for _ in range(len(X_test))]
        for i in range(len(X_test)):
            class_count={}
            for j in range(self.K):
                vote_label = self.y[sorted_index[i][j]]
                class_count[vote_label] = class_count.get(vote_label,0) + 1
            sorted_count = sorted(class_count.items(), key=lambda x: x[1],reverse=True)
            predict[i] = sorted_count[0][0]
        return predict
    def predict(self, X_test):
        return self.fit(X_test)
    def score(self,X,y):
        y_pred = self.predict(X)
        return 1 - np.count_nonzero(y-y_pred)/len(y)
knn = KNN((X_train,y_train), K=3)
print('KNN1准确率: ', knn.score(X_test,y_test))

4.结果展示.

两种方法的准确率相同.

4.1 KNN1.

4.2 KNN2.

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值