当前位置: 首页 > article >正文

KNN算法原理(深入浅出)

目录

      • 1. KNN算法的背景
      • 2. KNN算法的基本步骤
        • 步骤1:选择K值
        • 步骤2:计算距离
        • 步骤3:选择K个最近邻
        • 步骤4:进行分类或回归
      • 3. KNN算法的公式推导
        • 步骤1:计算新样本与每个训练样本之间的距离
        • 步骤2:找到距离最小的K个邻居
        • 步骤3:进行预测
      • 4. 总结
      • 5. K值的选择
        • **步骤1:导入必要的库**
        • **步骤2:加载数据集**
        • **步骤3:划分训练集和测试集**
        • **步骤4:数据标准化**
        • **步骤5:训练KNN模型**
        • **步骤6:做出预测并评估模型**
        • **步骤7:可视化结果(可选)**
        • **完整代码**
        • **输出**
        • **总结**

1. KNN算法的背景

KNN算法是一种监督学习算法,用于解决分类问题(比如判断某个人是男是女)和回归问题(比如预测某个房子的价格)。

下面通过“距离”来判断样本的类别,认为“相似的样本通常是属于同一类的”

KNN的基本思路就是:对于一个新的样本,计算它与所有已知样本的距离,找到距离它最近的K个样本,然后根据这K个样本的标签来推测新样本的标签。

2. KNN算法的基本步骤

下面逐步了解KNN算法的核心步骤:

步骤1:选择K值

K是一个正整数,它决定了我们在做预测时要考虑的邻居数量。比如,K=3表示我们会找到距离待预测样本最近的3个样本,看看它们的标签是什么,然后投票选出最终的标签。

步骤2:计算距离

在KNN中,距离是一个非常重要的概念。最常用的距离度量方法是欧氏距离。假设我们有两个样本:

  • 样本1的特征是 x 1 = ( x 1 , 1 , x 1 , 2 , . . . , x 1 , n ) x_1 = (x_{1,1}, x_{1,2}, ..., x_{1,n}) x1=(x1,1,x1,2,...,x1,n)
  • 样本2的特征是 x 2 = ( x 2 , 1 , x 2 , 2 , . . . , x 2 , n ) x_2 = (x_{2,1}, x_{2,2}, ..., x_{2,n}) x2=(x2,1,x2,2,...,x2,n)

这些特征是样本的不同属性(比如,人的身高、体重等)。计算这两个样本的欧氏距离,可以使用下面的公式:

d ( x 1 , x 2 ) = ( x 1 , 1 − x 2 , 1 ) 2 + ( x 1 , 2 − x 2 , 2 ) 2 + ⋯ + ( x 1 , n − x 2 , n ) 2 d(x_1, x_2) = \sqrt{(x_{1,1} - x_{2,1})^2 + (x_{1,2} - x_{2,2})^2 + \dots + (x_{1,n} - x_{2,n})^2} d(x1,x2)=(x1,1x2,1)2+(x1,2x2,2)2++(x1,nx2,n)2
这个公式的意思是,首先对每个特征的差值(即 x 1 , i − x 2 , i x_{1,i} - x_{2,i} x1,ix2,i)平方,然后把这些平方加起来,再开平方,得到的结果就是两个样本之间的距离。

步骤3:选择K个最近邻

计算完距离后,我们需要找到距离待预测样本最近的K个样本。这些样本就被称为邻居。我们通过这些邻居的标签来预测新样本的标签。

步骤4:进行分类或回归
  • 分类:如果我们的任务是分类,比如区分“男”或“女”,我们会选择K个邻居中出现最多的类别作为新样本的预测结果。这个过程叫做“投票”。例如,如果K=3,3个邻居的标签分别是“男”,“男”,“女”,那么新样本的标签预测为“男”。

    公式表示为:
    y ^ = mode ( y 1 , y 2 , . . . , y K ) \hat{y} = \text{mode}(y_1, y_2, ..., y_K) y^=mode(y1,y2,...,yK)
    这里的 y 1 , y 2 , . . . , y K y_1, y_2, ..., y_K y1,y2,...,yK 是K个邻居的标签,mode 表示选择出现次数最多的标签。

  • 回归:如果任务是预测一个数值(比如预测房价),我们会计算K个邻居标签的平均值作为新样本的预测结果。

    公式表示为:
    y ^ = 1 K ∑ i = 1 K y i \hat{y} = \frac{1}{K} \sum_{i=1}^{K} y_i y^=K1i=1Kyi
    这里的 y 1 , y 2 , . . . , y K y_1, y_2, ..., y_K y1,y2,...,yKK个邻居的标签(在回归问题中是数值)。

3. KNN算法的公式推导

假设我们有一个训练数据集 D = { ( x 1 , y 1 ) , ( x 2 , y 2 ) , . . . , ( x m , y m ) } D = \{(x_1, y_1), (x_2, y_2), ..., (x_m, y_m)\} D={(x1,y1),(x2,y2),...,(xm,ym)},每个 x i x_i xi 是样本的特征向量, y i y_i yi 是标签。

我们现在有一个新的样本 x new x_{\text{new}} xnew,需要预测它的标签。

步骤1:计算新样本与每个训练样本之间的距离

假设我们选择欧氏距离,计算新样本 x new x_{\text{new}} xnew 与每个训练样本 x i x_i xi 之间的距离:

d ( x new , x i ) = ∑ j = 1 n ( x new , j − x i , j ) 2 d(x_{\text{new}}, x_i) = \sqrt{\sum_{j=1}^{n} (x_{\text{new},j} - x_{i,j})^2} d(xnew,xi)=j=1n(xnew,jxi,j)2

这就是新样本与每个训练样本的距离。

步骤2:找到距离最小的K个邻居

对所有的训练样本计算完距离之后,我们找出距离新样本最近的K个训练样本。假设这K个样本的标签是 y 1 , y 2 , . . . , y K y_1, y_2, ..., y_K y1,y2,...,yK

步骤3:进行预测
  • 分类任务:我们根据K个邻居的标签进行投票,选择最多的标签作为预测结果。假设K=3,邻居的标签是“男”,“男”,“女”,那么最终预测结果是“男”。

y ^ = mode ( y 1 , y 2 , . . . , y K ) \hat{y} = \text{mode}(y_1, y_2, ..., y_K) y^=mode(y1,y2,...,yK)

  • 回归任务:我们计算K个邻居的标签的平均值,作为预测结果。

y ^ = 1 K ∑ i = 1 K y i \hat{y} = \frac{1}{K} \sum_{i=1}^{K} y_i y^=K1i=1Kyi

4. 总结

KNN算法的核心思想是:如果一个样本与其他样本相似,那么它的标签也应该与这些相似的样本的标签相似。通过计算距离、选择K个邻居,KNN可以非常直观地做出预测。公式推导中,我们首先计算距离,然后选择K个邻居,最后通过投票或均值来预测结果。

5. K值的选择

K的值对模型的效果影响很大。一般来说,K值较小会使模型对噪声较为敏感(可能过拟合),而K值较大则可能使模型过于平滑,导致欠拟合。通常,我们会通过交叉验证来选择一个合适的K值。


我们来通过一个具体的KNN算法应用案例,展示如何用Python实现KNN算法进行分类任务。我们将使用一个常见的机器学习库——scikit-learn,并以鸢尾花数据集(Iris dataset)为例,进行KNN分类。

步骤1:导入必要的库

首先,我们需要导入几个基本的库:

# 导入必要的库
import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt
  • numpypandas 用于数据处理。
  • train_test_split 用于将数据集分为训练集和测试集。
  • StandardScaler 用于标准化数据,使其适应KNN的距离计算。
  • KNeighborsClassifier 是scikit-learn中KNN算法的实现。
  • accuracy_score 用于评估分类结果的准确率。
  • load_iris 是scikit-learn内置的鸢尾花数据集。
步骤2:加载数据集

我们使用scikit-learn自带的鸢尾花数据集(Iris Dataset)进行KNN分类任务。这个数据集包含150个鸢尾花的样本,每个样本有4个特征(花萼长度、花萼宽度、花瓣长度、花瓣宽度),以及每个样本的类别标签(有三个类别:Setosa, Versicolor, Virginica)。

# 加载鸢尾花数据集
iris = load_iris()
X = iris.data  # 特征矩阵
y = iris.target  # 类别标签
步骤3:划分训练集和测试集

我们将数据集分为训练集和测试集,通常训练集占数据集的80%,测试集占20%。

# 将数据集分为训练集和测试集(80%训练集,20%测试集)
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
步骤4:数据标准化

KNN算法非常依赖特征之间的距离,因此特征的尺度(单位)必须统一。我们通常会使用标准化来处理特征,使得每个特征的均值为0,标准差为1。

# 标准化数据
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)
步骤5:训练KNN模型

接下来,我们用训练数据训练KNN模型。假设我们选择K=3作为邻居数量,并使用欧氏距离。

# 初始化KNN分类器,设置邻居数量为3
knn = KNeighborsClassifier(n_neighbors=3)

# 使用训练集训练模型
knn.fit(X_train_scaled, y_train)
步骤6:做出预测并评估模型

训练完成后,我们可以使用测试集对模型进行评估。我们使用准确率来衡量模型的表现。

# 使用测试集进行预测
y_pred = knn.predict(X_test_scaled)

# 计算预测准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy * 100:.2f}%")
步骤7:可视化结果(可选)

虽然鸢尾花数据集是4维的,但我们可以选择两个特征来可视化KNN的分类效果。我们选择前两个特征(花萼长度和花萼宽度)来进行2D可视化。
在这里插入图片描述

# 选择前两个特征进行可视化
X_train_2d = X_train[:, :2]
X_test_2d = X_test[:, :2]

# 标准化数据
X_train_2d_scaled = scaler.fit_transform(X_train_2d)
X_test_2d_scaled = scaler.transform(X_test_2d)

# 训练KNN模型
knn.fit(X_train_2d_scaled, y_train)

# 创建网格来画出决策边界
xx, yy = np.meshgrid(np.linspace(X_train_2d_scaled[:, 0].min(), X_train_2d_scaled[:, 0].max(), 100),
                     np.linspace(X_train_2d_scaled[:, 1].min(), X_train_2d_scaled[:, 1].max(), 100))

# 预测网格上每个点的类别
Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制决策边界
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(X_train_2d_scaled[:, 0], X_train_2d_scaled[:, 1], c=y_train, marker='o', edgecolor='k', s=50)
plt.title("KNN Classification (Training Set)")
plt.xlabel("Feature 1: Sepal Length")
plt.ylabel("Feature 2: Sepal Width")
plt.show()
完整代码

将上述步骤整合,代码如下:

import numpy as np
import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier
from sklearn.metrics import accuracy_score
from sklearn.datasets import load_iris
import matplotlib.pyplot as plt

# 加载鸢尾花数据集
iris = 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=42)

# 标准化数据
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 训练KNN模型
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train_scaled, y_train)

# 使用测试集进行预测
y_pred = knn.predict(X_test_scaled)

# 计算准确率
accuracy = accuracy_score(y_test, y_pred)
print(f"模型准确率: {accuracy * 100:.2f}%")

# 可视化结果 (选择前两个特征进行2D可视化)
X_train_2d = X_train[:, :2]
X_test_2d = X_test[:, :2]
X_train_2d_scaled = scaler.fit_transform(X_train_2d)
X_test_2d_scaled = scaler.transform(X_test_2d)

knn.fit(X_train_2d_scaled, y_train)

# 创建网格画出决策边界
xx, yy = np.meshgrid(np.linspace(X_train_2d_scaled[:, 0].min(), X_train_2d_scaled[:, 0].max(), 100),
                     np.linspace(X_train_2d_scaled[:, 1].min(), X_train_2d_scaled[:, 1].max(), 100))

Z = knn.predict(np.c_[xx.ravel(), yy.ravel()])
Z = Z.reshape(xx.shape)

# 绘制决策边界
plt.contourf(xx, yy, Z, alpha=0.8)
plt.scatter(X_train_2d_scaled[:, 0], X_train_2d_scaled[:, 1], c=y_train, marker='o', edgecolor='k', s=50)
plt.title("KNN Classification (Training Set)")
plt.xlabel("Feature 1: Sepal Length")
plt.ylabel("Feature 2: Sepal Width")
plt.show()
输出
  1. 模型准确率:程序会输出模型在测试集上的准确率,比如:“模型准确率: 96.67%”。
  2. 可视化:会绘制一个2D决策边界图,显示KNN算法如何根据两个特征(花萼长度和花萼宽度)进行分类。

总结

通过这个Python应用案例,我们演示了如何使用KNN算法进行鸢尾花数据集的分类。整个过程包括了数据加载、数据划分、标准化、训练模型、预测结果和可视化等步骤。KNN是一种非常直观的算法,适合初学者使用。


http://www.kler.cn/a/514586.html

相关文章:

  • bash: ./xxx: No such file or directory
  • 1/20赛后总结
  • 【HarmonyOS NEXT】华为分享-碰一碰开发分享
  • 特殊类设计
  • Linux内核编程(二十一)USB驱动开发-键盘驱动
  • WPS按双字段拆分工作表到独立工作簿-Excel易用宝
  • nvm版本安装
  • IP协议特性
  • 澎峰科技计算软件栈与沐曦GPU完成适配和互认证
  • 2000-2010年各省第三产业就业人数数据
  • 【单层神经网络】快速入门AI系列
  • 超大型集团合并报表数智管理转型
  • C语言基础------练习1
  • 相机内参的作用原理
  • doris:Stream Load
  • 登录认证(4):令牌技术:JWT令牌
  • Selenium-WEB自动化测试环境配置
  • springBoot 整合ModBus TCP
  • EJB如何管理事务
  • Qt Creator 15.0.0如何更换主题和字体
  • 【Java】常用工具类方法:树形结构、获取IP、对象拷贝、File相关、雪花算法等
  • ubuntu 安装显卡驱动gpu-cuda
  • TiDB 对 Hadoop 的影响:大数据时代的新选择
  • 深入理解 Java 的并发容器
  • MongoDB部署模式
  • 《论文阅读》GPT-3是否会产生移情对话?一种新的情境示例选择方法和用于生成同理心对话的自动评估度量 ICCL 2022