【机器学习入门】K 近邻 (KNN) 算法超详细教程 —— 从原理到 sklearn 双案例教学
文章目录
前言
K 近邻(K-Nearest Neighbors,简称 KNN)算法是机器学习中最经典、最易理解的分类算法之一,核心思想就是 “近朱者赤,近墨者黑”—— 一个样本的类别由它周围最近的 K 个邻居投票决定。
本文从原理出发,带你用 Python + scikit-learn 完整实现案例: 鸢尾花分类识别。
一、KNN 算法核心原理
1.1 算法思想
KNN 属于有监督学习的分类算法,逻辑非常直观:
给定一个待预测的新样本,在训练集中找到与它距离最近的 K 个样本,这 K 个样本中出现次数最多的类别,就是新样本的预测类别。
1.2 关键要素
K 值选择:K 太小容易受噪声影响(过拟合),K 太大容易忽略样本差异(欠拟合),通常通过交叉验证选择最优 K 值。
距离度量:常用欧氏距离计算样本间相似度,公式如下:
d
(
x
,
y
)
=
∑
i
=
1
n
(
x
i
−
y
i
)
2
d(x,y) = \sqrt{\sum_{i=1}^{n}(x_i - y_i)^2}
d(x,y)=i=1∑n(xi−yi)2
特征标准化:不同特征量纲差异大时,必须先做标准化,否则数值大的特征会主导距离计算。
1.3 算法步骤
- 计算待预测样本与所有训练样本的距离
- 按距离从小到大排序
- 选取距离最小的前 K 个样本
- 统计 K 个样本中各类别的出现次数
- 出现次数最多的类别即为预测结果
二、案例一:个人性格配对效果预测
2.1 数据集介绍
使用数据集 datingTestSet2.txt,共 1000 条样本,包含 3 个特征和 1 个标签:
- 第 1 列 : 每年旅行里程数
- 第 2 列 : 玩游戏所耗时间百分比
- 第 3 列 : 每周零食消耗数量
- 第 4 列(标签)人物类型 :1 = 好、2 = 中、3 = 差
2.2 数据可视化(3D 散点图)
先对数据做三维可视化,直观观察三类人群的分布:
import matplotlib.pyplot as plt
import numpy as np
# 加载数据
data = np.loadtxt('datingTestSet2.txt')
data_1 = data[data[ : , -1] == 1]
a = data[ : , -1]
b = data[a == 1]
data_2 = data[data[ : , -1] == 2]
data_3 = data[data[ : , -1] == 3]
# 绘制3D散点图
fig = plt.figure()
ax = plt.axes(projection='3d')
ax.scatter(data_1[:,0],data_1[:,1], zs = data_1[:,2],c = "#00DDAA",marker = "o")
ax.scatter(data_2[:,0],data_2[:,1], zs = data_2[:,2],c = "#FF5511",marker = "^")
ax.scatter(data_3[:,0],data_3[:,1], zs = data_3[:,2],c = "#000011",marker = "+")
ax.set(xlabel='Xaxes',ylabel='Yaxes',zlabel='Zaxes')
plt.show()

从图中可以清晰看到三类人群在特征空间中呈现明显的聚类分布,非常适合用 KNN 做分类。
2.3 KNN 建模与预测
使用 scikit-learn 的 KNeighborsClassifier 快速搭建模型:
import numpy as np
from sklearn.neighbors import KNeighborsClassifier
# 加载数据
data = np.loadtxt("datingTestSet2.txt")
X = data[:, :-1] # 特征:前三列
y = data[:, -1] # 标签:最后一列
# 创建KNN模型,K=25
knn = KNeighborsClassifier(n_neighbors=25)
knn.fit(X, y)
# 单样本预测
result = knn.predict([[14459, 4.458902, 0.268444]])
print("单样本预测类别:", result)
# 批量预测
predict_datas = [
[14254, 5.946014, 1.614244],
[22220, 5.297865, 0.638306],
[0, 5.757140, 1.062373],
[16721, 0.000000, 0.242778]
]
print("批量预测结果:", knn.predict(predict_datas))
三、案例二:鸢尾花分类识别
3.1 数据集介绍
使用鸢尾花数据集,包含花的四个形态特征和对应的类别标签:
- 萼片长 (cm) : 花萼的长度
- 萼片宽 (cm) : 花萼的宽度
- 花瓣长 (cm) : 花瓣的长度
- 花瓣宽 (cm) : 花瓣的宽度
- 类型_num : 类别标签(0 / 1 二分类)
- 训练集:66 条样本
- 测试集:9 条样本
3.2 数据预处理:Z-Score 标准化
由于四个特征的数值范围不同,需要先做标准化处理,让每个特征均值为 0、方差为 1,避免数值大的特征主导距离计算。Z-Score 标准化公式:
x
′
=
x
−
μ
σ
x' = \frac{x - \mu}{\sigma}
x′=σx−μ
其中 μ \mu μ 是均值, σ \sigma σ 是标准差。
3.3 完整代码实现
import pandas as pd
# ========== 1. 加载数据 ==========
train_data = pd.read_excel('鸢尾花训练数据.xlsx')
test_data = pd.read_excel('鸢尾花测试数据.xlsx')
train_X = train_data[['萼片长(cm)','萼片宽(cm)','花瓣长(cm)','花瓣宽(cm)']]
train_y = train_data['类型_num']
# ========== 2. Z-Score标准化 ==========
from sklearn.preprocessing import scale
data = pd.DataFrame()
data['萼片长标准化'] = scale(train_X['萼片长(cm)'])
data['萼片宽标准化'] = scale(train_X['萼片宽(cm)'])
data['花瓣长标准化'] = scale(train_X['花瓣长(cm)'])
data['花瓣宽标准化'] = scale(train_X['花瓣宽(cm)'])
test_X = test_data[['萼片长(cm)','萼片宽(cm)','花瓣长(cm)','花瓣宽(cm)']]
test_y = test_data['类型_num']
data_test = pd.DataFrame()
data_test['萼片长标准化'] = scale(test_X['萼片长(cm)'])
data_test['萼片宽标准化'] = scale(test_X['萼片宽(cm)'])
data_test['花瓣长标准化'] = scale(test_X['花瓣长(cm)'])
data_test['花瓣宽标准化'] = scale(test_X['花瓣宽(cm)'])
# ========== 3. 构建KNN模型 ==========
from sklearn.neighbors import KNeighborsClassifier
knn = KNeighborsClassifier(n_neighbors=3)
knn.fit(data,train_y)
train_predicted = knn.predict(data)
score_train = knn.score(data,train_y)
# ========== 4. 模型评估 ==========
test_predicted = knn.predict(data_test)
score_test = knn.score(data_test,test_y)
print(score_test) # 0.8888888888888888
代码说明
- 数据加载:用
pandas.read_excel()读取 Excel 训练集和测试集 - 特征提取:选取四个花的形态特征作为输入,类型标签作为输出
- 标准化:使用
sklearn.preprocessing.scale()做 Z-Score 标准化 - 模型训练:
KNeighborsClassifier(n_neighbors=3)创建 K=3 的 KNN 分类器 - 模型评估:
score()方法直接计算准确率,对比训练集和测试集效果
总结
- KNN 核心是 “近朱者赤”,通过 K 个最近邻居投票决定类别
- 距离计算 + K 值选择 + 特征标准化 是 KNN 的三大关键
- 特征量纲差异大时,标准化是必不可少的预处理步骤
- scikit-learn 的
KNeighborsClassifier可以快速搭建 KNN 模型 - KNN 适合小数据集、低维特征的分类场景,大数据集下效率较低
更多推荐

所有评论(0)