机器学习(九):KNN算法全解析与项目实践

发布于:2025-07-28 ⋅ 阅读:(8) ⋅ 点赞:(0)

声明:未经允许,禁止转载

算法原理

k k k近邻算法是一种常见的懒惰监督学习算法,懒惰指的是该算法不需要训练,只需要计算测试样本到各个训练集样本的距离,然后找出距离测试样本最近的 k k k个训练样本:

  • 对于分类任务,使用投票法,将 k k k个训练样本的大多数样本所属的类别作为该预测样本的类别;
  • 对于回归任务,将 k k k个样本实值的均值作为预测结果。

k k k近邻算法中, k k k和距离度量的选择都十分重要, k k k取不同值时,分类结果可能会差异很大(见下图),而距离度量的不同会影响 k k k个近邻的选择。

k-nearest-neighbor

算法实践

本文在鸢尾花数据集上进行 k k k近邻算法的实践。数据集按训练集和测试集 7 : 3 7:3 7:3的比例划分,具体实现代码如下:

import numpy as np
from scipy.spatial.distance import cdist
from scipy.stats import mode
from process import read_data
from sklearn.metrics import accuracy_score
from sklearn.neighbors import KNeighborsClassifier
import matplotlib.pyplot as plt

class KNNClassifier:
    def __init__(self, k, metric='euclidean'):
        self.k = k
        self.train_x = None
        self.train_y = None
        self.metric = metric
    
    def fit(self, x, y):
        self.train_x = x
        self.train_y = y
    
    def euclidean_distance(self, x1, x2):
        return cdist(x1, x2, metric=self.metric)

    def predict(self, test_x):
        # 距离计算
        dis_x = self.euclidean_distance(test_x, self.train_x)
        # 获取测试样本对应的k个最近邻的索引
        k_indices = np.argsort(dis_x, axis=1)[:, :self.k]
        # 根据索引获取对应的标签
        k_labels = self.train_y[k_indices]
        # 对每个样本的k个最近邻的标签进行投票选出频率最高的作为预测概率
        y_hat, _ = mode(k_labels, axis=1)
        return y_hat



if __name__ == "__main__":
    data_path = "../datasets/iris.csv"
    metric = 'euclidean'
    train_x, train_y, test_x, test_y = read_data(data_path)
    k_max = 20
    accs = []
    for k in range(1, k_max + 1):
        # 自建模型
        cknn = KNNClassifier(k, metric)
        cknn.fit(train_x, train_y)
        cy_hat = cknn.predict(test_x)
        custom_acc = accuracy_score(test_y.reshape(-1), cy_hat.reshape(-1))
        # 调库
        sknn = KNeighborsClassifier(n_neighbors=k, metric=metric)
        sknn.fit(train_x, train_y)
        sy_hat = sknn.predict(test_x)
        sklearn_acc = accuracy_score(test_y.reshape(-1), sy_hat.reshape(-1))
        accs.append(custom_acc)
        print("k[{}]\tcustom acc[{}]\tsklearn acc[{}]".format(k, custom_acc, sklearn_acc))
    x = np.arange(1, k_max + 1)
    plt.figure()
    plt.xlabel("k")
    plt.ylabel("accuracy")
    plt.xticks(x)
    plt.plot(x, accs, marker="<")
    plt.savefig("accuracy.png")

实践结果中计算了 k = [ 1 , 2 , 3 , . . . , 20 ] k=[1,2,3,...,20] k=[1,2,3,...,20]时的准确率,下图为对应的结果,横轴为 k k k的取值,纵轴为对应在测试集上的准确率:

knn-accuracy

结语

参考资料:《机器学习》周志华
源码地址KNN
以上便是本文的全部内容,若有任何错误敬请批评指正,觉得不错的话可以支持一下,不胜感激!!!。


网站公告

今日签到

点亮在社区的每一天
去签到