让我们弄清K近邻(KNN)算法究竟是如何运作的。与逻辑回归试图学习特定函数(如Sigmoid)并划定边界不同,KNN采用更直接、基于实例的方法。它常被称为“惰性学习器”,因为它在训练阶段并没有真正建立一个明确的模型。相反,它会记住整个训练数据集。真正的工作发生在你让它对一个新的、未见过的数据点进行分类时。以下是KNN对新数据点进行分类的逐步过程:选择K: 首先,你需要确定'K'的值,它表示要考虑的邻居数量。这是你作为实践者预先设定的一个数值(使其成为一个超参数,正如我们在第2章中讨论过的)。假设你选择$K=3$。计算距离: 当一个新的数据点出现时(我们称之为查询点),KNN会计算该查询点与存储的训练数据集中每一个数据点之间的距离。衡量这种距离的常用方法是使用标准欧几里得距离,它本质上是特征空间中两点之间的直线距离。如果你在$n$维空间中有两个点$p$和$q$,欧几里得距离计算如下: $$d(p, q) = \sqrt{(p_1 - q_1)^2 + (p_2 - q_2)^2 + \dots + (p_n - q_n)^2}$$ 或更简洁地: $$d(p, q) = \sqrt{\sum_{i=1}^{n}(p_i - q_i)^2}$$ 虽然欧几里得距离很常见,但有时也可以根据数据使用其他距离度量方法。核心思想是根据新点与每个训练点的特征,量化它们的“相似”或“接近”程度。找出K个最近邻居: 一旦所有距离都计算完毕,算法会找出与查询点距离最小的'K'个训练数据点。这些就是它的“最近邻居”。如果我们选择$K=3$,KNN会找出距离新点最近的3个训练点。多数投票: 现在,查看这'K'个最近邻居的类别标签。KNN在这些邻居中进行简单的多数投票。K个邻居中最常见的类别将成为新查询点的预测类别。例如,如果$K=3$,并且两个邻居属于A类,一个属于B类,则新点将被分类为A类。如果$K=5$,并且三个邻居是B类,两个是A类,则预测为B类。分配类别: 投票结果就是新数据点的最终分类。让我们将其可视化。想象我们有根据两个特征绘制的属于两个类别(A类为蓝色,B类为橙色)的数据点。一个新的、未分类的点(绿色星形)出现。如果我们设置$K=5$,KNN会找出距离星形最近的5个训练点。{"layout": {"title": "KNN分类示例 (K=5)", "xaxis": {"title": "特征1"}, "yaxis": {"title": "特征2"}, "showlegend": true, "legend": {"title":"数据点"}}, "data": [{"x": [1, 1.5, 2.5, 3, 3.5, 4, 5], "y": [1.5, 2, 1, 2.5, 1.5, 3, 2], "mode": "markers", "type": "scatter", "name": "A类", "marker": {"color": "#1c7ed6", "size": 10}}, {"x": [3.5, 4.5, 5, 5.5, 6, 6.5, 7], "y": [4, 5, 3.5, 4.5, 5.5, 4, 5], "mode": "markers", "type": "scatter", "name": "B类", "marker": {"color": "#f76707", "size": 10}}, {"x": [4], "y": [3.5], "mode": "markers", "type": "scatter", "name": "新点", "marker": {"color": "#37b24d", "size": 14, "symbol": "star"}}, {"x": [3, 4, 3.5, 4.5, 5], "y": [2.5, 3, 4, 5, 3.5], "mode": "markers", "type": "scatter", "name": "最近邻居 (K=5)", "marker": {"color": "rgba(0,0,0,0)", "size": 18, "line": {"color": "#ae3ec9", "width": 2}}}]}K=5的KNN示例。绿色星形是新点。算法找出5个最近的点(用紫色圈出)。四个邻居是B类(橙色),一个邻居是A类(蓝色)。通过多数投票,KNN将新点分类为B类。这就是核心机制。'K'的选择很重要。小的'K'(例如$K=1$)会使模型对噪声或异常值非常敏感;分类结果可能仅凭一个距离很近、可能异常的点就显著改变。非常大的'K'会使决策边界更平滑,但可能会模糊局部模式,或者根据数据集中整体的多数类别对点进行分类,而忽略附近的点。选择合适的'K'通常需要尝试多个值,并查看哪个在独立的验证数据集上表现最佳(这是我们在第2章中提及的一个原理,并将再次讨论)。因为KNN高度依赖距离计算,所以所有特征都处于可比较的尺度也很重要。这就是为什么特征缩放(我们将在第6章介绍)在使用KNN之前通常是一个必要的预处理步骤。如果特征值过大且未正确缩放,它们可能会不成比例地影响距离计算。