K近邻算法和线性回归的幕后细节

2024-01-13 17:50

本文主要是介绍K近邻算法和线性回归的幕后细节,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1. 写在前面

今天开始, 开始尝试进行机器学习算法的一些查缺补漏知识的整理, 主要还是之前没有注意的一些点吧, 这次主要是KNN算法和线性回归的两个点, 这两个算法或许在大家看来或许都是两个比较简单的算法, 但是这次又偶然学习了一次, 发现还是有些知识是被忽略掉的, 所以借这个机会进行补充。 首先是KNN算法的kd树部分, 这里会通过一个具体的例子来说一下kd树的原理, 之前写白话KNN的时候, 这块知识是略掉的, 但感觉还是有必要了解一下这个东西的, 因为毕竟KNN我们知道, 如果拿一个新样本来判断它属于哪个类, 我们可是要计算它与其他样本点所有的距离, 这在样本非常多的时候时间复杂度可是很可怕的, 所以kd树的这种数据结构有利于降低一下时间复杂度, 差不多能从O(n)降到O(logn), 也是kd树要引入的原因, 后面会通过一个例子来看看kd树的构建和搜索k近邻点的方式, 就知道为啥它能降低时间复杂度了。

然后就是线性回归, 这个之前也是忽略了一个点, 就是损失函数, 我们知道线性回归的损失函数就是平方差损失, 因为这个可以衡量预测值和真实值之间的差距嘛, 那既然是差距, 为啥不用别的差损失单单选定了平方差呢? 其实这个损失函数是由基于一个误差项的假设推导出来的, 这里会补充一下。 所以这两个小细节希望能对这两个简单的算法加深理解吧。

大纲如下

  • KNN的kd树
  • 线性回归的概率理解

2. KNN的kd树

KNN算法的重点在于找出K个最近邻的点, 在寻找过程中我们其实有两种方式进行选择:

  1. 蛮力实现
    这个方法很简单, 就是计算出待测样本到所有训练样本的距离, 然后选择最小的k个距离即可得到k个最近邻点, 这个方法样本数据少的时候, 还可以, 但是训练集很大的时候, 计算非常耗时,其实是不太可取的。所以在这里也能看出学习算法的重要性了, 有时候学完了理论是没法在实际应用中用的, 实际工程中还需要考虑各种最优化的策略呢, 比如第二种方式
  2. KD Tree
    这个算法中, 首先是对训练数据进行建模, 构造出一个KD树来, 然后再根据构建好的Kd树来获取近邻样本的数据, 这个方式是KNN算法中用于快速寻找近邻的一种方式, 会降低蛮力实现的复杂度。

这里主要是拿一个例子来看一下如何构建Kd树以及如何寻找近邻点, 至于kd树的理论可以参考后面给出的链接, 那里面说的比较详细。 说白了, kd树就可以看成是多维的二叉搜索树。
在这里插入图片描述
构造kd树的方式很简单, 首先我们从构建根节点开始。 两个原则:

  • 选维度进行分裂(方差最大原则)
  • 依据方差最大选好了维度, 从该维度的哪个点去分割呢? 中位数,这样才平衡。

具体步骤如下:这里先放一个图比较好理解:
在这里插入图片描述

  1. 构建根节点, 通过计算, x(1)的方差大,此时的切分维度x(1),上点集合在x(1)维度下从小到大排序(2,3), (4,7). (5, 4), (7, 2), (8, 1), (9, 6); 中值为(7, 2)。
    (注:2,4,5,7,8,9在数学中的中值为(5 + 7)/2=6,但因该算法的中值需在点集合之内,所以本文中值计算用的len(points)//2=3, points[3]=(7,2))
  2. (2,3),(4,7),(5,4)挂在(7,2)节点的左子树,(8,1),(9,6)挂在(7,2)节点的右子树。
  3. 构建(7,2)节点的左子树时,点集合(2,3),(4,7),(5,4)此时的切分维度为x(2),这三点
    按照x(2)维度从小到大排序(2, 3), (5, 4), (4, 7),中值为(5,4)作为分割平面,(2,3)挂在
    其左子树,(4,7)挂在其右子树。
  4. 构建(7,2)节点的右子树, 点集合(8,1), (9,6)的分割维度x(2), points[1]=(9, 6)作为分割
    平面, (8,1)挂在其左子树。至此k-d tree构建完成。

构建kd树的过程是对一个平面或者空间进行逐步划分的过程:
在这里插入图片描述

我们到这里或许会有疑问, 这个东西干啥用呢? 我们拿一个样本来尝试搜索它的最近邻:
在这里插入图片描述
拿这个(3,5)点来看, 我们如果想搜索它的k近邻, 首先要找到包含目标点的叶子节点, 以此节点作为“当前最近点”, 这个点的话,我们先从根节点开始(7,2), 第一个维度3<7, 可以断定(3,5)在根节点的左子树上, 然后到了左子树的根节点(5,4), 第二个维度5>4, 可以断定在(5,4)的右子树上, (5,4)的右子树只有一个节点(4,7), 此时维度也比较完毕了, 那么就先假定(4,7)这个点为(3,5)的最近邻节点,这时候就出现了第一个红圆。

然后递归的向上回退, 即回到(4,7)的父节点(5,4)上面,因为我这个点只是在(4,7)那个区域, 但具体在什么位置不知道, 所以就可以算一下与(4,7)的父节点(5,4)有多远,如果发现离父节点更近一些, 就会认为这个父节点是离(3,5)最近的节点。 果然, (3,5)离得(5,4)近一些, 这时候, 最近邻节点更新成(5,4), 出现了绿色的那个圆。

这时候, 我们得考虑一下, 因为父节点(5,4)把左边的区域化成了两块, (4,7)是(5,4)的一个子节点, 这时候我们需要检查(5,4)的另一个子节点里面是不是还有离着目标点更近的点, 具体方法就是看看那个绿色的圆是否已经和另一个子节点对应的区域相交, 如果相交之后, 就有可能在另一个子节点对应区域里面有离着目标点最近的, 这里相交了, 所以这时候移动到父节点的另一个子节点, 也就是(2,3)上。 计算这个点和目标点的距离, 发现比父节点的距离近, 那么就更新最近邻节点, 出现了蓝色的圆。如果不想交, 那么就再去找父节点(5,4)的父节点(7,2), 这个点已经是根节点了, 然后再看一下当前的蓝色圆是否与(7,2)的另一个子节点的区域是否相交, 发现不相交了, 这样找到了最近的节点是(2,3)。 具体过程是下面这个图:

在这里插入图片描述
下面看一个更加复杂的例子:这个例子之所以说是复杂, 是因为与根节点的另一个节点所在的区域也相交了。
在这里插入图片描述
简单的过一遍这个过程, 首先S认为D是它的最近邻节点, 那么就以SD为半径画个圆, 然后回退到D的父节点B, 发现BS距离在圆之外, 且圆与B的另一个子节点所在区域也没有相交, 于是回退到B的父节点A, A是根节点, 另一个节点是C所在区域, 发现圆与C所在区域有相交, 于是到了C, 再看C里面有两个子节点G和E, 计算了一下, 就找到了最近点E。

下面分析一下kd树的时间复杂度, 我们发现, kd树的搜索是沿着树的高度直上直下进行搜索比较的, 这样,最后的搜索时间复杂度就和树的高度有关了, 之所以我们要尽可能的建立平衡的二叉树(找每一个维度中位数所在的样本), 就是为了能让树的高度小一些, 这时候, 能把搜索效率提到最高, n个节点的话, 如果建成平衡二叉树的话, 差不多时间复杂度由 O ( n ) O(n) O(n)提到 O ( l o g n ) O(logn) O(logn)

3. 线性回归的概率理解

线性回归我们肯定是很熟悉了, 给定一批数据 ( Y i , X i 1 , X i 2 , . . . , X i p ) (Y_i, X_{i1}, X_{i2}, ...,X_{ip}) (Yi,Xi1,Xi2,...,Xip), 模型是

Y = X β + ε Y=X \beta+\varepsilon Y=Xβ+ε
这里采用了向量化的表示方法, β \beta β里面就是那些参数了, 我们喜欢称之为 W W W, 而这里的 ε \varepsilon ε就是误差项。 我们的误差函数往往定义成下面这个样子:
J ( β ) = ∥ X β − Y ∥ 2 J(\beta)=\|X \beta-Y\|^{2} J(β)=XβY2
也就是平方差损失。 我们往往通过最小二乘法,就可以得到最终 β \beta β的解析解:
β ^ = ( X T X ) − 1 X T Y \hat{\beta}=\left(X^{T} X\right)^{-1} X^{T} Y β^=(XTX)1XTY

但是上面有个细节,就是为啥误差函数要定义成平方差损失呢? 这个问题之前没有研究过, 这次学习看到了, 所以整理下来吧, 这个误差函数其实是基于误差项的一个假设进行推导出来的。

我们知道, 对于每个样本来说, 线性回归的公式可以写成:
y i = β T x i + ε i y^i=\beta^Tx^i+\varepsilon ^i yi=βTxi+εi

其中我们是假设这里的误差项服从标准正态的, 也就是 ε ∼ N ( 0 , σ 2 ) \varepsilon\sim N(0, \sigma^2) εN(0,σ2), 这时候就有
p ( ε i ) = 1 σ 2 π e − ε i 2 2 σ 2 p(\varepsilon^i)=\frac{1}{\sigma \sqrt {2\pi}}e^{-\frac{{\varepsilon^i}^2}{2\sigma^2}} p(εi)=σ2π 1e2σ2εi2
这时候, 如果把 ε i \varepsilon^i εi用上面等式替换掉, 就会得到:
P ( y i ∣ x i , β , σ ) = 1 σ 2 π e − ( y i − β T x i ) 2 2 σ 2 P\left({y}^{i} \mid x^{i}, {\beta},{\sigma}\right)=\frac{1}{\sigma \sqrt{2 \pi}} e^{\frac{-\left(y^{i}-\beta^{T} x^{i}\right)^{2}}{2 \sigma^{2}}} P(yixi,β,σ)=σ2π 1e2σ2(yiβTxi)2
这时候, 我们如果想让 y i y_i yi β T x i \beta^Tx^i βTxi非常接近, 那么我们就要最大化上面的这个公式, 找那个最高点, 也就是均值所在处。 即我们需要 M a x i m u m L i k e l i h o o d : P ( y i ∣ x i , β , σ ) Maximum Likelihood: P\left({y}^{i} \mid x^{i}, {\beta},{\sigma}\right) MaximumLikelihood:P(yixi,β,σ), 如果是针对所有样本, 我们使用连乘 M a x i m u m L i k e l i h o o d : ( 1 σ 2 π ) n ∏ i = 1 n e − ( y i − β T x i ) 2 2 σ 2 Maximum Likelihood:\left(\frac{1}{\sigma \sqrt{2 \pi}}\right)^{n} \prod_{i=1}^{n} e^{\frac{-\left(y^{i}-\beta^{T} x^{i}\right)^{2}}{2 \sigma^{2}}} MaximumLikelihood:(σ2π 1)ni=1ne2σ2(yiβTxi)2
我们用log转成加法运算:
log ⁡ [ P ( D ∣ β , σ ) ] = l o g { ( 1 σ 2 π ) n ∏ i = 1 n e − ( y i − β T x i ) 2 2 σ 2 } \log [P(D \mid \beta, \sigma)]=log\{\left(\frac{1}{\sigma \sqrt{2 \pi}}\right)^{n} \prod_{i=1}^{n} e^{\frac{-\left(y^{i}-\beta^{T} x^{i}\right)^{2}}{2 \sigma^{2}}}\} log[P(Dβ,σ)]=log{(σ2π 1)ni=1ne2σ2(yiβTxi)2}

下面换成加法运算:
arg ⁡ max ⁡ w { ( 1 σ 2 π ) n ∏ i = 1 n e − ( y i − β T x i ) 2 2 σ 2 } = arg ⁡ max ⁡ w ( log ⁡ [ ( 1 σ 2 π ) ) n ] + ∑ i = 1 n − ( y i − β T x i ) 2 2 σ 2 \operatorname{arg} \max _{w}\left\{\left(\frac{1}{\sigma \sqrt{2 \pi}}\right)^{n} \prod_{i=1}^{n} e^{\frac{-\left(y^{i}-\beta^{T} x^{i}\right)^{2}}{2 \sigma^{2}}}\right\}=\arg \max _{w}\left(\operatorname{log}\left[\left(\frac{1}{\sigma \sqrt{2 \pi}}\right)\right)^{n}\right]+\sum_{i=1}^{n} \frac{-\left(y^{i}-\beta^{T} x^{i}\right)^{2}}{2 \sigma^{2}} argwmax{(σ2π 1)ni=1ne2σ2(yiβTxi)2}=argwmax(log[(σ2π 1))n]+i=1n2σ2(yiβTxi)2
由于 l o g log log的那块和 2 σ 2 2\sigma^2 2σ2都是常数, 我们可以直接去掉, 就变成了:
arg ⁡ max ⁡ w ∑ i = 1 n − ( y i − β T x i ) 2 \underset{w}{\arg \max } \sum_{i=1}^{n}-\left(y^{i}-\beta^{T} x^{i}\right)^{2} wargmaxi=1n(yiβTxi)2
我们把负号去掉, 就相当于最小化了, 就得到了最终的形式:
arg ⁡ min ⁡ w ∑ i = 1 n ( y i − β T x i ) 2 \underset{w}{\arg \min } \sum_{i=1}^{n}\left(y^{i}-\beta^{T} x^{i}\right)^{2} wargmini=1n(yiβTxi)2

这才得到了最终的损失函数的形式。 可以发现也不是随便定义的吧。

有了损失函数, 在推导一下解析解
L ( β ) = ∥ X β − Y ∥ 2 = ( X β − Y ) T ( X β − Y ) = Y T Y − Y T X β − β T X T Y + β T X T X β \mathcal{L}(\beta)=\|X \beta-Y\|^{2}=(X \beta-Y)^{T}(X \beta-Y)=Y^{T} Y-Y^{T} X \beta-\beta^{T} X^{T} Y+\beta^{T} X^{T} X {\beta} L(β)=XβY2=(XβY)T(XβY)=YTYYTXββTXTY+βTXTXβ
我们对 β \beta β求梯度
∇ β L ( β ) = ∇ β ( Y T Y − Y T X β − β T X T Y + β T X T X β ) = 0 − X T Y − X T Y + 2 X T X β = 2 X T X β − 2 X T Y \nabla_{\beta} \mathcal{L}(\beta)=\nabla_{\beta}\left(Y^{T} Y-Y^{T} X \beta-\beta^{T} X^{T} Y+\beta^{T} X^{T} X \beta\right)=0-X^{T} Y-X^{T} Y+2 X^{T} X \beta=2 X^{T} X \beta-2 X^{T} Y βL(β)=β(YTYYTXββTXTY+βTXTXβ)=0XTYXTY+2XTXβ=2XTXβ2XTY
令梯度等于0, 我们就可以得到 2 X T X β = 2 X T Y 2 X^{T} X \beta=2 X^{T} Y 2XTXβ=2XTY, 即推导出 β = ( X T X ) − 1 X T Y \beta=\left(X^{T} X\right)^{-1} X^{T} Y β=(XTX)1XTY

细节补充好了, 下面是关于线性回归的小总结:

在这里插入图片描述

关于线性回归, 先不充到这里吧。

参考

  • 统计学习方法之KNN笔记
  • 白话机器学习算法理论+实战之K近邻算法

这篇关于K近邻算法和线性回归的幕后细节的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/602287

相关文章

代码随想录算法训练营:12/60

非科班学习算法day12 | LeetCode150:逆波兰表达式 ,Leetcode239: 滑动窗口最大值  目录 介绍 一、基础概念补充: 1.c++字符串转为数字 1. std::stoi, std::stol, std::stoll, std::stoul, std::stoull(最常用) 2. std::stringstream 3. std::atoi, std

人工智能机器学习算法总结神经网络算法(前向及反向传播)

1.定义,意义和优缺点 定义: 神经网络算法是一种模仿人类大脑神经元之间连接方式的机器学习算法。通过多层神经元的组合和激活函数的非线性转换,神经网络能够学习数据的特征和模式,实现对复杂数据的建模和预测。(我们可以借助人类的神经元模型来更好的帮助我们理解该算法的本质,不过这里需要说明的是,虽然名字是神经网络,并且结构等等也是借鉴了神经网络,但其原型以及算法本质上还和生物层面的神经网络运行原理存在

大林 PID 算法

Dahlin PID算法是一种用于控制和调节系统的比例积分延迟算法。以下是一个简单的C语言实现示例: #include <stdio.h>// DALIN PID 结构体定义typedef struct {float SetPoint; // 设定点float Proportion; // 比例float Integral; // 积分float Derivative; // 微分flo

LeetCode 算法:二叉树的中序遍历 c++

原题链接🔗:二叉树的中序遍历 难度:简单⭐️ 题目 给定一个二叉树的根节点 root ,返回 它的 中序 遍历 。 示例 1: 输入:root = [1,null,2,3] 输出:[1,3,2] 示例 2: 输入:root = [] 输出:[] 示例 3: 输入:root = [1] 输出:[1] 提示: 树中节点数目在范围 [0, 100] 内 -100 <= Node.

【Java算法】滑动窗口 下

​ ​    🔥个人主页: 中草药 🔥专栏:【算法工作坊】算法实战揭秘 🦌一.水果成篮 题目链接:904.水果成篮 ​ 算法原理 算法原理是使用“滑动窗口”(Sliding Window)策略,结合哈希表(Map)来高效地统计窗口内不同水果的种类数量。以下是详细分析: 初始化:创建一个空的哈希表 map 用来存储每种水果的数量,初始化左右指针 left

ROS2从入门到精通4-4:局部控制插件开发案例(以PID算法为例)

目录 0 专栏介绍1 控制插件编写模板1.1 构造控制插件类1.2 注册并导出插件1.3 编译与使用插件 2 基于PID的路径跟踪原理3 控制插件开发案例(PID算法)常见问题 0 专栏介绍 本专栏旨在通过对ROS2的系统学习,掌握ROS2底层基本分布式原理,并具有机器人建模和应用ROS2进行实际项目的开发和调试的工程能力。 🚀详情:《ROS2从入门到精通》 1 控制插

算法与数据结构面试宝典——回溯算法详解(C#,C++)

文章目录 1. 回溯算法的定义及应用场景2. 回溯算法的基本思想3. 递推关系式与回溯算法的建立4. 状态转移方法5. 边界条件与结束条件6. 算法的具体实现过程7. 回溯算法在C#,C++中的实际应用案例C#示例C++示例 8. 总结回溯算法的主要特点与应用价值 回溯算法是一种通过尝试各种可能的组合来找到所有解的算法。这种算法通常用于解决组合问题,如排列、组合、棋盘游

【图像识别系统】昆虫识别Python+卷积神经网络算法+人工智能+深度学习+机器学习+TensorFlow+ResNet50

一、介绍 昆虫识别系统,使用Python作为主要开发语言。通过TensorFlow搭建ResNet50卷积神经网络算法(CNN)模型。通过对10种常见的昆虫图片数据集(‘蜜蜂’, ‘甲虫’, ‘蝴蝶’, ‘蝉’, ‘蜻蜓’, ‘蚱蜢’, ‘蛾’, ‘蝎子’, ‘蜗牛’, ‘蜘蛛’)进行训练,得到一个识别精度较高的H5格式模型文件,然后使用Django搭建Web网页端可视化操作界面,实现用户上传一

线性回归(Linear Regression)原理详解及Python代码示例

一、线性回归原理详解         线性回归是一种基本的统计方法,用于预测因变量(目标变量)与一个或多个自变量(特征变量)之间的线性关系。线性回归模型通过拟合一条直线(在多变量情况下是一条超平面)来最小化预测值与真实值之间的误差。 1. 线性回归模型         对于单变量线性回归,模型的表达式为:         其中: y是目标变量。x是特征变量。β0是截距项(偏置)。β1

【数据结构与算法 经典例题】使用队列实现栈(图文详解)

💓 博客主页:倔强的石头的CSDN主页               📝Gitee主页:倔强的石头的gitee主页    ⏩ 文章专栏:《数据结构与算法 经典例题》C语言                                   期待您的关注 ​​ 目录  一、问题描述 二、前置知识 三、解题思路 四、C语言实现代码 🍃队列实现代码: