从零实现KNN算法

本文详细介绍了KNN算法的工作原理,包括数据归一化、计算距离和确定最近邻的过程。同时讨论了KNN的优点(如简单易用)和缺点(如计算开销大),为读者提供了深入理解和应用KNN的指导。
摘要由CSDN通过智能技术生成

算法简介

KNN(K Near Neighbor)意为k个最近邻居,对于一个未知样本,通过计算训练集中最相似(距离最近)的k个样本,利用它们的标签进行分类或者回归预测。该算法简单易懂并且在解决一些问题表现出了出色的性能。

KNN的工作原理

对于两个不同的类别,首先提取它们不同的特征并能在坐标轴上表示出来,例如两种电影的不同尽头的出现次数,先暂且分为A类和B类。这样我们就得到了一个数据集用于训练,接下来进行数据归一化。

归一化

不同的数据之间的差值可能很大,归一化数值就是将x轴和y轴的数据化为0~1之间的数,将原本像长方形的数据化为正方形。

这里随便举一些数据:
A:(1,2)、(2,5)、(3,9)        测试数据(2,8)、(5,2)
B:(4,1)、(5,6)、(5,4)
先设归一化后的数据为G,待计算的数据为D,min为数据中的最小值,同理max为最大值。
对于x轴,要处理的数据依次为(1、2、3、2、5、4、5、5),显然min为1,max为5。y轴的数据同理。
根据公式:

G = \frac{D-min}{max-min}

处理后的数据:
A:(0,0.125)、(0.25,0.5)、(0.5,1)
B:(0.75,0)、(1,0.625)、(1,0.375)

归一化前的数据 

归一化后的数据 

可以看到归一化后的数据更加匀称,对于KNN来说,计算点与点的距离是它的核心算法,因此数据之间的差值会影响结果的预测,这就是为什么我们需要归一化。

计算距离

对于每个未知样本,计算它与训练集中所有的样本的距离,在二维平面中计算点之间的距离的方式有很多,本文就使用大家比较熟悉的欧式距离。

Distance = \sqrt{({x_{1}}-{x_{2}})^{2} + ({y_{1}}-{y_{2}})^{2} }

确定最近邻

即选取距离未知样本最近的k个训练样本,本文中设k为3。

投票决策

对于分类问题,将这k个最近邻的标签进行投票,选择票数最多的类别作为未知样本的类别。对于回归问题,可以取k个最近邻的平均值作为预测值。

代码实现

示例数据
train_data = np.array([[1, 2], [2, 5], [3, 9], [4, 1], [5, 6], [5, 4]])
train_labels = ['A', 'A', 'A', 'B', 'B', 'B']
test_data = np.array([[2, 8], [5, 2]])
归一化处理
def normalize_data(data):
    """
    对输入的数据进行归一化处理

    参数:
    data: 需要归一化的numpy数组,形状为(m, n),其中m是样本数,n是特征数

    返回:
    normalized_data: 归一化后的数据,形状与原数据相同
    """
    # 计算每列特征的最小值和最大值
    column_min = np.min(data, axis=0)
    column_max = np.max(data, axis=0)

    # 对每行数据的每个特征进行归一化
    normalized_data = (data - column_min) / (column_max - column_min)

    return normalized_data


# 归一化示例数据
normalized_train_data = normalize_data(train_data)
normalized_test_data = normalize_data(test_data)
计算欧式距离
def euclidean_distance(x1, x2):
    return np.sqrt(np.sum((x1 - x2) ** 2))
KNN分类器
def knn(train_data, train_labels, test_data, k):
    """ 
    参数:
    train_data: 训练数据的numpy数组,形状为(m, n),其中m是样本数,n是特征数
    train_labels: 训练标签的列表或numpy数组,长度为m
    test_data: 测试数据的numpy数组,形状为(p, n),其中p是测试样本数
    k: 最近邻居的数量

    返回:
    test_labels: 测试数据的预测标签列表
    """
    test_labels = []

    for i in range(test_data.shape[0]):
        # 初始化距离和标签列表
        distances = [euclidean_distance(test_data[i], train_data[j]) for j in range(train_data.shape[0])]
        labels = [train_labels[j] for j in range(train_data.shape[0])]

        # 获取最近的k个邻居的索引
        k_indices = np.argsort(distances)[:k]

        # 提取最近的k个邻居的标签
        k_nearest_labels = [labels[i] for i in k_indices]

        # 使用最常见的标签作为预测标签
        most_common = Counter(k_nearest_labels).most_common(1)
        test_labels.append(most_common[0][0])

    return test_labels

运行结果

KNN的优缺点

KNN算法有着诸多优点,如简单易懂、无需训练过程等。但同时也存在一些缺点,例如对于大规模数据集计算开销大、需要存储全部训练数据等。

结语

KNN算法作为一种简单而有效的分类方法,为我们提供了解决问题的一种思路。通过本文的介绍,相信读者对KNN算法有了更深入的理解,并能够灵活运用到实际问题中。在实际应用中,我们可以根据具体问题的需求对KNN进行改进和优化,使其发挥更大的作用。若有错误,请在评论区指出,谢谢。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值