目录
knn(KNearest Neighbors)三要素:
1.距离度量(Distance Metric):
KNN算法中,距离度量是核心,它决定了如何计算新数据点与训练数据点之间的相似度。常用的距离度量包括:
- 欧氏距离(Euclidean Distance):多维空间中最常见的距离度量方式。
- 曼哈顿距离(Manhattan Distance):也称为城市街区距离,适用于各个坐标维度的绝对值之和。
- 闵可夫斯基距离(Minkowski Distance):是欧氏距离和曼哈顿距离的推广,通过参数调整可以变化为其他距离度量。
切比雪夫距离(Chebyshev Distance):在多维空间中,最大坐标差的距离。
2.K值的选择
-
K值的选择对KNN算法的性能有重要影响。K值太小,模型可能会对噪声数据过于敏感,导致过拟合;K值太大,模型可能会受到远离新数据点的训练样本的影响,导致欠拟合。
- K值的选择通常基于经验或通过交叉验证等方法来确定最优的K值。
选择K值的方法:交叉验证,通过交叉验证来评估不同K值的性能,选择最佳K值。
K值的影响
3.决策规则(Decision Rule)
KNN算法的决策规则决定了如何根据K个最近邻的已知类别来确定新数据点的类别。最常见的决策规则包括:
- 平均值(Averaging):对于回归问题,可以取K个最近邻目标值的平均值作为预测结果。
- 加权投票(Weighted Voting):考虑距离的倒数作为权重,距离越近的邻居对预测结果的影响越大。
- 多数投票(Majority Voting):选择K个最近邻中出现次数最多的类别作为新数据点的预测类别。
基本步骤
- 确定K值:选择一个正整数K,代表考虑的最近邻居的数量。
- 计算距离:计算待分类样本与训练集中每个样本的距离。
- 找到最近的K个邻居:根据距离排序,选择距离最近的K个样本。
- 进行投票:让这K个邻居对新样本的类别进行“投票”,最常见的类别即为预测结果。
1.模型
数据决定空间划分
2.策略
k个最近邻的最大类别投票
3.算法
对待分类样本,计算与所有已知样本的距离,获得最近k个样本的标签,“权值最多数”类别为输出待分类样本类别。
K近邻算法的一般流程
1.收集数据:可以使用任何方法
2.准备数据:距离计算所需要的数值,最后是结构化的 数据格式。
3.分析数据:可以使用任何方法
4.训练算法:(此步骤kNN)中不适用
5.测试算法:计算错误率
使用算法:首先需要输入样本数据和结构化的输出结果, 然后运行k-近邻算法判定输入数据分别属于哪个分类, 最后应用对计算出的分类执行后续的处理。
实例:
KD树:优化K-NN搜索
KD树(K-Dimensional Tree)是一种用于多维空间搜索的数据结构,特别适合于K-NN算法中的最近邻搜索。
KD树的优势
- 减少计算量:通过树结构快速缩小搜索范围,减少距离计算的次数。
- 提高效率:在高维数据中尤其有效,避免了暴力搜索的高时间复杂度。
KD树的构建
- 选择轴:在每个维度上选择一个轴进行分割。
- 分割数据:根据选定轴的中位数将数据分为两部分。
- 递归构建:对每部分递归构建子树。
KNN算法:判别模型
KNN算法是一种判别模型,因为它直接从训练数据中学习决策边界。然而,它也可以在某种程度上被视为生成模型,因为它可以估计数据的概率分布。
优点
精度高
对异常值不敏感
无数据输入假定
缺点
计算复杂度高
空间复杂度高
适用数据范围
数值型和标称型
代码实现KNN,以鸢尾花为例
欧式距离为例:
from math import sqrt
distances = np.round([sqrt(np.sum((x_train - x_pre)**2)) for x_train in X_train],3)
K折交叉验证
from sklearn.model_selection import KFold
from sklearn.neighbors import KNeighborsClassifier
X=iris.data
y=iris.target
# 定义我们想要搜索的K值(候选集),这里定义8个不同的值
ks=[1,3,5,7,9,11,13,15]
# 例:进行5折交叉验证,KFold返回的是每一折中训练数据和验证数据的index
# 假设数据样本为:[1,3,5,6,11,12,43,12,44,2],总共10个样本
# 则返回的kf的格式为(前面的是训练数据,后面的是验证数据):
# [0,1,3,5,6,7,8,9],[2,4]
# [0,1,2,4,6,7,8,9],[3,5]
# [1,2,3,4,5,6,7,8],[0,9]
# [0,1,2,3,4,5,7,9],[6,8]
# [0,2,3,4,5,6,8,9],[1,7]
kf =KFold(n_splits=5,random_state=2001,shuffle=True)
# 保存当前最好的K值和对应的准确值
best_k=ks[0]
best_score=0
# 循环每一个K值
for k in ks:
curr_score=0
for train_index,valid_index in kf.split(X):
#每一折的训练以及计算准确率
clf=KNeighborsClassifier(n_neighbors=k)
clf.fit(X[train_index],y[train_index])
curr_score=curr_score+clf.score(X[valid_index],y[valid_index])
#求5折的平均准确率
avg_score=curr_score/5
if avg_score>best_score:
best_k=k
best_score=avg_score
print("现在的最佳准确率:%.2f"%best_score,"现在的最佳K值 %d"%best_k)
print("最终最佳准确率:%.2f"%best_score,"最终的最佳K值 %d"%best_k)
运行效果: