在这篇文章中,您将了解用于分类和回归的 K 近邻 (KNN) 算法。阅读本文后,您将了解:
- KNN 使用的模型表示。
- 如何使用 KNN 学习模型(提示:它不学习)。
- 如何使用 KNN 进行预测。
- KNN 的许多名称,包括不同领域如何称呼它。
- 如何准备数据以充分利用 KNN。
- 在哪里可以找到更多关于 KNN 算法的信息。
这篇文章是为开发人员撰写的,不假定有统计学或数学背景。重点在于算法的工作原理以及如何将其用于预测建模问题。如果您有任何问题,请留言,我将尽力回答。
通过我的新书《掌握机器学习算法》启动您的项目,其中包括所有示例的分步教程和Excel 电子表格文件。
让我们开始吧。

机器学习中的 K 近邻
图片由 Valentin Ottone 提供,保留部分权利。
KNN 模型表示
KNN 的模型表示是整个训练数据集。
就这么简单。
KNN 除了存储整个数据集外没有模型,因此不需要学习。
高效的实现可以使用复杂的树状数据结构(如 k-d 树)来存储数据,以提高预测期间新模式的查找和匹配效率。
由于存储了整个训练数据集,您可能需要仔细考虑训练数据的一致性。定期整理、在新数据可用时经常更新以及删除错误和异常数据可能是个好主意。
获取您的免费算法思维导图

方便的机器学习算法思维导图样本。
我创建了一份方便的思维导图,其中包含60多种按类型组织的算法。
下载、打印并使用它。
还可以独家访问机器学习算法电子邮件迷你课程。
使用 KNN 进行预测
KNN 直接使用训练数据集进行预测。
对新实例 (x) 进行预测时,通过在整个训练集中搜索 K 个最相似的实例(邻居),并汇总这 K 个实例的输出变量来完成。对于回归,这可能是平均输出变量;对于分类,这可能是众数(或最常见)类别值。
为了确定训练数据集中 K 个实例中哪些与新输入最相似,使用距离度量。对于实值输入变量,最流行的距离度量是 欧几里得距离。
欧几里得距离计算为新点 (x) 和现有点 (xi) 在所有输入属性 j 上的平方差之和的平方根。
欧几里得距离(x, xi) = sqrt( sum( (xj – xij)^2 ) )
其他流行的距离度量包括:
还有许多其他距离度量可以使用,例如 Tanimoto、Jaccard、Mahalanobis 和 余弦距离。您可以根据数据的特性选择最佳距离度量。如果不确定,可以尝试不同的距离度量和不同的 K 值,看看哪种组合能产生最准确的模型。
如果输入变量类型相似(例如,所有都是宽度和高度),欧几里得距离是一个很好的度量。如果输入变量类型不相似(例如年龄、性别、身高等),曼哈顿距离是一个很好的度量。
K 的值可以通过算法调优找到。尝试许多不同的 K 值(例如,从 1 到 21 的值)并查看哪一个最适合您的问题是个好主意。
KNN 的计算复杂度随训练数据集的大小而增加。对于非常大的训练集,可以通过从训练数据集中抽取样本来计算 K 个最相似的实例,从而使 KNN 变为随机。
KNN 已经存在很长时间了,并且得到了很好的研究。因此,不同学科对它有不同的名称,例如:
- 基于实例的学习:使用原始训练实例进行预测。因此,KNN 通常被称为基于实例的学习或基于案例的学习(其中每个训练实例都是问题领域的一个案例)。
- 懒惰学习:不需要学习模型,所有工作都在请求预测时发生。因此,KNN 通常被称为懒惰学习算法。
- 非参数:KNN 对所解决问题的功能形式不作任何假设。因此,KNN 被称为非参数机器学习算法。
KNN 可用于回归和分类问题。
用于回归的 KNN
当 KNN 用于回归问题时,预测基于 K 个最相似实例的平均值或中位数。
用于分类的 KNN
当 KNN 用于分类时,输出可以计算为 K 个最相似实例中频率最高的类别。每个实例本质上都会为其类别投票,得票最多的类别被视为预测结果。
类别概率可以计算为在一组 K 个最相似实例中属于每个类别的新数据实例的标准化频率。例如,在二元分类问题中(类别为 0 或 1):
p(class=0) = count(class=0) / (count(class=0)+count(class=1))
如果您正在使用 K 并且您有偶数个类别(例如 2 个),那么选择一个奇数 K 值以避免平局是一个好主意。反之,当您有奇数个类别时,使用偶数 K 值。
平局可以通过将 K 增加 1 并查看训练数据集中下一个最相似实例的类别来一致地打破。
维度灾难
KNN 在输入变量数量较少 (p) 时表现良好,但在输入变量数量非常大时会遇到困难。
每个输入变量都可以被视为 p 维输入空间的一个维度。例如,如果您有两个输入变量 x1 和 x2,则输入空间将是二维的。
随着维度的增加,输入空间的体积以指数级增长。
在高维空间中,可能相似的点之间的距离可能非常大。所有点将彼此相距遥远,我们在简单的二维和三维空间中对距离的直觉失效。这起初可能感觉不直观,但这个普遍问题被称为“维度灾难”。
最佳 KNN 数据准备
- 重新缩放数据:如果所有数据都具有相同的尺度,KNN 的性能会好得多。将数据标准化到 [0, 1] 范围是一个好主意。如果数据具有高斯分布,对其进行标准化也可能是个好主意。
- 处理缺失数据:缺失数据意味着无法计算样本之间的距离。这些样本可以被排除,或者可以估算缺失值。
- 降低维度:KNN 适用于低维数据。您可以在高维数据(数百或数千个输入变量)上尝试它,但请注意,它可能不如其他技术表现良好。KNN 可以从特征选择中受益,这可以降低输入特征空间的维度。
进一步阅读
如果您有兴趣在 Python 中从头开始实现 KNN,请查看帖子
以下是一些涵盖 KNN 算法的优秀机器学习书籍,它们从预测建模的角度进行介绍。
- 应用预测建模,回归第 7 章,分类第 13 章。
- 数据挖掘:实用机器学习工具和技术,第 76 和 128 页
- 数据科学实践:来自前线的直言不讳,第 71 页
- 机器学习,第 8 章
另请参阅维基百科上的 K 近邻。
总结
在这篇文章中,您发现了 KNN 机器学习算法。您了解到:
- KNN 存储整个训练数据集,并将其用作其表示。
- KNN 不学习任何模型。
- KNN 通过计算输入样本与每个训练实例之间的相似性来即时进行预测。
- 有许多距离度量可供选择,以匹配您的输入数据结构。
- 在使用 KNN 时,最好重新缩放您的数据,例如使用归一化。
如果您对此帖子或 KNN 算法有任何疑问,请在评论中提问,我将尽力回答。
KNN 适合在两组数据中查找最近的日期,但不包括已使用的最近邻居?如果不是,您会建议我使用什么算法来解决这个问题。
我的疑问是:
A = [‘2016-05-01 00:17:10’, ‘2016-05-01 00:49:06’]
B = [ ‘2016-05-01 01:49:02’, ‘2016-05-01 01:17:06’]
对于
A[0]
,最近的邻居是B[1]
,因此B[1]
在下一步中不再使用,因此A[1]
的最近邻居是B[0]
。感谢您的建议。
嗨,Jason,
请接受我对您关于 kNN 的说明性文章的赞扬。
我非常想知道 k 是如何计算的,使其范围在 1 到 21 之间。
因为关于 k = 21 的值,其原理并不明确。
如果您能阐明得出 k 值在下限和上限之间的方法,我将不胜感激。
嗨,巴瓦尼,好问题。
没有公式可以计算问题的最佳 k 值。
我的建议是使用试错法。在您的问题上尝试不同的 k 值,看看哪个能使模型表现最好。
我通常使用的最佳 k 值是取数据集中观测数量的平方根。
虽然这可能听起来很疯狂;有时,当我的数据集是高维的,将 k 值从 1 迭代到 n,然后计算预测误差,然后确定最佳 k 值对我有效。
好提示。
感谢这个小窍门
嗨,为了获得最佳 K 值,我之前使用过肘部法则,即您绘制一张图表,其中包含不同的 K 值,图表中出现肘部形状的点,您将其选为 K。我也使用了平方根法,但我的数据集很小。
请问对于大型数据集,肘部法则是否有效?
好建议!
试试看吧。
嗨,Jason!
我想知道是否有办法让我检索邻居 ID?
例如:如果 n = 10,我想指定数据点 x,并让算法回复 x 的 10 个最近邻居的 ID。
这是可以做到的事情吗?我正在使用 R 和 Caret 进行工作。如果可能的话,我想坚持使用它。
格鲁吉娜,我不太明白你说的 ID 是什么意思。也许是特定的行号或列值。
您可能需要为您的要求实现一些自定义功能。
你好,Jason
我有一个数据集,记录了完成一个状态所需的时间。例如,状态 1 - 5.2 秒,状态 2 - 5.5 秒,状态 3 - 5.2 秒等。我可以使用 KNN 来匹配输入并判断它属于哪个状态,即使输入与训练数据集不完全接近吗?以及我的数据集需要多复杂才能解决这种多类别匹配问题?
抱歉 Anand,我不太理解这个问题。
非常感谢您的努力。愿上帝保佑。
我很高兴您发现这篇文章有用。
你好,
我想知道输入应该是什么样子?
我有一个 csv 文件,其中包含游戏的“价格”和“分数”,当我尝试标记图表时,
Python 给我的输入报错。
谢谢
您好,感谢您的有用文章。
K 近邻(例如 k=1)会导致过拟合,这是真的吗?
KNN 会在不同的问题上给出不同的结果。
KNN 算法是否也适用于分类变量?
是的。
如何在 R 中使用 knn 处理分类数据?我使用具有分类特征的 kddcup 数据。
也许对分类输入使用汉明距离。
有没有办法为/使用 KNN 选择特征?就像 LASSO 回归可以用于特征选择一样。我假设 LASSO 不能在运行 KNN 之前进行,因为前者是一个参数模型,而后者是一个非参数模型。
是的,考虑 RFE。
我如何找到对 KNN 实现最有影响力的特征?。
我想要从特征列表中选择几个特征。
使用特征选择方法
https://machinelearning.org.cn/an-introduction-to-feature-selection/
嗨,杰森,
请澄清我的疑问,当我在 R 中实现 knn 算法时,我们没有使用懒惰和渴望学习技术。我们什么时候应该使用它们……
此致,
巴加亚什里
KNN 是一种懒惰学习算法。
几乎所有其他常见的机器学习算法都可以被认为是渴望学习(例如,从训练数据准备模型)。
很棒的帖子。感谢您的努力。:)
很高兴它有帮助。
我无法下载思维导图。
在这里尝试
https://machinelearningmastery.leadpages.co/machine-learning-algorithms-mini-course/
如何将 knn 应用于提取的视网膜血管结构,以比较测试图像与训练图像进行生物识别认证
如果您正在处理图像,也许可以尝试 CNN 深度学习方法?
为什么我们使用 KNN 来显示最短路径而不是其他算法,即它的特殊性是什么
我不认为 kNN 被用作最短路径算法,它用于分类和回归。
我该如何将其用于回归?我是否需要像分类一样计算概率?
请看这篇文章
https://machinelearning.org.cn/spot-check-regression-machine-learning-algorithms-python-scikit-learn/
你好,杰森,
我如何使用 knn 进行二元分类?
问题究竟是什么?
你好,Jason博士
我已发送电子邮件询问在恶意软件检测中应该使用哪个算法,您告诉我监督学习需要一个分类算法。
我的问题是,KNN 适合恶意软件检测吗?哪种分类算法最适合恶意软件检测?
感谢您的精彩教程。
我建议测试一套监督学习算法,看看哪种最适合您的问题。
这个过程可以帮助您解决监督预测建模问题
https://machinelearning.org.cn/start-here/#process
嗨
我们如何处理 KNN 中的平局。当邻居保持相同距离时,它如何进行最佳投票?
采用了哪些方法……
在这种情况下,您可以使用随机选择。
事实上,文献中有很多处理平局的方法。快速调查一下可能会有帮助。
我想知道如何将 knn 算法应用于多输入(所有输入都是独立的)。训练算法一切都很好,但如果我想输入新输入(即活动用户输入)并预测其输出,这如何可能?我面临这个问题已经两个月了,暂时我通过取平均值将三个输入转换为一个。请给出建议。
我建议使用 sklearn 来开发您的模型。
然后您可以通过直接调用模型的 predict() 方法进行预测。在此处了解更多信息:
https://machinelearning.org.cn/make-predictions-scikit-learn/
你好,杰森,
我每个不同的输入都得到了相同的输出。是数据有问题还是算法有问题?请指教。
这里有一些想法
https://machinelearning.org.cn/machine-learning-performance-improvement-cheat-sheet/
你好 Jason,
有没有任何算法可以进行分类(k 近邻)与分类变量?如果有,是哪个?
kNN 可以用分类变量进行分类,您必须使用可以处理分类变量的距离度量。
你能解释一下汉明距离的直观概念吗?
如果我的数据集中有性别作为独立变量,并且如果未见数据中的类别为男性,如何预测 Y 值?
更多关于汉明距离的信息请参见此处:
https://en.wikipedia.org/wiki/Hamming_distance
我们如何在包含数值和分类属性混合的数据集上应用 knn 算法。
好问题。您可以对分类变量使用汉明距离,对归一化数值变量使用欧几里得或类似距离,然后将分数相加。
非常棒的帖子!我看到您在不同的帖子中写了不同的方法。
您是否有关于不同机器学习算法(属性、何时使用、限制等)比较的帖子,以便能够比较这些方法?
非常感谢
蒂莫
我通常建议在问题上进行算法抽查,更多详细信息请点击此处:
https://machinelearning.org.cn/faq/single-faq/what-algorithm-config-should-i-use
对于 10 个特征和 2 张人脸,knn 算法是什么?提前感谢。
抱歉,我没跟上,你是什么意思?
KNN 可以使用非度量测量吗?
如果数据集是混合的(数值、标称和二进制)特征,为了对这些数据进行分类,我们需要定义新的度量,能够处理这三种类型。
通常,组合方法广泛用于这种情况。
如果新度量是不同度量的组合,那么很难满足三角不等式,所以它可能是相似度量或距离,但不是度量。
我的问题是
KNN 可以使用这样的度量吗?
我们知道 KNN 需要度量距离。
总而言之
我可以使用 KNN 和非度量测量来对数据进行分类吗?
当然。您可以使用任何您认为合理的距离度量。
我建议保持简单。
杰森,好帖子。谢谢
一个问题——假设有 100 条记录被分类为“是”和“否”。所有 100 条都是“是”,那么第 101 条新记录实际上是“否”的,也会被分类为“否”吗?
不,模型需要“是”和“否”的示例,理想情况下是相同数量的示例。
下午好,感谢您提供这些解释。也许由于我数学方面的不足,您能更详细地解释一下“对于非常大的训练集,kNN 可以通过从训练数据集中抽取样本来计算 k 个最相似的实例,从而使其变为随机”吗?我对“随机”的理解是它通常是随机的。您是说在使用来自非常大数据集的不同测试数据时,kNN 本身会变得随机吗?这难道不取决于您如何选择数据作为测试值吗?非常感谢您能提供任何额外信息。
为了对测试集进行预测,将从训练集中抽取一个随机样本。
这将使给定固定训练集在对相同测试集样本进行预测时产生随机预测。这样做的好处是计算复杂度降低,而技能大致相同。
嗨,Jason,感谢您提供的信息丰富的帖子。您能告诉我对于实现 k-NN 来说,什么是一个好的特征选择方法吗?
好问题,我在这里回答
https://machinelearning.org.cn/faq/single-faq/what-feature-selection-method-should-i-use
我有一个使用测试和训练数据的有效模型。我正在努力寻找在生产环境中实施的最佳方法。我是否需要实现一个函数并遍历数据集,或者是否存在一个命令可以在 Python 中使用大文件对未预见的数据进行预测。
嗨,查德……以下资源可能有助于您了解部署机器学习模型时的最佳实践:
https://machinelearning.org.cn/deploy-machine-learning-model-to-production/
此外,了解管道的概念也可能会有所帮助。
https://machinelearning.org.cn/machine-learning-modeling-pipelines/