文章目录
- 前言
- 一、KNN 算法核心原理
- 1.1 算法思想
- 1.2 关键要素
- 1.3 算法步骤
- 二、案例一:个人性格配对效果预测
- 2.1 数据集介绍
- 2.2 数据可视化(3D 散点图)
- 2.3 KNN 建模与预测
- 三、案例二:鸢尾花分类识别
- 3.1 数据集介绍
- 3.2 数据预处理:Z-Score 标准化
- 3.3 完整代码实现
- 总结
前言
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 散点图)
先对数据做三维可视化,直观观察三类人群的分布:
importmatplotlib.pyplotaspltimportnumpyasnp# 加载数据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快速搭建模型:
importnumpyasnpfromsklearn.neighborsimportKNeighborsClassifier# 加载数据data=np.loadtxt("datingTestSet2.txt")X=data[:,:-1]# 特征:前三列y=data[:,-1]# 标签:最后一列# 创建KNN模型,K=25knn=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 完整代码实现
importpandasaspd# ========== 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标准化 ==========fromsklearn.preprocessingimportscale 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模型 ==========fromsklearn.neighborsimportKNeighborsClassifier 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 适合小数据集、低维特征的分类场景,大数据集下效率较低