
一文简单理解KNN最近邻算法
K最近邻 (KNN) 算法是一种用于解决分类和回归问题的监督机器学习方法。 Evelyn Fix 和 Joseph Hodges 于 1951 年开发了该算法,随后 Thomas Cover 对其进行了扩展。本文探讨了 KNN 算法的基本原理、工作原理和实现。
什么是 K 最近邻算法?
KNN 是机器学习中最基本但最重要的分类算法之一。它属于监督学习领域,在模式识别、数据挖掘和入侵检测中有广泛的应用。
它在现实生活中被广泛使用,因为它是非参数的,这意味着它不会对数据的分布做出任何基本假设。我们获得了一些先验数据(也称为训练数据),它将坐标分类为由属性标识的组。
作为示例,请考虑下表包含两个特征的数据点:
现在,给定另一组数据点(也称为测试数据),通过分析训练集将这些点分配到一组。请注意,未分类的点标记为“白色”。
KNN算法背后的直觉
如果我们将这些点绘制在图表上,我们也许能够找到一些簇或组。现在,给定一个未分类的点,我们可以通过观察其最近邻居属于哪个组来将其分配给一个组。这意味着靠近被分类为“红色”的点簇的点被分类为“红色”的概率更高。
直观上,我们可以看到第一个点(2.5,7)应该被分类为“绿色”,第二个点(5.5,4.5)应该被分类为“红色”。
为什么我们需要 KNN 算法?
KNN算法是一种通用且广泛使用的机器学习算法,主要因其简单性和易于实现而被使用。它不需要对底层数据分布进行任何假设。它还可以处理数值和分类数据,使其成为分类和回归任务中各种类型数据集的灵活选择。它是一种非参数方法,根据给定数据集中数据点的相似性进行预测。与其他算法相比,KNN 对异常值不太敏感。
KNN算法的工作原理是根据距离度量(例如欧几里得距离)查找给定数据点的 K 个最近邻。然后,数据点的类别或值由 K 个邻居的多数票或平均值确定。这种方法允许算法适应不同的模式并根据数据的局部结构进行预测。
KNN 算法中使用的距离度量
众所周知,KNN 算法可以帮助我们识别查询点的最近点或组。但是为了确定查询点的最近组或最近点,我们需要一些度量。为此,我们使用以下距离度量:
欧氏距离
这只不过是平面/超平面中两点之间的笛卡尔距离。欧几里得距离也可以可视化为连接所考虑的两个点的直线的长度。该指标帮助我们计算物体在两种状态之间完成的净位移。
曼哈顿距离
当我们对物体移动的总距离而不是位移感兴趣时,通常使用曼哈顿距离度量。该度量是通过对 n 维点的坐标之间的绝对差求和来计算的。
KNN算法如何选择k的值?
k的值在KNN算法中非常关键,用于定义算法中邻居的数量。 k近邻 (kNN) 算法中的 k 值应根据输入数据进行选择。如果输入数据有更多异常值或噪声,则 k 值越高越好。建议为 k 选择一个奇数,以避免分类中出现平局。交叉验证方法可以帮助为给定数据集选择最佳 k 值。
KNN 算法的工作原理
K 最近邻 (KNN) 算法根据相似性原理运行,通过考虑训练数据集中 K 个最近邻的标签或值来预测新数据点的标签或值。
步骤1:选择K的最佳值
- K表示进行预测时需要考虑的最近邻居的数量。
步骤2:计算距离
- 为了测量目标和训练数据点之间的相似性,使用欧几里得距离。计算数据集中的每个数据点与目标点之间的距离。
步骤3:寻找最近邻居
- 与目标点距离最小的 k 个数据点是最近邻点。
步骤4:投票分类或取平均值进行回归
- 在分类问题中, 的类标签是通过进行多数投票来确定的。邻居中出现次数最多的类成为目标数据点的预测类。
- 在回归问题中,类标签是通过取 K 个最近邻的目标值的平均值来计算的。计算出的平均值成为目标数据点的预测输出。
KNN算法的优点
- 算法复杂度不是很高,易于实现。
- 适应度广。根据 KNN 算法的工作原理,它将所有数据存储在内存存储中,因此每当添加新示例或数据点时,算法都会根据该新示例进行自我调整,并对未来的预测做出贡献。
- 很少的超参数。KNN 算法训练中所需的唯一参数是 k 的值和我们希望从评估指标中选择的距离指标。
KNN算法的缺点
- 不能扩展,KNN 算法也被认为是一种惰性算法。该术语的主要意义在于,这需要大量的计算能力和数据存储。这使得该算法既耗时又消耗资源。
- 维度灾难。意味着当维数太高时,该算法很难对数据点进行正确分类。
- 容易过拟合。由于算法受到维度灾难的影响,因此也容易出现过度拟合的问题。因此,通常应用特征选择和降维技术来解决这个问题。
import math
def classifyAPoint(points,p,k=3):
'''
This function finds the classification of p using
k nearest neighbor algorithm. It assumes only two
groups and returns 0 if p belongs to group 0, else
1 (belongs to group 1).
Parameters -
points: Dictionary of training points having two keys - 0 and 1
Each key have a list of training data points belong to that
p : A tuple, test data point of the form (x,y)
k : number of nearest neighbour to consider, default is 3
'''
distance=[]
for group in points:
for feature in points[group]:
#calculate the euclidean distance of p from training points
euclidean_distance = math.sqrt((feature[0]-p[0])**2 +(feature[1]-p[1])**2)
# Add a tuple of form (distance,group) in the distance list
distance.append((euclidean_distance,group))
# sort the distance list in ascending order
# and select first k distances
distance = sorted(distance)[:k]
freq1 = 0 #frequency of group 0
freq2 = 0 #frequency og group 1
for d in distance:
if d[1] == 0:
freq1 += 1
elif d[1] == 1:
freq2 += 1
return 0 if freq1>freq2 else 1
# driver function
def main():
# Dictionary of training points having two keys - 0 and 1
# key 0 have points belong to class 0
# key 1 have points belong to class 1
points = {0:[(1,12),(2,5),(3,6),(3,10),(3.5,8),(2,11),(2,9),(1,7)],
1:[(5,3),(3,2),(1.5,9),(7,2),(6,1),(3.8,1),(5.6,4),(4,2),(2,5)]}
# testing point p(x,y)
p = (2.5,7)
# Number of neighbours
k = 3
print("The value classified to unknown point is: {}".\
format(classifyAPoint(points,p,k)))
if __name__ == '__main__':
main()
本文转载自沐白AI笔记,作者:杨沐白
