
Scikit-learn KNeighborsClassifier 实战Iris 数据集 5 折交叉验证调参指南在机器学习领域k近邻k-Nearest Neighbors, kNN算法以其直观性和有效性著称。本文将带您深入实战使用Scikit-learn库对经典Iris数据集进行kNN模型调优重点演示如何通过网格搜索和交叉验证找到最佳超参数组合。1. 环境准备与数据加载首先确保已安装必要的Python库。建议使用conda或pip安装scikit-learn、numpy、matplotlib和seaborn。以下是初始化代码import numpy as np import matplotlib.pyplot as plt from sklearn import datasets from sklearn.neighbors import KNeighborsClassifier from sklearn.model_selection import GridSearchCV from sklearn.preprocessing import StandardScaler import seaborn as sns # 加载Iris数据集 iris datasets.load_iris() X iris.data y iris.target feature_names iris.feature_names target_names iris.target_namesIris数据集包含150个样本每个样本有4个特征萼片长度、萼片宽度、花瓣长度、花瓣宽度分为3类鸢尾花。我们先进行简单的数据探索print(f特征矩阵形状: {X.shape}) print(f类别分布: {np.bincount(y)}) plt.figure(figsize(10,6)) sns.pairplot(datapd.DataFrame(X, columnsfeature_names), diag_kindkde, plot_kws{alpha:0.6}) plt.suptitle(Iris数据集特征分布, y1.02) plt.show()2. 数据预处理与标准化kNN算法对特征尺度敏感因此标准化是必要步骤。我们使用StandardScaler将特征缩放到均值为0、方差为1的标准正态分布scaler StandardScaler() X_scaled scaler.fit_transform(X) # 标准化前后对比 fig, (ax1, ax2) plt.subplots(1, 2, figsize(12,5)) sns.boxplot(dataX, axax1).set_title(原始数据) sns.boxplot(dataX_scaled, axax2).set_title(标准化后数据) plt.tight_layout()标准化后的箱线图显示各特征已处于相同量纲这将确保距离计算的公平性。3. 超参数网格搜索设计kNN有三个关键超参数需要优化n_neighbors (k值)决定参与投票的邻居数量weights距离权重策略uniform或distancep距离度量参数1为曼哈顿距离2为欧氏距离我们使用GridSearchCV进行5折交叉验证搜索param_grid { n_neighbors: range(1, 21), weights: [uniform, distance], p: [1, 2] } knn KNeighborsClassifier() grid_search GridSearchCV(knn, param_grid, cv5, scoringaccuracy, n_jobs-1) grid_search.fit(X_scaled, y)4. 结果分析与可视化获取最佳参数组合和交叉验证结果print(f最佳参数: {grid_search.best_params_}) print(f最佳准确率: {grid_search.best_score_:.3f}) # 提取所有参数组合结果 cv_results pd.DataFrame(grid_search.cv_results_) top_results cv_results.sort_values(rank_test_score).head(10)为直观展示参数影响我们绘制热力图# 筛选p2的结果 p2_results cv_results[cv_results[param_p]2] heatmap_data p2_results.pivot_table(indexparam_n_neighbors, columnsparam_weights, valuesmean_test_score) plt.figure(figsize(10,6)) sns.heatmap(heatmap_data, annotTrue, fmt.3f, cmapYlGnBu) plt.title(不同k值和权重策略下的准确率热力图(p2)) plt.xlabel(权重策略) plt.ylabel(k值) plt.show()典型的热力图会显示较小k值1-3时模型容易过拟合中等k值5-10通常表现最佳distance权重策略在多数情况下优于uniform5. 最佳模型验证与决策边界使用最佳参数重新训练模型并可视化决策边界best_knn grid_search.best_estimator_ # 选择两个主要特征进行可视化 X_2d X_scaled[:, :2] # 仅使用前两个特征 best_knn_2d KNeighborsClassifier(**grid_search.best_params_) best_knn_2d.fit(X_2d, y) # 生成网格点 x_min, x_max X_2d[:, 0].min() - 1, X_2d[:, 0].max() 1 y_min, y_max X_2d[:, 1].min() - 1, X_2d[:, 1].max() 1 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) # 预测每个网格点 Z best_knn_2d.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 绘制决策边界 plt.figure(figsize(10,6)) plt.contourf(xx, yy, Z, alpha0.4, cmapviridis) sns.scatterplot(xX_2d[:,0], yX_2d[:,1], huey, paletteviridis, edgecolork) plt.xlabel(feature_names[0]) plt.ylabel(feature_names[1]) plt.title(kNN决策边界可视化(基于前两个特征)) plt.legend(target_names) plt.show()决策边界图清晰展示了kNN的分类逻辑——基于局部邻域进行决策。边界形状会随k值变化小k值边界复杂可能过拟合大k值边界平滑可能欠拟合6. 实际应用建议与注意事项基于本次实验我们总结以下工程实践要点k值选择黄金法则对于小型数据集n100k通常取3-5中型数据集100n1000k取5-10大型数据集n1000k可取√n距离加权策略对比策略优点缺点uniform计算简单忽略距离信息distance更精确对噪声敏感常见陷阱与解决方案维度灾难当特征数过多时考虑特征选择或降维计算效率使用KD树或Ball Tree加速近邻搜索类别不平衡采用加权投票或调整类别权重# 高效近邻搜索示例 from sklearn.neighbors import KDTree kdtree KDTree(X_scaled) distances, indices kdtree.query(X_scaled[:1], k5) print(f最近5个邻居的索引: {indices})扩展技巧尝试不同的距离度量余弦相似度、马氏距离等结合特征重要性进行加权距离计算对超参数搜索空间进行贝叶斯优化# 特征加权距离计算示例 feature_weights np.array([0.2, 0.1, 0.5, 0.2]) # 假设花瓣长度最重要 X_weighted X_scaled * feature_weights通过本指南您已掌握使用Scikit-learn实现kNN分类的完整流程。实际项目中建议将调参过程封装为可复用的Pipeline并结合业务需求持续优化模型性能。