一问讲清楚什么是——KNN模型

目录

引入

一、K-最近邻(K-Nearest Neighbors, KNN)算法详解

一、📌 什么是 KNN?

二、🧠 工作原理(分类任务)

三、📏 距离度量方式

✅ 欧几里得距离(最常用):

✅ 曼哈顿距离(绝对距离):

✅ 闵可夫斯基距离(欧氏和曼哈顿的推广):

四、🔢 参数 K 的选择

通常选法:

五、⚙️ 算法实现步骤(伪代码)

六、🎯 应用场景

七、🏋️‍♂️ 优点 vs 缺点

八、🔬 数学本质(从模式识别角度)

九、🧮 扩展:KNN 回归

✅ 总结一句话:

二、OpenCV 中的 cv2.ml.KNearest_create() 函数

1. 函数原型

2. 功能说明

3. 返回值

三、cv2.ml_KNearest 对象的常用方法

1. train(samples, layout, responses)

2. findNearest(samples, k)

四、示例代码

五、注意事项

六、相关API

七、总结


引入

  cv2.ml.KNearest_create() 是 OpenCV 中机器学习模块(cv2.ml)提供的一个用于创建 K-最近邻(K-Nearest Neighbors, KNN)分类器 实例的方法。该方法返回的是一个 cv2.ml_KNearest 类的对象,用户可以通过该对象进行模型的训练、预测等操作。下面将从基本概念、函数用途、使用方法、参数、返回值、相关方法等方面进行详细介绍,风格类似教科书内容。


一、K-最近邻(K-Nearest Neighbors, KNN)算法详解

一、📌 什么是 KNN?

        K-最近邻(K-Nearest Neighbors, KNN) 是一种基本的、监督式分类和回归算法
它的核心思想是:

“看你周围最相似的 K 个邻居属于什么类别,你也就属于那个类别。”

特点:

  • 懒惰学习(Lazy Learning):没有训练过程,只是存储训练数据。

  • 非参数模型(Non-parametric):不做任何关于数据分布的假设。


二、🧠 工作原理(分类任务)

KNN 的分类流程如下:

  1. 准备训练数据集(每个样本有特征和标签)。

  2. 给定一个待分类的测试样本

  3. 计算该样本与所有训练样本之间的距离

  4. 选出距离最近的 K 个训练样本

  5. 统计 K 个邻居所属的类别

  6. 投票决定测试样本的类别


三、📏 距离度量方式

KNN 的核心是计算“相似度”,通常使用距离度量:

✅ 欧几里得距离(最常用):

对于两个向量 $\mathbf{x} = (x_1, x_2, ..., x_n)$$\mathbf{y} = (y_1, y_2, ..., y_n)$

d(\mathbf{x}, \mathbf{y}) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2}

✅ 曼哈顿距离(绝对距离):

d(\mathbf{x}, \mathbf{y}) = \sum_{i=1}^{n}|x_i - y_i|

✅ 闵可夫斯基距离(欧氏和曼哈顿的推广):

d(\mathbf{x}, \mathbf{y}) = \left( \sum_{i=1}^{n}|x_i - y_i|^p \right)^{1/p}

常用 $p=1$(曼哈顿),$p=2$(欧氏)。


四、🔢 参数 K 的选择

  • K 值太小:容易受噪声干扰,模型复杂,过拟合

  • K 值太大:会包含太多不相关的样本,导致欠拟合

通常选法:

  • 使用交叉验证选择最优 K 值。

  • 常见取值:3、5、7,依赖实际数据。


五、⚙️ 算法实现步骤(伪代码)

Input: 训练集 D,测试样本 x,参数 K
Output: x 的预测类别

1. 对于训练集中的每个样本 xi:
    计算 d(x, xi) ← 测试样本与 xi 的距离
2. 将训练样本按照 d 值升序排列
3. 取前 K 个样本作为邻居
4. 统计这 K 个邻居中每个类别出现的频率
5. 返回出现频率最高的类别作为预测结果

六、🎯 应用场景

  • 图像识别(手写数字识别)

  • 文本分类

  • 医学诊断(如肿瘤良恶性判断)

  • 推荐系统(用户相似度)


七、🏋️‍♂️ 优点 vs 缺点

优点缺点
实现简单、直观存储和计算代价高(需要保存全部训练数据)
适用于多分类问题对不均衡数据敏感
无需模型训练,灵活维数灾难:维度越高效果越差


八、🔬 数学本质(从模式识别角度)

KNN 是一个基于局部邻域一致性假设的算法。即:

“如果一个样本在特征空间中的 K 个最近邻大多数属于某一类别,那么该样本也属于这个类别。”

这其实是一种 基于投票的密度估计法,也可看作是非参数化的核方法的一种简化形式。


九、🧮 扩展:KNN 回归

KNN 也可用于回归问题:

  • 再是“投票决定类别”,而是“取 K 个邻居的平均值”。

公式如下:

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

其中 $y_i$ 是 K 个最近邻的实际值。


✅ 总结一句话:

KNN 是一种没有模型的“以邻为师”的方法,它简单有效,适合小规模数据,但在大数据和高维度上会面临性能瓶颈。


二、OpenCV 中的 cv2.ml.KNearest_create() 函数

1. 函数原型

cv2.ml.KNearest_create() -> retval

2. 功能说明

        该函数用于创建一个 K-最近邻分类器(KNearest)对象的实例,返回一个可供后续调用的 cv2.ml_KNearest 类对象。通过该对象,可以执行如下操作:

  • train():训练模型。

  • findNearest():进行最近邻查询与预测。

  • load() / save():模型的加载与保存。

3. 返回值

返回一个 cv2.ml_KNearest 类型的对象实例。例如:

knn = cv2.ml.KNearest_create()


三、cv2.ml_KNearest 对象的常用方法

以下是通过 cv2.ml.KNearest_create() 创建的对象所支持的常用方法:

1. train(samples, layout, responses)

训练模型。

  • samples训练样本数据,类型为 np.float32 的二维矩阵,每一行表示一个样本。

  • layout数据布局类型,常为 cv2.ml.ROW_SAMPLE

  • responses:每个样本的标签,类型为 np.float32 的列向量或一维数组。

例:

knn.train(train_data, cv2.ml.ROW_SAMPLE, train_labels)

2. findNearest(samples, k)

使用 KNN 方法对新数据进行预测

  • samples:待分类数据,类型为 np.float32 的二维矩阵。

  • k:使用的最近邻个数。

  • 返回:预测标签、最近邻的响应值、距离等。

例:

ret, result, neighbours, dist = knn.findNearest(test_data, k=3)

返回内容解释:

  • ret:主要预测结果(通常等于 result[0])。

  • result:预测结果数组。

  • neighbours:K 个最近邻的标签。

  • dist:K 个最近邻的距离。


四、示例代码

  • 整个图像背景会被染成两类颜色,显示出模型的“决策边界”。

  • 点密集分布在边界两侧,表示训练数据的聚类效果。

  • 点击图像时,分类器将会返回点击位置所属的类别,并标记颜色。

import numpy as np
import cv2

# 设置随机种子
np.random.seed(42)

# 创建两类训练数据
class0 = np.random.randint(0, 256, (25, 2)).astype(np.float32)
class1 = np.random.randint(256, 512, (25, 2)).astype(np.float32)

train_data = np.vstack((class0, class1))
labels = np.vstack((np.zeros((25, 1), dtype=np.float32), np.ones((25, 1), dtype=np.float32)))

# 创建 KNN 模型并训练
knn = cv2.ml.KNearest_create()
knn.train(train_data, cv2.ml.ROW_SAMPLE, labels)

# 创建画布并绘制分类边界
canvas = np.zeros((512, 512, 3), dtype=np.uint8)

# 分类边界可视化
for y in range(0, 512):
    for x in range(0, 512):
        sample = np.array([[x, y]], dtype=np.float32)
        ret, result, neighbours, dist = knn.findNearest(sample, k=3)
        if result[0][0] == 0:
            canvas[y, x] = (0, 0, 0)  # 红色区域
        else:
            canvas[y, x] = (255, 255, 255)  # 绿色区域

# 绘制原始样本点
for pt in class0:
    cv2.circle(canvas, (int(pt[0]), int(pt[1])), 5, (0, 0, 255), -1)
for pt in class1:
    cv2.circle(canvas, (int(pt[0]), int(pt[1])), 5, (0, 255, 0), -1)

# 鼠标点击预测函数
def on_mouse(event, x, y, flags, param):
    if event == cv2.EVENT_LBUTTONDOWN:
        sample = np.array([[x, y]], dtype=np.float32)
        ret, result, neighbours, dist = knn.findNearest(sample, k=3)
        print(f"点击 ({x}, {y}) → 预测类别: {int(result[0][0])}")
        color = (0, 0, 255) if result[0][0] == 0 else (0, 255, 0)
        cv2.circle(canvas, (x, y), 5, color, -1)

# 展示窗口
cv2.namedWindow("KNN 分类边界")
cv2.setMouseCallback("KNN 分类边界", on_mouse)

while True:
    cv2.imshow("KNN 分类边界", canvas)
    if cv2.waitKey(1) & 0xFF == 27:  # 按 ESC 退出
        break

cv2.destroyAllWindows()


五、注意事项

  1. 输入数据必须 np.float32 类型,否则训练或预测时将报错。

  2. K 值应根据实际应用场景进行调整,过大或过小都会影响预测准确性。

  3. 由于 KNN 是惰性学习算法,训练过程简单但预测开销大,不适合大规模数据实时处理

  4. 所有输入数据(包括标签)应进行预处理(如归一化)以提升性能


六、相关API

函数说明
cv2.ml.TrainData_create()构建训练数据的辅助工具
cv2.ml.KNearest_load(filename)从文件加载已有的 KNN 模型
model.save(filename)保存模型到文件
model.clear()清除模型内容

七、总结

  cv2.ml.KNearest_create() 是 OpenCV 提供的用于机器学习中 K-最近邻分类任务的创建函数。通过该函数,用户可以灵活构建 KNN 分类器,执行训练、预测等操作。其实现基于 OpenCV 的机器学习模块,封装良好、使用方便,适合中小型分类问题的入门学习和应用开发。

### KNN算法在机器学习中的实现与应用 #### KNN算法简介 K近邻(K-Nearest Neighbor, KNN)是种基本分类与回归方法。该算法的核心思想在于通过计算待测样本与训练集中各个样本的距离,选取距离最小的前K个邻居,并依据这些邻居的信息来进行决策。对于分类题而言,则是根据多数表决原则决定新实例所属类别;而对于回归题来说,则通常采用这K个最接近的数据点的目标属性平均值作为预测结果。 #### 二、R语言下的具体实践案例 针对鸢尾花数据集的应用展示了如何利用基础函数完成整个流程而无需依赖额外包的支持[^2]。在这个例子中,通过对不同特征维度间欧氏距离或其他度量方式的选择实现了对未知样本的有效识别。这种做法不仅有助于理解原理本身,同时也锻炼了编程技巧以及解决实际题的能力。 ```r # 加载必要的库并读入数据 library(ggplot2) data(iris) head(iris) # 数据预处理... set.seed(1234) trainIndex <- sample(seq_len(nrow(iris)), size = floor(.7 * nrow(iris))) trainingData <- iris[trainIndex, ] testingData <- iris[-trainIndex, ] # 定义knn函数用于后续调用 knnPredict <- function(trainSet, testInstance, labels, k){ distances <- sqrt(rowSums((t(t(trainSet[,1:4]) - as.numeric(testInstance)))^2)) sortedDistIndices <- order(distances)[1:k] classCounts <- table(labels[sortedDistIndices]) return(names(which.max(classCounts))) } predictions <- sapply(as.matrix(testingData[,1:4]), knnPredict, trainSet=as.matrix(trainingData[,1:4]), labels=trainingData$Species,k=3L) confusionMatrix <- table(predictions,factor(testingData$Species)) print(confusionMatrix) ``` 上述代码片段演示了个完整的基于自定义逻辑而非第三方工具包构建KNN模型的过程,包括但不限于数据分割、相似性测量及最终评估等方面的工作。 #### 三、应用场景探讨 尽管存在诸如计算复杂度较高等局限之处,但在某些特定条件下依然能够展现出独特价值: - **低维空间**:当输入变量数量较少时,性能表现良好; - **多模态分布**:可以很好地适应具有多个峰值的概率密度函数所描述的现象; - **快速原型开发**:由于易于理解和编码特性,在初期探索阶段可作为种高效手段迅速验证想法可行性[^3]。 综上所述,虽然与其他更先进的技术相比可能显得不够先进,但凭借其实现简便性和灵活性依旧占据着不可替代的地位。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

WenJGo

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值