一、KNN算法核心思想
-
定义
-
K近邻(K Nearest Neighbor):通过样本在特征空间中与最近邻样本的距离判断其类别/数值。
-
核心思想:若一个样本的k个最相似样本中多数属于某类别,则该样本也属于此类别(分类)或取k个样本目标值的均值(回归)。
-
-
关键问题
-
相似性度量:使用距离公式(如欧氏距离)。
-
K值选择:
-
K过小:易受噪声影响,过拟合风险高。
-
K过大:忽略局部特征,欠拟合风险高。
-
极端情况:若K=训练样本数,模型始终预测训练集中最多类别。
-
-
二、算法流程
分类流程
-
计算未知样本到所有训练样本的距离。
-
按距离升序排列训练样本。
-
选取前K个最近邻样本。
-
统计K个样本中最多类别,作为预测结果。
回归流程
-
计算未知样本到所有训练样本的距离。
-
按距离升序排列训练样本。
-
选取前K个最近邻样本。
-
计算K个样本目标值的均值,作为预测结果。
三、距离度量方法
距离类型 | 公式 | 特点 |
---|---|---|
欧氏距离 | ∑i=1n(xi−yi)2 | 最常用,空间直线距离 |
曼哈顿距离 | $\sum_{i=1}^n | x_i - y_i |
切比雪夫距离 | $\max( | x_i - y_i |
闵可夫斯基距离 | $\left( \sum_{i=1}^n | x_i - y_i |
四、特征预处理
为什么需要?
特征量纲差异过大会影响模型结果(如某个特征的方差远大于其他特征)。
方法对比
方法 | 公式 | 特点 | 适用场景 |
---|---|---|---|
归一化 | X′=max−minX−min | 缩放到[0,1];对异常值敏感 | 小规模精确数据 |
标准化 | X′=σX−μ | 均值为0,标准差为1;抗异常值能力强 | 大规模嘈杂数据 |
代码实现:
python
from sklearn.preprocessing import MinMaxScaler, StandardScaler
# 归一化
scaler = MinMaxScaler(feature_range=(0, 1))
X_normalized = scaler.fit_transform(X)
# 标准化
scaler = StandardScaler()
X_standardized = scaler.fit_transform(X)
五、API使用
分类问题
python
from sklearn.neighbors import KNeighborsClassifier
# 初始化模型(K=3)
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# 预测
y_pred = model.predict(X_test)
回归问题
python
from sklearn.neighbors import KNeighborsRegressor
model = KNeighborsRegressor(n_neighbors=2)
model.fit(X_train, y_train)
y_pred = model.predict([[3, 11, 10]]) # 输入需为二维数组
⚠️ 易错点 :预测时输入必须是二维数组(如[[1]]
而非[1]
)。
六、超参数调优:交叉验证与网格搜索
交叉验证(Cross-Validation)
-
目的:提高模型评估的可靠性。
-
流程:
-
将训练集分为n份(如n=5)。
-
轮流用1份作为验证集,其余n-1份训练模型。
-
取n次评估的平均值作为模型得分。
-
网格搜索(Grid Search)
-
目的:自动寻找最优超参数组合。
-
流程:遍历所有预设参数组合,用交叉验证评估每组性能。
代码实现
python
from sklearn.model_selection import GridSearchCV
# 定义参数网格
param_grid = {'n_neighbors': [1, 3, 5, 7]}
model = KNeighborsClassifier()
# 交叉验证网格搜索
grid = GridSearchCV(model, param_grid, cv=5)
grid.fit(X_train, y_train)
# 输出最优参数
print("Best K:", grid.best_params_)
七、实战案例
鸢尾花分类
python
from sklearn.datasets import load_iris
from sklearn.model_selection import train_test_split
# 1. 加载数据
data = load_iris()
X, y = data.data, data.target
# 2. 划分数据集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2)
# 3. 标准化
scaler = StandardScaler()
X_train = scaler.fit_transform(X_train)
X_test = scaler.transform(X_test)
# 4. 训练模型
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# 5. 评估
accuracy = model.score(X_test, y_test)
手写数字识别
python
import pandas as pd
from sklearn.neighbors import KNeighborsClassifier
# 1. 加载数据(28x28像素)
data = pd.read_csv('digits.csv')
X = data.iloc[:, 1:] / 255 # 归一化像素值
y = data.iloc[:, 0]
# 2. 训练模型
model = KNeighborsClassifier(n_neighbors=3)
model.fit(X_train, y_train)
# 3. 预测新图片
img = plt.imread('digit.png').reshape(1, -1) # 转换为1x784
prediction = model.predict(img)
关键要点总结
-
K值选择:需平衡过拟合与欠拟合(交叉验证调优)。
-
特征预处理:优先使用标准化(鲁棒性强)。
-
距离度量:欧氏距离最常用,高维数据可用曼哈顿距离。
-
评估方法:分类用准确率,回归用均方误差。
-
模型优化:网格搜索+交叉验证是超参数调优黄金组合。