【机器学习】KNN 算法的实用技巧汇总(含实战建议)
KNN(K-Nearest Neighbors,K近邻)是一种非常直观、易于实现的监督学习算法,广泛用于分类和回归任务中。尽管 KNN 理解简单,但在实际应用中,仍有一些小技巧可以显著提高其性能和效果。
本文将基于 Chris Albon 的经典知识卡片,结合实践经验,对 KNN 算法的常见技巧做一次整理和深入讲解。
技巧 1:所有的特征应被放缩到相同的量级
原文:
所有的特征应该被放缩到相同的量级
原因分析:
KNN 是一种基于距离的算法,最常见的距离度量如欧几里得距离(Euclidean Distance)、曼哈顿距离(Manhattan Distance)等都受到各维度特征值大小的直接影响。如果不同特征的量纲不一致(如身高 cm 与体重 kg),可能导致某个特征对距离计算的影响被放大或缩小,导致模型偏倚。
实践建议:
-
对所有数值型特征进行标准化(Standardization)或归一化(Normalization):
from sklearn.preprocessing import StandardScaler scaler = StandardScaler() X_scaled = scaler.fit_transform(X)
-
避免在未缩放的特征数据上直接使用 KNN。
技巧 2:为了避免平票的出现,K 应该选择奇数
原文:
为了避免平票的出现,K 应该选择奇数
原因分析:
KNN 的分类结果通常基于多数投票(majority voting),若邻居中存在相同数量的多个类别,即出现“平票”,模型将难以判断最终类别。
实践建议:
-
若是二分类问题,K 选择奇数(如 3、5、7)可以有效防止平票。
-
多分类问题也可能出现平票,此时应结合具体数据做投票策略优化(比如加权投票)。
技巧 3:投票结果可被距离加权,距离越近投票值越大
原文:
投票的结果会被到邻近样本的距离归一化,这样更近的样本的投票价值更大
原因分析:
距离更近的邻居往往更有代表性,因此可以采用加权 KNN,使得距离越近的样本拥有更大的投票权重,提升分类准确率。
实践建议:
-
使用
scikit-learn
中的weights='distance'
选项:from sklearn.neighbors import KNeighborsClassifier knn = KNeighborsClassifier(n_neighbors=5, weights='distance') knn.fit(X_train, y_train)
-
可以自定义权重函数,如:
weights=lambda d: 1 / (d + 1e-5)
技巧 4:尝试多种不同的距离度量方法
原文:
尝试多种不同的距离度量方法
原因分析:
不同问题、不同数据类型下,选择合适的距离度量方式尤为关键。例如:
-
欧几里得距离(默认,适用于连续变量)
-
曼哈顿距离(适用于稀疏高维数据)
-
闵可夫斯基距离(包含了欧几里得和曼哈顿)
-
汉明距离(适用于分类变量)
-
余弦相似度(用于文本向量化、方向性强的数据)
实践建议:
-
调用
KNeighborsClassifier
时,可以设置metric
参数:knn = KNeighborsClassifier(n_neighbors=5, metric='manhattan')
-
也可使用自定义距离函数:
def custom_distance(x, y): return np.sum(np.abs(x - y)**3)**(1/3)
附加建议:K 值怎么选?
虽然奇数是防止平票的好方式,但最终 K 的选择仍需结合验证集或交叉验证进行调优。例如使用网格搜索:
from sklearn.model_selection import GridSearchCV
param_grid = {'n_neighbors': list(range(1, 30, 2))}
grid = GridSearchCV(KNeighborsClassifier(), param_grid, cv=5)
grid.fit(X_train, y_train)
print(grid.best_params_)
总结
技巧编号 | 内容概述 | 实用性等级 |
---|---|---|
技巧 1 | 特征缩放 | ⭐⭐⭐⭐⭐ |
技巧 2 | K 取奇数,避免平票 | ⭐⭐⭐⭐ |
技巧 3 | 加权投票 | ⭐⭐⭐⭐⭐ |
技巧 4 | 尝试多种距离度量 | ⭐⭐⭐⭐ |
KNN 虽然是基础模型,但在数据预处理、参数调优方面有不少细节可挖掘。只有掌握了这些“简单中的技巧”,才能真正发挥 KNN 的潜力。
参考资料
如果你觉得本文对你有帮助,欢迎点赞、收藏、转发支持!