资讯动态

KNN算法实战:从鸢尾花分类入门机器学习

发布时间:2026/8/22 9:55:08 来源:尧图企业网站定制
1. 项目概述从数据到决策的经典一步刚入门机器学习的朋友总会问一个问题有没有一个算法原理简单直观又能快速上手看到效果帮我建立起对分类问题的第一印象我的答案通常是KNN。今天我们就来手把手实现一个基于K近邻算法对经典鸢尾花数据集进行分类预测的项目。这不仅是很多人的机器学习“初恋”更是理解“基于实例学习”和“距离度量”核心思想的绝佳范例。鸢尾花数据集堪称机器学习领域的“Hello World”。它包含了150个样本每个样本有4个特征花萼长度、花萼宽度、花瓣长度、花瓣宽度对应3个类别山鸢尾、变色鸢尾、维吉尼亚鸢尾。我们的任务就是给定一朵鸢尾花的四个测量数据让算法自动判断它属于哪一类。KNN算法将完美诠释什么叫“物以类聚人以群分”——要判断一个新样本的类别只需看看它在特征空间里离得最近的K个“邻居”大多数属于哪一类就把它归为哪一类。整个过程没有复杂的模型训练核心就是计算距离和投票直观得就像我们日常做判断一样。这个项目适合所有对机器学习感兴趣的初学者无论你是学生、转行者还是好奇的业务人员。通过它你不仅能学会如何用Python和Scikit-learn快速搭建一个可运行的分类器更能深入理解数据预处理、特征重要性、模型评估以及算法关键参数如K值的影响。接下来我会带你从零开始拆解每一个步骤背后的逻辑并分享那些只有实际动手才会遇到的“坑”和技巧。2. 核心思路与算法原理解析2.1 KNN算法的工作机制懒惰的“邻居投票法”KNN是一种典型的“懒惰学习”算法。说它“懒”是因为它没有显式的训练过程。模型不会从训练数据中归纳出一个简化的规则或函数比如像线性回归那样得到一个权重向量而是把所有的训练样本本身“记”下来。当需要对一个新样本进行预测时算法才开始工作它计算这个新样本与“记忆库”中每一个样本的距离找出距离最近的K个点然后统计这K个点中哪个类别的样本最多就将新样本判定为该类别。这个过程可以分解为三个核心步骤距离计算选择一种距离度量方式如欧氏距离计算待预测样本与所有训练样本的距离。邻居查找根据计算出的距离对所有训练样本进行排序选出距离最小的前K个样本。投票决策对这K个邻居的类别标签进行统计将出现次数最多的类别作为预测结果。对于回归问题则通常是取K个邻居目标值的平均值。这里的关键在于“距离”和“K值”。距离定义了样本之间的相似度而K值决定了参与投票的“陪审团”规模。K值太小比如K1模型容易受到噪声点的影响变得非常敏感导致过拟合K值太大则可能将距离很远的、不相关的样本也纳入投票使决策边界过于平滑导致欠拟合并且计算量会增大。2.2 为什么选择鸢尾花数据集和KNN对于初学者项目技术选型必须考虑“最小可行性”和“教育意义”。鸢尾花数据集规模小、特征少、类别清晰且线性可分程度高能让我们快速聚焦于算法本身而不是陷入复杂的数据清洗和特征工程中。它的四个特征都是数值型且量纲一致厘米避免了初期就需要处理缺失值、分类变量或标准化等复杂问题。选择KNN算法与之匹配原因有三 第一直观性。KNN的原理无需概率论或优化理论的深厚背景就能理解降低了入门门槛。 第二零训练时间。对于小数据集预测时的计算开销可以接受能让我们立即看到结果。 第三揭示本质。通过调整K值我们可以非常直观地观察到模型复杂度与决策边界形状的变化这是理解偏差-方差权衡的生动教材。注意KNN的“懒惰”特性意味着它的预测阶段计算成本很高因为需要与所有训练样本计算距离。这在海量数据场景下是致命的缺点但对于鸢尾花这样的微型数据集则完全不是问题。2.3 项目流程设计一个完整的机器学习小项目不应只停留在调用fit和predict。一个严谨的流程能帮助我们形成良好的工程习惯。本项目的主要流程如下环境准备与数据加载搭建Python环境导入必要的库如numpy,pandas,sklearn,matplotlib并加载鸢尾花数据集。数据探索性分析查看数据的基本信息形状、类型、统计描述并通过可视化如散点图矩阵、箱线图初步了解特征分布与类别关系。数据预处理虽然鸢尾花数据很干净但我们仍需要将其划分为训练集和测试集这是评估模型泛化能力的关键。有时为了演示也会加入数据标准化步骤。模型训练与预测创建KNN分类器实例设置K值等参数在训练集上“拟合”实质是存储数据然后在测试集上进行预测。模型评估与可视化使用准确率、混淆矩阵、分类报告等指标量化模型性能。同时通过可视化决策边界对于二维特征子集来直观理解模型的分类逻辑。参数调优与影响分析系统地改变K值观察模型在训练集和测试集上性能的变化从而选择最优的K值并深入理解其影响。3. 实操环境搭建与数据初探3.1 工具链选择与配置工欲善其事必先利其器。对于数据科学项目Anaconda发行版是首选它集成了Python、Jupyter Notebook以及绝大多数我们需要的科学计算库。在Jupyter Notebook中逐步运行代码并即时查看结果和图表对于学习和调试来说体验极佳。核心库包括NumPy Pandas用于高效的数值计算和表格数据处理。Pandas的DataFrame结构查看数据非常方便。Matplotlib Seaborn用于数据可视化。Seaborn基于Matplotlib提供了更美观、更高级的统计图形接口。Scikit-learn机器学习核心库。它提供了鸢尾花数据集、数据划分方法、KNN分类器实现以及全套评估工具。其API设计高度一致fit,predict,transform学会一个就能触类旁通。你可以通过以下命令一次性安装所有依赖如果使用Anaconda则大部分已预装pip install numpy pandas matplotlib seaborn scikit-learn jupyter3.2 加载与审视数据让我们从加载数据开始并养成查看数据“长相”的好习惯。# 导入必要的库 import numpy as np import pandas as pd import matplotlib.pyplot as plt import seaborn as sns from sklearn import datasets from sklearn.model_selection import train_test_split from sklearn.neighbors import KNeighborsClassifier from sklearn.metrics import classification_report, confusion_matrix, accuracy_score # 设置绘图风格 sns.set(stylewhitegrid) plt.rcParams[font.sans-serif] [SimHei] # 用来正常显示中文标签 plt.rcParams[axes.unicode_minus] False # 用来正常显示负号 # 加载鸢尾花数据集 iris datasets.load_iris() # 将数据转换为Pandas DataFrame便于查看 iris_df pd.DataFrame(datairis.data, columnsiris.feature_names) iris_df[target] iris.target iris_df[target_name] iris.target_names[iris.target] # 查看数据前5行 print(数据前5行) print(iris_df.head()) # 查看数据集基本信息 print(\n数据集基本信息) print(f数据形状: {iris_df.shape}) print(f特征名称: {iris.feature_names}) print(f类别名称: {iris.target_names}) # 查看数据统计摘要 print(\n数据统计描述) print(iris_df.describe())运行这段代码你会立刻对数据有一个整体把握150行5列4个特征1个目标值。describe()函数输出的统计量均值、标准差、最小值、四分位数等非常重要。例如你会发现花瓣长度petal length的标准差最大可能意味着这个特征在不同类别间差异明显蕴含的分类信息更丰富。3.3 数据可视化看见模式数字是抽象的图形是直观的。在建模前进行可视化探索能帮助我们形成假设甚至发现潜在问题。# 1. 类别分布查看确保数据平衡 plt.figure(figsize(6,4)) sns.countplot(xtarget_name, datairis_df) plt.title(鸢尾花类别分布) plt.xlabel(类别) plt.ylabel(数量) plt.show() # 2. 特征与类别关系的散点图矩阵 sns.pairplot(iris_df, huetarget_name, diag_kindhist, palettehusl) plt.suptitle(鸢尾花特征散点图矩阵按类别着色, y1.02) plt.show() # 3. 特征箱线图查看分布与离群点 plt.figure(figsize(12, 6)) for i, feature in enumerate(iris.feature_names): plt.subplot(2, 2, i1) sns.boxplot(xtarget_name, yfeature, datairis_df) plt.title(f{feature} 箱线图) plt.tight_layout() plt.show()实操心得pairplot图非常强大它同时展示了任意两个特征之间的散点关系以及单个特征的分布直方图。从图中可以清晰看到花瓣长度和花瓣宽度这两个特征组合几乎可以完美地将三个类别分开散点图形成三个明显的簇。这暗示我们也许不需要四个特征只用这两个最强的特征就能取得很好的分类效果。这为后续的特征选择或降维提供了直观依据。箱线图告诉我们数据中是否有离群点。幸运的是鸢尾花数据集非常干净没有明显的离群值。如果存在我们需要决定是删除、修正还是保留因为KNN基于距离对离群点比较敏感。4. 数据预处理与模型构建4.1 划分训练集与测试集这是机器学习中至关重要的一步目的是评估模型对未知数据的泛化能力防止我们陶醉于在训练数据上的虚假高分过拟合。通常我们按照7:3或8:2的比例随机划分。# 分离特征X和目标变量y X iris.data y iris.target # 划分训练集和测试集test_size0.3表示30%作为测试集 # random_state参数用于固定随机种子确保每次运行划分结果一致便于复现 X_train, X_test, y_train, y_test train_test_split(X, y, test_size0.3, random_state42, stratifyy) print(f训练集样本数: {X_train.shape[0]}) print(f测试集样本数: {X_test.shape[0]}) print(f训练集类别分布: {np.bincount(y_train)}) print(f测试集类别分布: {np.bincount(y_test)})关键参数解释test_size0.330%的数据留作最终测试。random_state42这是一个“魔法数字”设定它可以让随机划分的结果固定下来。在分享代码或调试时这能保证所有人得到相同的结果非常重要。stratifyy这是关键技巧它要求划分后的训练集和测试集中各个类别的比例与原始数据集保持一致。对于鸢尾花这样类别平衡的数据似乎没必要但这是一个好习惯。当你的数据类别不均衡时比如99%是A类1%是B类如果不使用分层划分随机划分可能导致测试集中几乎没有B类样本从而使评估结果失真。4.2 特征标准化一个容易被忽视但关键的操作鸢尾花数据的四个特征都是同一量纲厘米且数值范围相近比如花萼长度在4-8之间花瓣长度在1-7之间。在这种情况下标准化并非绝对必要因为距离计算受各特征尺度差异的影响相对较小。但是在绝大多数现实场景中特征标准化是KNN算法的必要前置步骤。为什么因为KNN依赖距离度量。如果一个特征的取值范围是0-10000如工资而另一个是0-1如比例那么在计算欧氏距离时取值范围大的特征将完全主导距离计算结果使其他特征失效。标准化的目的就是将所有特征转换到同一尺度通常是均值为0标准差为1。让我们演示一下这个过程尽管对鸢尾花数据效果不明显但你要掌握这个方法。from sklearn.preprocessing import StandardScaler # 初始化标准化器 scaler StandardScaler() # 重要只在训练集上拟合scaler然后用它来转换训练集和测试集 X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) # 注意这里是transform不是fit_transform # 查看标准化后的数据前两行 print(标准化后的训练集前两行均值≈0标准差≈1) print(X_train_scaled[:2]) print(f\n训练集特征均值{np.mean(X_train_scaled, axis0)}) print(f训练集特征标准差{np.std(X_train_scaled, axis0)})重要警告这是一个初学者极易踩坑的地方。fit_transform包含了计算参数均值和标准差并转换数据两个步骤。我们必须只在训练集上进行fit学习参数然后对训练集和测试集都进行transform应用相同的参数进行转换。如果在测试集上也使用fit_transform等于让模型“偷看”了测试集的信息用测试集计算了新的均值和标准差会导致评估结果过于乐观是一种数据泄露严重不科学4.3 构建并训练KNN模型在Scikit-learn中构建一个模型通常只需要几行代码。关键在于理解创建对象时传入的参数。# 创建KNN分类器实例这里先使用一个默认的K值n_neighbors5 knn KNeighborsClassifier(n_neighbors5) # “训练”模型 —— 对于KNN这一步只是将训练数据存储起来 knn.fit(X_train_scaled, y_train) # 在训练集和测试集上进行预测 y_train_pred knn.predict(X_train_scaled) y_test_pred knn.predict(X_test_scaled) # 计算准确率 train_accuracy accuracy_score(y_train, y_train_pred) test_accuracy accuracy_score(y_test, y_test_pred) print(fK5时模型在训练集上的准确率: {train_accuracy:.4f}) print(fK5时模型在测试集上的准确率: {test_accuracy:.4f})此时你得到了两个准确率。理想情况下两者都高且接近。如果训练集准确率远高于测试集可能是过拟合K值太小如果两者都低可能是欠拟合K值太大或模型不适合。我们初始的K5看起来效果不错。5. 模型评估与深度分析5.1 超越准确率混淆矩阵与分类报告准确率是一个宏观指标但当类别不平衡时它可能具有欺骗性。我们需要更细致的工具。# 生成混淆矩阵 conf_matrix confusion_matrix(y_test, y_test_pred) print(混淆矩阵行真实标签 列预测标签) print(conf_matrix) # 使用Seaborn绘制美观的混淆矩阵热图 plt.figure(figsize(8,6)) sns.heatmap(conf_matrix, annotTrue, fmtd, cmapBlues, xticklabelsiris.target_names, yticklabelsiris.target_names) plt.title(KNN分类器混淆矩阵 (K5)) plt.ylabel(真实类别) plt.xlabel(预测类别) plt.show() # 生成详细的分类报告 print(\n分类报告) print(classification_report(y_test, y_test_pred, target_namesiris.target_names))解读混淆矩阵对角线上的数字是预测正确的样本数。非对角线上的数字则是误判的样本。例如如果矩阵中[1,2]位置是3意味着有3个真实类别为1的样本被错误预测为类别2。通过热图我们可以一目了然地看到模型在哪些类别之间容易混淆。对于鸢尾花数据我们通常会发现setosa山鸢尾很容易被正确分类而virginica和versicolor之间可能会有少量混淆。解读分类报告它提供了每个类别的精确率、召回率、F1-score和支持度。精确率在所有被预测为A类的样本中真正是A类的比例。它关注的是预测结果的准确性。召回率在所有真实为A类的样本中被成功预测为A类的比例。它关注的是模型找出所有A类样本的能力。F1-score是精确率和召回率的调和平均数是一个综合指标在两者需要权衡时很有用。支持度测试集中该类别的真实样本数。这份报告能告诉你模型是否对某个特定类别“偏心”了。5.2 可视化决策边界二维简化为了直观理解KNN如何做决策我们可以将高维空间投影到二维。我们选取两个最具区分度的特征从之前的pairplot可知是花瓣长度和宽度来绘制决策边界。from matplotlib.colors import ListedColormap # 选取两个特征花瓣长度索引2和花瓣宽度索引3 X_train_2d X_train_scaled[:, [2, 3]] X_test_2d X_test_scaled[:, [2, 3]] # 重新在二维特征上训练一个KNN模型 knn_2d KNeighborsClassifier(n_neighbors5) knn_2d.fit(X_train_2d, y_train) # 创建网格点来绘制决策区域 x_min, x_max X_train_2d[:, 0].min() - 0.5, X_train_2d[:, 0].max() 0.5 y_min, y_max X_train_2d[:, 1].min() - 0.5, X_train_2d[:, 1].max() 0.5 xx, yy np.meshgrid(np.arange(x_min, x_max, 0.02), np.arange(y_min, y_max, 0.02)) # 对网格上每一个点进行预测 Z knn_2d.predict(np.c_[xx.ravel(), yy.ravel()]) Z Z.reshape(xx.shape) # 设置颜色映射 cmap_background ListedColormap([#FFAAAA, #AAFFAA, #AAAAFF]) cmap_points ListedColormap([#FF0000, #00FF00, #0000FF]) # 绘制决策区域和训练样本点 plt.figure(figsize(10, 8)) plt.contourf(xx, yy, Z, alpha0.4, cmapcmap_background) plt.scatter(X_train_2d[:, 0], X_train_2d[:, 1], cy_train, cmapcmap_points, edgecolork, s50, label训练集) plt.scatter(X_test_2d[:, 0], X_test_2d[:, 1], cy_test, cmapcmap_points, edgecolork, markers, s100, linewidth1.5, label测试集) plt.xlabel(花瓣长度标准化后) plt.ylabel(花瓣宽度标准化后) plt.title(KNN决策边界可视化 (K5基于花瓣长度宽度)) plt.legend() plt.show()这张图非常直观地展示了KNN的“投票”机制。不同颜色的区域代表模型预测的类别。每个小点训练集或方块测试集的颜色代表其真实类别。你可以看到决策边界是由许多小线段组成的复杂多边形这正是KNN“分段线性”决策的特点。测试样本点落在哪个颜色的区域就被预测为哪个类别。通过观察误判的点比如一个绿色方块落在了蓝色区域你能直观理解模型犯错的原因。6. 核心参数调优与模型选择6.1 K值的选择偏差与方差的权衡K值是KNN唯一的超参数也是最需要调优的。我们可以通过绘制K值与模型性能准确率的关系曲线来寻找最佳K值。# 尝试不同的K值范围从1到训练集样本数但通常不会取太大 k_range range(1, 31) train_accuracies [] test_accuracies [] for k in k_range: knn_temp KNeighborsClassifier(n_neighborsk) knn_temp.fit(X_train_scaled, y_train) train_accuracies.append(knn_temp.score(X_train_scaled, y_train)) test_accuracies.append(knn_temp.score(X_test_scaled, y_test)) # 绘制K值-准确率曲线 plt.figure(figsize(10, 6)) plt.plot(k_range, train_accuracies, label训练集准确率, markero) plt.plot(k_range, test_accuracies, label测试集准确率, markers) plt.xlabel(K值) plt.ylabel(准确率) plt.title(K值对KNN模型性能的影响) plt.legend() plt.grid(True, linestyle--, alpha0.7) plt.show() # 找出测试集上准确率最高的K值 best_k_index np.argmax(test_accuracies) best_k k_range[best_k_index] best_test_accuracy test_accuracies[best_k_index] print(f在测试集上表现最佳的K值是: {best_k}) print(f对应的测试集准确率是: {best_test_accuracy:.4f})解读曲线当K1时训练集准确率通常为1.0因为每个点的最近邻居就是它自己但测试集准确率往往较低。这是典型的过拟合模型对训练数据中的噪声也学得太好了导致泛化能力差。随着K值增大训练集准确率逐渐下降模型变简单测试集准确率通常会先上升后下降。上升阶段模型泛化能力增强下降阶段模型可能变得过于简单无法捕捉数据中的有效模式导致欠拟合。曲线中测试集准确率的峰值点对应的K值通常是我们想要的最佳平衡点。它权衡了模型的复杂度和泛化能力。实操心得K值通常取奇数以避免在投票时出现平票的情况对于二分类问题偶数K也可能导致平票。K值不应超过训练集样本数的平方根这是一个经验法则。对于我们的训练集105个样本sqrt(105)≈10我们的最佳K值很可能在10附近。这个寻找最佳K值的过程本质上就是在进行模型选择。我们使用测试集作为“验证集”来评估不同K值的效果。但在更严谨的流程中我们会将数据划分为训练集、验证集和测试集用验证集来调参用测试集做最终的一次性评估以避免对测试集的多次使用造成信息泄露。6.2 距离度量的选择除了K值距离度量公式也是KNN的一个关键选择尽管在实践中欧氏距离最常用。Scikit-learn的KNeighborsClassifier默认使用闵可夫斯基距离当参数p2时即为欧氏距离。欧氏距离最直观是两点间的直线距离。适用于各个特征维度重要性相似且量纲一致或已标准化的情况。曼哈顿距离各维度坐标差绝对值的和。当数据在高维空间中具有网格状结构时可能更合适对异常值的敏感性略低于欧氏距离。闵可夫斯基距离欧氏距离和曼哈顿距离的泛化形式。你可以通过metric参数来指定距离度量方式。例如使用曼哈顿距离knn_manhattan KNeighborsClassifier(n_neighborsbest_k, metricmanhattan) knn_manhattan.fit(X_train_scaled, y_train) print(f曼哈顿距离下测试集准确率: {knn_manhattan.score(X_test_scaled, y_test):.4f})对于鸢尾花数据由于特征经过标准化且分布相对规整欧氏距离和曼哈顿距离的结果通常相差无几。但在某些特定领域如文本分析、基因序列余弦相似度等其他度量方式可能更合适。6.3 使用交叉验证进行更稳健的评估之前我们只用了一次划分random_state42来评估模型。但单次划分的结果可能具有偶然性。为了得到模型性能更稳健的估计我们使用K折交叉验证。from sklearn.model_selection import cross_val_score # 重新实例化一个模型使用我们找到的最佳K值假设best_k11 final_knn KNeighborsClassifier(n_neighborsbest_k) # 进行5折交叉验证评估指标为准确率 cv_scores cross_val_score(final_knn, X_train_scaled, y_train, cv5, scoringaccuracy) print(f5折交叉验证准确率: {cv_scores}) print(f交叉验证平均准确率: {cv_scores.mean():.4f} (/- {cv_scores.std() * 2:.4f})) # 在整个训练集上重新训练最终模型并在测试集上进行最终评估 final_knn.fit(X_train_scaled, y_train) final_test_accuracy final_knn.score(X_test_scaled, y_test) print(f最终模型在独立测试集上的准确率: {final_test_accuracy:.4f})交叉验证将训练集分成5份轮流用其中4份训练1份验证重复5次。最终得到5个准确率分数。平均准确率是对模型泛化能力的更好估计而标准差则反映了模型性能的稳定性。如果标准差很大说明模型性能对训练数据的划分很敏感可能不够稳定。7. 常见问题、陷阱与进阶思考7.1 KNN算法的优缺点总结通过这个项目你应该对KNN的优缺点有了切身感受优点原理简单易于理解和实现。无需估计参数没有显式的训练过程。对数据分布没有假设。适用于各种类型的数据只要距离度量定义得当。在多分类问题上表现自然。无需像一些算法那样进行改造。对于小规模、低维度、类别边界清晰的数据效果往往不错。缺点计算成本高。预测时需要计算与所有训练样本的距离当训练集很大时样本数N或特征数D很大预测速度会非常慢。这是其最大的瓶颈。对高维数据效果差。这是“维度灾难”的典型体现。在高维空间中所有点之间的距离都趋于相等使得距离度量失去意义。对不平衡数据敏感。如果某个类别的样本数远多于其他类那么新样本的K个邻居很可能大多数都属于这个大类导致预测偏向多数类。对特征尺度和相关性敏感。需要谨慎进行特征标准化且默认的欧氏距离假设各特征相互独立。需要存储全部训练数据。内存占用大。7.2 实操中遇到的典型问题与解决方案问题预测速度太慢。解决方案对于大规模数据可以考虑使用近似最近邻算法如基于树结构的KD-Tree、Ball Tree或者基于局部敏感哈希的算法。Scikit-learn的KNeighborsClassifier默认会自动尝试选择algorithm参数auto,ball_tree,kd_tree,brutebrute是暴力计算小数据可用大数据集用树结构能加速。另外特征降维如PCA也能有效减少计算量。问题如何确定最佳的K值解决方案除了我们上面绘制的学习曲线更严谨的方法是使用网格搜索结合交叉验证。Scikit-learn提供了GridSearchCV工具可以自动遍历你设定的参数组合如K从1到20并用交叉验证评估每一组参数最后给出最佳参数。from sklearn.model_selection import GridSearchCV param_grid {n_neighbors: range(1, 31)} grid_search GridSearchCV(KNeighborsClassifier(), param_grid, cv5, scoringaccuracy) grid_search.fit(X_train_scaled, y_train) print(f最佳参数: {grid_search.best_params_}) print(f最佳交叉验证分数: {grid_search.best_score_:.4f})问题距离度量中所有特征的权重相同吗解决方案默认是相同的。但有时我们知道某些特征更重要。可以为距离计算中的每个特征赋予不同的权重这需要自定义距离函数。更常见的做法是进行特征选择剔除不相关或冗余的特征或者使用能够自动学习特征权重的算法但KNN本身不具备此能力。问题出现平票怎么办解决方案Scikit-learn的KNN在平票时会选择距离总和更小的那个类别或者根据algorithm的实现细节决定。你也可以通过设置weightsdistance参数来使用距离加权投票。此时邻居的投票权重与其距离成反比越近的邻居话语权越重这通常能带来更好的性能并且天然避免了平票问题。7.3 项目扩展与进阶方向完成这个基础项目后你可以从以下几个方向进行拓展深化对机器学习的理解尝试不同的数据集将同样的流程应用到其他分类数据集上如手写数字识别MNIST、葡萄酒分类等感受不同数据特性带来的挑战。引入特征工程尝试对鸢尾花数据构造新的特征如长宽比、面积等看看是否能提升模型性能。或者尝试使用特征选择方法如基于树模型的特征重要性、递归特征消除RFE来筛选特征。对比其他算法用同样的数据尝试逻辑回归、决策树、支持向量机等算法比较它们的性能、速度和结果解释性。这能帮助你建立算法选择的直觉。处理类别不平衡你可以手动构造一个不平衡的鸢尾花数据集比如只取一部分某个类别的样本然后尝试使用过采样如SMOTE、欠采样或为KNN设置class_weight参数来改善模型对少数类的识别能力。探索回归问题KNN也可以用于回归KNeighborsRegressor。你可以找一些回归数据集如波士顿房价将预测类别改为预测连续值体验KNN在回归任务中的应用。这个基于KNN的鸢尾花分类项目就像学习游泳时在浅水区的第一次划水。它让你熟悉了机器学习项目从数据加载、探索、预处理、建模、评估到调参的完整闭环。理解了KNN你就掌握了“基于实例”和“距离度量”这两个贯穿许多机器学习领域的基础概念。当你下次遇到一个分类问题时即使不选用KNN这个项目中学到的评估方法、调参思想和避免数据泄露的准则都将是你工具箱里宝贵的财富。

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价