Python 数据分析入门:和谁最像,就更可能属于哪一类?一文入门 K近邻算法

适合人群:Python 初学者 / 数据分析入门 / 机器学习入门 / 教学案例分享

在上一篇文章里,我们已经知道了什么是分类:
就是根据已有样本的特征,去判断新样本属于哪一个类别。

那么问题来了:

如果现在来了一个新学生,我们想预测他能不能通过技能考核,计算机到底该怎么判断?

一种非常直观的思路是:

看看这个学生和谁最像。

如果他和过去那些“已经通过考核”的学生更像,那么他大概率也会通过;
如果他和过去那些“没有通过考核”的学生更像,那么他通过的可能性就更低。

这就是今天要讲的内容:

K近邻算法(K-Nearest Neighbor,KNN)

K近邻算法是机器学习中最基础、也最容易理解的分类算法之一。它的核心思想很朴素:

物以类聚,和谁最像,就更可能属于哪一类。

这一篇文章继续沿用“学生职业技能考核通过预测”这个案例,带你从零开始理解:

  • K近邻算法到底在做什么
  • 它为什么叫“近邻”
  • K值是什么意思
  • 距离是怎么计算的
  • 为什么同一个样本,K取不同值,结果可能不同
  • 如何用 Python 完成一个简单的 KNN 分类任务

一、先从一个问题开始:新学生到底更像谁?

还是回到这个熟悉的案例。

学校现在有一批历史数据,里面记录了以往学生的情况,比如:

  • 平时成绩
  • 实训成绩
  • 出勤率
  • 是否参加培训
  • 最终是否通过技能考核

现在来了一个新学生,学校希望提前判断他能不能通过考核。

这时候,一种非常自然的想法就是:

  • 先看看他和哪些老学生比较像
  • 再看这些“相似学生”最后是通过了还是没通过
  • 然后用这些相似学生的结果来推测新学生的结果

比如说:

如果一个新学生的成绩、出勤率、培训情况,都和过去那些“已通过”的学生非常接近,那他通过的概率通常也会比较大。

这其实就是 K近邻算法的基本出发点。


二、什么是 K近邻算法?

K近邻算法,英文叫 K-Nearest Neighbor,简称 KNN。它是机器学习中最基础、最简单的算法之一。

它的核心思路可以概括成一句话:

当一个新样本到来时,先找到离它最近的 K 个样本,再根据这 K 个样本中谁占大多数,来决定新样本属于哪一类。

这里有两个关键词特别重要:

  • 近邻
  • K

1)什么叫“近邻”?

“近邻”就是和当前样本最接近的那些样本。

这里的“接近”不是肉眼看着像,而是要根据样本之间的距离来计算。
距离越小,说明两个样本越相似;距离越大,说明两个样本差别越大。

2)什么叫“K”?

K 就是“选几个邻居”的意思。

比如:

  • K = 1,表示只看最近的 1 个样本
  • K = 3,表示看最近的 3 个样本
  • K = 5,表示看最近的 5 个样本

最后,再根据这 K 个邻居中,大多数属于哪一类,来决定新样本的类别。


三、K近邻到底怎么理解?先不要急着看公式

如果你第一次学 KNN,最重要的不是公式,而是先把它的思路想明白。

可以把它理解成一个非常生活化的判断过程:

假设班里来了一个新同学,你想判断他更像“成绩稳定、能通过考核”的学生,还是更像“学习基础薄弱、存在风险”的学生。

你可能会这样做:

  • 先找几个和他情况最接近的学生
  • 看看这些学生最后表现如何
  • 再据此做出判断

这就是 KNN 的思路。

所以,KNN 的本质并不是去“总结一套复杂规则”,而是:

直接参考周围最相似的样本,让邻居来投票。

这也是为什么 KNN 经常被认为是最适合初学者入门的分类算法之一。


四、KNN 的基本流程,其实只有几步

K近邻算法虽然名字听起来像个专业术语,但它的流程并不复杂,大体可以分成下面几步:

第一步:准备训练数据

也就是准备一批已经知道结果的历史样本。
比如过去学生的成绩、出勤率、培训情况,以及他们最终是否通过考核。

第二步:输入一个新样本

比如一个新学生的数据:

  • 平时成绩 78
  • 实训成绩 80
  • 出勤率 90
  • 参加培训:是

现在我们希望判断他是“通过”还是“未通过”。

第三步:计算这个新样本和所有训练样本之间的距离

距离越小,说明越像;距离越大,说明越不像。

第四步:找出距离最近的 K 个样本

比如 K = 3,就找最近的 3 个邻居。

第五步:看这 K 个邻居中,哪一类占多数

如果最近的 3 个样本中:

  • 2 个是“通过”
  • 1 个是“未通过”

那么就把这个新样本判为“通过”。

所以 KNN 的整体逻辑可以压缩成一句话:

先找最近的邻居,再用邻居投票决定类别。


五、一个最经典的问题:为什么 K 取不同值,结果会变?

这是学习 KNN 时一定会遇到的问题。

假设有一个新样本,现在我们分别取:

  • K = 3
  • K = 5

结果可能会不一样。

为什么?

因为你参考的“邻居范围”变了。

如果一个新样本周围最近的 3 个样本里,“通过”占多数,那么它会被判为“通过”;
但如果扩大到最近的 5 个样本,“未通过”占多数,那么它又可能被判为“未通过”。

这说明什么?

说明 K 值会直接影响分类结果。

K 太小会怎样?

如果 K 很小,比如 K = 1,那么模型会特别依赖离它最近的那个样本。
这样做的好处是判断比较灵敏,但缺点是容易受个别样本影响。

K 太大会怎样?

如果 K 很大,那么参与投票的邻居更多,结果会更“稳”一些。
但缺点是,可能把离得稍远、其实不那么相似的样本也拉进来,导致判断不够精细。

所以 K 值并不是越大越好,也不是越小越好。
在实际应用中,K 通常需要通过实验来确定。


六、KNN 里最关键的一步:怎么判断“谁更像”?

KNN 的核心就是“找最近邻”,而要找最近邻,就必须先解决一个问题:

样本之间的距离怎么计算?

这是 KNN 里最关键的步骤之一。

1)距离越小,表示越相似

KNN 的基本思想是:

  • 距离小 = 更相似
  • 距离大 = 差别更大

所以分类时,系统会计算新样本和每个训练样本的距离,然后找出最近的 K 个。

2)常见的距离度量方法

常见的数值型属性距离度量方法有很多,比如:

  • 欧几里得距离
  • 曼哈顿距离
  • 闵可夫斯基距离
  • 余弦相似度
  • 汉明距离
  • 杰卡德相似系数

对于初学者来说,最常见、也最容易理解的是:

  • 欧几里得距离
  • 曼哈顿距离
欧几里得距离

它就是我们在平面几何里熟悉的“直线距离”。

曼哈顿距离

它更像是在城市街区里走路,只能横着走和竖着走,不能斜着穿过去。

在很多入门案例里,默认使用的就是欧几里得距离。

3)为什么要做数据规范化?

在计算距离之前,通常需要先把各个属性的值进行规范化。

原因很简单:

如果不同特征的量纲差别太大,比如:

  • 平时成绩:0 到 100
  • 出勤率:0 到 100
  • 某个金额特征:0 到 10000

那金额这个特征可能会在距离计算中占据过大的影响,导致结果失衡。

所以在 KNN 中,数据预处理往往很重要。


七、KNN 为什么被认为简单?它到底“简单”在哪?

KNN 被很多教材和课程作为入门算法,不是没有原因的。

因为它的思路非常直观:

  • 不需要先建立一棵复杂的树
  • 不需要先求一个复杂的概率模型
  • 不需要先找到一条最优分界线

它做的事情很朴素:

来了一个新样本,就去训练集中找最像它的几个样本,看他们属于哪一类。

这也是为什么 KNN 往往被认为:

  • 容易理解
  • 容易上手
  • 很适合作为机器学习入门算法

从算法特点上看,它不像某些方法那样先训练出一套明确规则,而是更多依赖样本本身来完成判断。


八、KNN 的优点有哪些?

从入门和实际使用的角度看,KNN 有几个非常明显的优点。

1)思路简单,容易理解

这是它最大的优点。
KNN 的核心逻辑就是“找邻居、看多数、做判断”,非常符合人的直觉。

2)容易实现

无论是自己手写一个简单版本,还是用 sklearn 调用现成模型,KNN 都不算复杂。

3)新样本加入时,不需要重新训练

这一点也很有特点。
当有新样本要加入训练集时,KNN 不需要像某些模型那样重新训练一次。

因为它本来就不是先训练出一个特别复杂的模型,而是“把历史样本先存着,等有新样本时再拿来比较”。


九、KNN 有哪些局限?

KNN 虽然简单直观,但并不代表它没有缺点。

1)分类时计算开销较大

因为每来一个新样本,都要去计算它和训练集中很多样本之间的距离。
如果训练数据很多,这个过程会比较慢。

2)对距离度量比较敏感

如果距离计算方式选得不好,或者数据没有规范化,那么结果可能会受影响。

3)K 值不好确定

K 太小,容易受局部样本影响;
K 太大,又可能把不那么相似的样本也算进去。
所以 K 值通常需要通过实验来确定。

也就是说,KNN 很适合入门理解,但在真正的数据规模很大时,也要注意它的性能问题。


十、继续用学生案例理解 KNN

还是用“学生技能考核预测”这个案例来理解。

假设现在有一个新学生:

  • 平时成绩:79
  • 实训成绩:82
  • 出勤率:91
  • 参加培训:是

过去已经有很多学生的历史数据,并且我们知道他们最后是“通过”还是“未通过”。

KNN 会怎么做?

它不会先急着总结一堆规则,而是会:

  1. 计算这个新学生与所有历史学生之间的距离
  2. 找出最接近的 K 个学生
  3. 看这 K 个学生中,谁的类别占多数
  4. 用多数类别作为新学生的预测结果

如果最近的 3 个学生里,有 2 个通过、1 个未通过,那新学生就更可能被判为“通过”。

所以 KNN 很像一种“参考相似案例”的判断方式。


十一、Python 实操:用 KNN 完成一个简单分类任务

下面直接使用“学生技能考核预测”这组模拟数据来做一个完整示例。
为了让 KNN 能顺利计算,我们这里先只使用数值型特征:

  • 平时成绩
  • 实训成绩
  • 出勤率

类别标签是:

  • 通过
  • 未通过

1)准备数据

import pandas as pd

data = {
    '平时成绩': [82, 76, 90, 60, 71, 88, 67, 95, 78, 85, 69, 92],
    '实训成绩': [85, 70, 92, 58, 75, 90, 65, 96, 80, 87, 68, 94],
    '出勤率': [96, 85, 98, 70, 80, 97, 75, 99, 90, 93, 78, 98],
    '是否通过': ['通过', '未通过', '通过', '未通过', '通过', '通过', '未通过', '通过', '通过', '通过', '未通过', '通过']
}

df = pd.DataFrame(data)
print("原始数据:")
print(df)

2)划分特征和类别

X = df[['平时成绩', '实训成绩', '出勤率']]
y = df['是否通过']

3)划分训练集和测试集

from sklearn.model_selection import train_test_split

X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)

这里的意思是:

  • 75% 的数据用于训练
  • 25% 的数据用于测试

4)做数据规范化

因为 KNN 要计算距离,所以通常要先做规范化处理。

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

5)创建 KNN 模型并训练

from sklearn.neighbors import KNeighborsClassifier

knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train_scaled, y_train)

这里的 n_neighbors=3 表示:

选择距离最近的 3 个邻居来参与投票。

6)查看模型效果

print("测试集准确率:", knn.score(X_test_scaled, y_test))

7)预测新学生是否能通过

现在我们来模拟一个新学生:

  • 平时成绩:79
  • 实训成绩:82
  • 出勤率:91
new_student = [[79, 82, 91]]
new_student_scaled = scaler.transform(new_student)

prediction = knn.predict(new_student_scaled)
print("新学生预测结果:", prediction[0])

如果运行顺利,你会得到这个新学生的预测类别,比如“通过”或“未通过”。


十二、完整代码一次放全

如果你想直接复制运行,可以使用下面这份完整代码:

import pandas as pd
from sklearn.model_selection import train_test_split
from sklearn.preprocessing import StandardScaler
from sklearn.neighbors import KNeighborsClassifier

# 1. 构造学生数据
data = {
    '平时成绩': [82, 76, 90, 60, 71, 88, 67, 95, 78, 85, 69, 92],
    '实训成绩': [85, 70, 92, 58, 75, 90, 65, 96, 80, 87, 68, 94],
    '出勤率': [96, 85, 98, 70, 80, 97, 75, 99, 90, 93, 78, 98],
    '是否通过': ['通过', '未通过', '通过', '未通过', '通过', '通过', '未通过', '通过', '通过', '通过', '未通过', '通过']
}

df = pd.DataFrame(data)

print("原始数据:")
print(df)

# 2. 提取特征和标签
X = df[['平时成绩', '实训成绩', '出勤率']]
y = df['是否通过']

# 3. 划分训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(
    X, y, test_size=0.25, random_state=42
)

# 4. 数据标准化
scaler = StandardScaler()
X_train_scaled = scaler.fit_transform(X_train)
X_test_scaled = scaler.transform(X_test)

# 5. 构建KNN模型
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(X_train_scaled, y_train)

# 6. 模型评估
print("\n测试集准确率:", knn.score(X_test_scaled, y_test))

# 7. 预测新学生
new_student = [[79, 82, 91]]
new_student_scaled = scaler.transform(new_student)

prediction = knn.predict(new_student_scaled)
print("新学生预测结果:", prediction[0])

输出:

原始数据:
    平时成绩  实训成绩  出勤率 是否通过
0     82    85   96   通过
1     76    70   85  未通过
2     90    92   98   通过
3     60    58   70  未通过
4     71    75   80   通过
5     88    90   97   通过
6     67    65   75  未通过
7     95    96   99   通过
8     78    80   90   通过
9     85    87   93   通过
10    69    68   78  未通过
11    92    94   98   通过

测试集准确率: 1.0
新学生预测结果: 通过

十三、如果改一下 K 值,会发生什么?

KNN 最值得动手实验的地方,就是 K 值。

比如你可以试试:

knn = KNeighborsClassifier(n_neighbors=1)

或者:

knn = KNeighborsClassifier(n_neighbors=5)

你会发现,不同的 K 值,模型结果可能会发生变化。

这正说明:

K 值是 KNN 中非常关键的参数。

一般来说:

  • K 较小,模型更灵活,但更容易受噪声影响
  • K 较大,模型更稳定,但可能不够敏感

因此,K 值通常需要通过实验来选择,而不是随便拍一个数字。


十四、这一课最核心要记住什么?

学完 K近邻算法,至少要把下面几件事想清楚。

1)KNN 的核心思想是什么?

找离新样本最近的 K 个样本,用这些邻居的多数类别来决定新样本的类别。

2)“近”是什么意思?

近,就是距离更小,也就是更相似。

3)K 值有什么作用?

K 表示参考多少个邻居,它会直接影响分类结果。

4)为什么要做数据规范化?

因为不同特征量纲不同,会影响距离计算结果。

5)KNN 适合拿来做什么?

  • 适合理解分类的基本思想
  • 适合作为机器学习入门算法
  • 适合样本量不算特别大、特征比较明确的场景

十五、结尾总结

这一课主要解决的是一个非常直观的问题:

如果要判断一个新样本属于哪一类,能不能先看看它和谁最像?

答案就是:

可以,这就是 K近邻算法的基本思想。

通过“学生技能考核预测”这个案例,我们可以建立以下几个核心认识:

  • K近邻算法是机器学习中最基础、最简单的算法之一
  • 它通过比较新样本与训练样本之间的距离来完成分类
  • 它会选出距离最近的 K 个样本,再用多数投票决定类别
  • K 值会影响分类结果,通常需要通过实验来确定
  • 在计算距离之前,通常需要对特征进行规范化

对于初学者来说,KNN 的价值不仅在于“会用一个模型”,更重要的是它能帮助你建立一种非常直观的分类思维:

分类有时候并不需要先总结复杂规则,先看看‘和谁最像’,也能做出判断。


十六、课后思考

建议你自己试着回答下面几个问题:

  1. K近邻算法为什么叫“近邻”?
  2. K 值过大和过小分别可能带来什么问题?
  3. 为什么在 KNN 中要重视距离计算?
  4. 为什么很多情况下需要先做数据规范化?
  5. KNN 和上一篇讲的“分类概述”之间是什么关系?

如果这几个问题你都能比较顺畅地说清楚,那么你对 KNN 的基本思路就已经掌握得比较扎实了。


写在最后

K近邻算法很适合拿来做机器学习入门。
因为它没有特别绕的理论门槛,核心逻辑也很符合人的直觉:

先找最像的邻居,再参考邻居的结果做判断。

如果这篇文章对你有帮助,后面就可以顺着继续学习下一课:

  • 决策树:像老师一样一步步做判断
  • 决策树构建:树的第一步为什么先看这个条件
  • 随机森林:一棵树不够稳,那就很多棵一起投票
Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐