前言

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 算法步骤

  1. 计算待预测样本与所有训练样本的距离
  2. 按距离从小到大排序
  3. 选取距离最小的前 K 个样本
  4. 统计 K 个样本中各类别的出现次数
  5. 出现次数最多的类别即为预测结果

二、案例一:个人性格配对效果预测

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

代码说明

  1. 数据加载:用 pandas.read_excel() 读取 Excel 训练集和测试集
  2. 特征提取:选取四个花的形态特征作为输入,类型标签作为输出
  3. 标准化:使用 sklearn.preprocessing.scale() 做 Z-Score 标准化
  4. 模型训练:KNeighborsClassifier(n_neighbors=3) 创建 K=3 的 KNN 分类器
  5. 模型评估:score() 方法直接计算准确率,对比训练集和测试集效果

总结

  1. KNN 核心是 “近朱者赤”,通过 K 个最近邻居投票决定类别
  2. 距离计算 + K 值选择 + 特征标准化 是 KNN 的三大关键
  3. 特征量纲差异大时,标准化是必不可少的预处理步骤
  4. scikit-learn 的 KNeighborsClassifier 可以快速搭建 KNN 模型
  5. KNN 适合小数据集、低维特征的分类场景,大数据集下效率较低

更多推荐