资讯详情

鸢尾花数据集机器学习算法比较:从数据预处理到模型评估完整指南

📅 2026/11/2 5:58:46 | 华诺云谱 👁 阅读
鸢尾花数据集机器学习算法比较:从数据预处理到模型评估完整指南
简介面向机器学习课程期末作业的鸢尾花数据集算法比较项目适合计算机、电子信息、数学等专业学生完成课程设计、期末大作业或毕业设计时参考。压缩包体量轻巧仅9KB包含7个文件其中4个为标准Python脚本另有一份Markdown文档及少量系统隐藏文件四个脚本分别实现了Logistic回归、随机森林、KNN与决策树四种经典分类算法搭配自带鸢尾花数据集可直接运行并对比不同模型在该数据上的分类准确率与适用性。已有396人学习代码均经过测试运行成功内含结果输出可供对照并采用参数化编程思路数据划分、随机种子、模型超参数等均可按需修改便于反复实验和结果分析。注释清晰、结构明了配合Markdown说明既适合快速完成期末作业也适合在此基础上扩展为毕业设计或课程报告。由具十年仿真经验的资深算法工程师整理内容务实值得相关专业学生下载参考。1. 为什么期末作业都拿鸢尾花“开刀”先看懂这份作业在考什么一份“机器学习期末作业-鸢尾花数据集算法比较”几乎是每个入门机器学习的人都会撞上的坎。它表面上是让你对 150 条鸢尾花样本做分类骨子里考的是三件事会不会处理真实数据、懂不懂算法之间的本质差别、能不能把实验过程讲成一份让人信服的报告。很多人在这一步翻车不是因为代码写不出来而是把 Sklearn 的.fit()一调就以为大功告成等到问“为什么逻辑回归在这个数据集上和决策树打平”时一句话都答不上来。这份作业的聪明之处在于鸢尾花数据集足够小、足够干净但又不是“一眼就能分对”三类样本里有一类线性不可分正好逼着你比较线性模型和非线性模型的边界。从期末作业的角度看它考的不是模型精度能刷到多高而是你有没有理解“数据预处理 → 划分训练集测试集 → 算法选型 → 调参 → 评估 → 结论”这一整套机器学习应用流程。适合谁做适合第一次完整跑通一个机器学习项目、想在报告里讲清楚“为什么选这个算法”的人。这篇笔记就按我自己做这类作业的路径把数据集、算法、代码、参数和坑一次讲透。2. 鸢尾花数据集拿到的 150 条样本里藏着哪些“暗雷”鸢尾花数据集Iris Dataset是机器学习里最经典的入门数据1936 年由统计学家 Ronald Fisher 提出后来被各种教材和课程广泛采用。它包含 150 条样本3 个类别各 50 条分别是 Setosa、Versicolor、Virginica。每个样本有 4 个特征花萼长度Sepal Length、花萼宽度Sepal Width、花瓣长度Petal Length、花瓣宽度Petal Width单位都是厘米。标签是花的种类。数据本身没缺值、没乱码、格式整齐特别适合做算法比较。但越“干净”的数据越容易让人忽略它内部的结构问题直接决定了后面做算法比较时的结论可靠性。2.1 先摸清数据分布三个类别的特征到底长什么样做算法比较之前第一件事不是急于建模而是对数据进行探索性分析。我自己习惯先看特征分布的散点图矩阵用 Pandas 加载数据后在 Sklearn 里内置的数据集基础上转为 DataFrame再用 Seaborn 的pairplot一次看全所有特征组合下的类别分布。import pandas as pd import seaborn as sns import matplotlib.pyplot as plt from sklearn.datasets import load_iris iris load_iris() df pd.DataFrame(iris.data, columnsiris.feature_names) df[species] iris.target_names[iris.target] print(df.head()) print(df.describe()) sns.pairplot(df, huespecies) plt.savefig(iris_pairplot.png, dpi150)这段代码把数据集转成带列名的表格后先打印前 5 行和统计摘要再画出散点图矩阵。df.describe()能快速确认特征范围有无异常而pairplot里的hue参数把三类样本涂成不同颜色——注意看 Setosa 那组它的所有特征都和其他两类分得清清楚楚但 Versicolor 和 Virginica 在花萼长度、花萼宽度上有显著重叠只靠这两个特征很难区分。这就是后面做算法比较的出发点四维特征里只有部分维度有判别力线性模型改怎么应对重叠区域。2.2 划分训练集与测试集随机种子不是随便填的数据结构摸清后下一个动作是划分训练集和测试集。常见做法是用train_test_split默认的 75% 训练、25% 测试比例。但这个数据集只有 150 条一共 37 条测试样本如果划分不当个别类别的分布很容易偏离整体。这里最关键的一步设置stratify参数让训练集和测试集里的类别比例和原始数据集一致。from sklearn.model_selection import train_test_split X iris.data y iris.target X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.25, random_state42, stratifyy ) print(训练集大小:, X_train.shape) print(测试集大小:, X_test.shape)stratifyy表示按标签分布分层采样。对这个小数据集来说这比纯随机切分可靠得多。random_state42则是固定随机种子。不要小看这个参数不固定种子的话每次运行结果都不一样报告里写的精度永远无法被复现作业答辩时老师让你重跑一遍就露馅了。换成任何固定整数都行但一旦定了后续所有实验都要共用同一个随机种子否则多个算法比较时的数据基础不一致比较就没有意义。这里建议把数据划分单独放进一个代码块训练、测试、验证三个集合的划分统一管理。因为这个数据集小一般不做独立的验证集而是靠交叉验证来评估模型稳定性划分策略详见 4.3 节的交叉验证设计。3. 算法比较六个模型的原理、假设和边界算法比较是这份作业的内核很多人在这部分犯的错误是把 Sklearn 里十几个模型全部塞进去跑一遍输出一张精度对比表就完事。但做算法比较不是为了刷数字而是要讲清楚“这个算法凭什么在这个数据集上表现好/差”。所以选哪些算法、各有什么假设必须提前想明白。3.1 线性模型组逻辑回归、线性判别分析和线性 SVM 的取舍鸢尾花数据集上最常见的入门算法组合是逻辑回归Logistic Regression、线性判别分析LDA和线性核 SVM。三个都是线性模型但优化目标完全不同。逻辑回归是直接建模条件概率 P(Y|X)用极大似然估计求解参数输出天然是概率值。它在 Iris 上的问题在于目标函数是“所有样本的似然乘积”样本均衡时表现稳定但对特征尺度敏感。LDA 的思路则不同它不直接分类而是寻找一个投影方向让类间散度最大、类内散度最小。LDA 有个很强的假设——每个类别的特征服从高斯分布且协方差矩阵相同。Iris 数据集恰好基本满足这个假设所以 LDA 在小样本线性分类任务上的表现往往比逻辑回归还要稳。线性 SVM 走的是最大化间隔路线关注的是“离决策边界最近的样本”——也就是支持向量。它不依赖全部样本的统计分布对离群点的鲁棒性比逻辑回归差一些。放在这里对比的价值在于三个线性模型在训练数据上可能精度差不多但支持向量的分布和决策边界的位置差异能帮你在文档里写出“不同优化策略对边界选择的影响”这类分析。3.2 非线性模型组决策树、KNN 和朴素贝叶斯的边界在哪比完线性模型下一步引入三个“不吃线性假设”的模型。决策树Decision Tree通过递归划分特征空间实现分类对异常值和特征尺度不敏感但容易过拟合。KNNK-近邻根本没有训练过程直接记住所有训练样本预测时靠测试样本周围 K 个近邻投票。KNN 的性能高度依赖特征尺度所以使用前必须做标准化否则量级大的特征会主导距离计算。朴素贝叶斯Naive Bayes基于特征独立的强假设在 Iris 这类特征相关性较强的数据上理论上吃亏。同样是直觉上“非线性模型”的算法在这份作业中的表现差异很大。决策树的决策边界是一组轴平行切分在 Iris 上常常把 Versicolor 和 Virginica 的交界处切出锯齿状边界KNN 则能拟合非常复杂的边界但 K 值太小容易把边界切得支离破碎朴素贝叶斯因为独立性假设和真实数据不符往往在这份作业里精度垫底——这个“垫底”本身就是报告里最有价值的一个结论说明模型的假设与数据特征不匹配时算法再经典也得让步。3.3 比较基准与评估指标只看 accuracy 会漏掉信息算法之间比什么指标也是要写在报告核心部分的内容。Iris 是一个三类均衡分类问题每类 50 条样本精度Accuracy看起来够用。但只看精度的问题在于如果某个类别被系统性地误判为另一个类别精度可能依然很高而你却不知道错在哪。所以在算法比较实验里除了最终精度对比还应该输出每个模型的混淆矩阵Confusion Matrix看清哪些类别容易混淆。算法核心参数主要假设Iris 上最常见的表现逻辑回归C决策边界线性精度 0.90~1.00概率输出可解释LDAsolver / shrinkage高斯分布、协方差相同通常表现稳定精度约 0.95线性 SVMC最大间隔、线性可分精度约 0.95支持向量少决策树max_depth / min_samples_leaf无深度大时过拟合风险高KNNK / 距离度量局部结构稳定标准化后精度高K 小易过拟合朴素贝叶斯var_smoothing特征独立常为最低精度有教学价值从这张表可以引出报告里的第二个重点如果某个模型精度格外低要去看是不是假设出了问题而不是一味调参硬撑。比如朴素贝叶斯在 Iris 上精度偏低是因为它默认特征条件独立而 Petal Length 和 Petal Width 相关性极强——用混淆矩阵看到这个现象后文档里就有一句可以写好的分析。4. 从零跑通算法比较源代码怎么写、参数怎么调进入实操环节。下面给出我在做这种期末作业时的一套完整、可复现的源代码框架覆盖数据加载、标准化、训练、评估、可视化整个流程。代码统一用 Sklearn 实现各个算法的关键参数单独标注方便直接改参数观察变化。4.1 统一的建模和评估框架六行代码跑六个模型为了保证算法比较的公平性所有模型必须用同一条数据划分、同一个标准化器、同一套评估指标。我通常写一个统一训练函数把模型对象作为参数传入输出精度和混淆矩阵。from sklearn.linear_model import LogisticRegression from sklearn.discriminant_analysis import LinearDiscriminantAnalysis from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier from sklearn.neighbors import KNeighborsClassifier from sklearn.naive_bayes import GaussianNB from sklearn.metrics import accuracy_score, confusion_matrix, classification_report from sklearn.preprocessing import StandardScaler scaler StandardScaler() X_train_scaled scaler.fit_transform(X_train) X_test_scaled scaler.transform(X_test) models { Logistic Regression: LogisticRegression(max_iter1000, random_state42), LDA: LinearDiscriminantAnalysis(), Linear SVM: SVC(kernellinear, random_state42), Decision Tree: DecisionTreeClassifier(max_depth3, random_state42), KNN: KNeighborsClassifier(n_neighbors5), Naive Bayes: GaussianNB() } for name, model in models.items(): model.fit(X_train_scaled, y_train) y_pred model.predict(X_test_scaled) acc accuracy_score(y_test, y_pred) print(f{name}: {acc:.4f})注意后半段对X_test_scaled用的是transform而不是fit_transform这是因为标准化器的均值和方差必须完全由训练数据估计测试数据只做转换不能参与计算——用测试集的统计量做标准化会引入数据泄漏导致测试精度虚高几乎是这类作业里最常见的坑。逻辑回归里max_iter1000是防止默认的 100 轮迭代不足导致收敛警告如果数据标准后仍看到收敛警告优先增大max_iter而不是把C调大。LDA 没有关键超参数要调这也是它适合做比较基准的原因。决策树我设置了max_depth3目的是防止默认深度下把训练集完全切分导致测试集精度下降。KNN 的n_neighbors5是经验起点后面会单独讨论 K 的取值。4.2 交叉验证小数据集的精度“后悔药”单次划分下算出来的精度有一个严重问题——它依赖那一次 25% 测试集的选择可能偏高也可能偏低。150 条数据本来就少一次划分的方差很大所以我在比较实验里额外加了一层 K 折交叉验证用交叉验证的平均分代替单次划分的分数。from sklearn.model_selection import cross_val_score for name, model in models.items(): cv_scores cross_val_score(model, X_train_scaled, y_train, cv5) print(f{name} 交叉验证: {cv_scores.mean():.4f} (/- {cv_scores.std():.4f}))cv5意思是将训练集分成 5 份轮流拿其中 4 份训练、1 份验证。这里用训练集做交叉验证固定测试集只留到最后做最终验证。交叉验证后的平均分能更稳定地反映算法在小数据上的真实水平。如果你在单次划分下看到某模型精度达到 1.00千万别急着写“完美分类”先跑一遍交叉验证——如果交叉验证分数明显低于单次划分分数说明模型在特定测试集上捡了便宜真正的泛化能力没那么强。交叉验证的cv值在这个小数据集上设置成 5 比较合适。cv10每次用 135 条训练、15 条验证训练集之间重合度过高验证分数的方差偏大cv3则训练数据只有 100 条对小数据来说太少评估分数不够稳定。4.3 KNN 的 K 值怎么选从 1 到 20 画一条学习曲线KNN 是这个项目里最值得展开写“调参过程”的模型因为它的超参数 K 直观且效果敏感。K1 时模型会记住每个训练点决策边界极度扭曲K 太大时边界过于平滑又可能把小类别的分布直接抹掉。我一般会把 K 从 1 到 20 逐个测一遍用交叉验证的平均分画一条线找最优值。import numpy as np k_range range(1, 21) cv_mean [] cv_std [] for k in k_range: knn KNeighborsClassifier(n_neighborsk) scores cross_val_score(knn, X_train_scaled, y_train, cv5) cv_mean.append(scores.mean()) cv_std.append(scores.std()) best_k np.argmax(cv_mean) 1 print(f最优 K 值: {best_k}, 交叉验证精度: {max(cv_mean):.4f}) plt.figure(figsize(8, 4)) plt.plot(k_range, cv_mean, markero) plt.xlabel(K) plt.ylabel(CV Accuracy) plt.title(KNN K Value vs CV Accuracy) plt.savefig(knn_k_tuning.png, dpi150)注意np.argmax(cv_mean) 1是因为range从 1 开始数组下标 0 对应 K1。运行结果通常落在 K5~10 之间如果你的结果跑出 K20 还继续上涨说明训练样本的局部结构本来就很稀疏K 再大也只是逼近全局多数类——这一点写进文档里很有说服力K 从 1 到 20 的曲线变化本身就是 KNN“偏差与方差权衡”的直观演示。决策树同理可以画max_depth从 1 到 10 的交叉验证曲线。这两条曲线加进实验报告能让“参数怎么设”从拍脑袋变成有依据的分析过程。4.4 把结果组织成报告表格和图的正确用法所有算法跑完后输出最终对比表和测试集上的混淆矩阵。每个模型都要在同一个测试集上评估只用固定的X_test_scaled和y_test不要再回头调整前一步的划分方式。下面的代码把六个模型的精度放进 DataFrame排序输出。from sklearn.metrics import ConfusionMatrixDisplay results [] for name, model in models.items(): y_pred model.predict(X_test_scaled) results.append({ Model: name, Test Accuracy: accuracy_score(y_test, y_pred), CV Accuracy: cross_val_score(model, X_train_scaled, y_train, cv5).mean() }) results_df pd.DataFrame(results).sort_values(Test Accuracy, ascendingFalse) print(results_df) for name, model in models.items(): model.fit(X_train_scaled, y_train) ConfusionMatrixDisplay.from_estimator(model, X_test_scaled, y_test, display_labelsiris.target_names) plt.title(name) plt.savefig(fconfusion_matrix_{name.replace( , _)}.png, dpi150)这里生成两张核心图表一张是六模型精度对比表另一张是每个模型的混淆矩阵图。报告中表格负责总览混淆矩阵负责解释细节。写文档时我习惯把表格放在最前面然后挑一两个在混淆矩阵里表现异常的模型细写——比如哪个模型把 Virginica 错分成了 Versicolor这种错误暗示了什么特征信息没有被该模型利用这样整份报告就从“跑了六个模型打印结果”升级成“做了一次像样的算法比较”。5. 避坑指南期末作业常见的五个翻车现场这类作业交上去扣分往往不是扣在模型精度不够而是扣在过程不严谨。下面五个坑几乎每个做 Iris 作业的人都会踩中几个列出来供你对照自查。5.1 数据泄漏测试集统计量混进训练过程现象模型在测试集上精度高达 0.98但交叉验证分数只有 0.90差距大得反常。原因在标准化时对全部数据fit_transform导致标准化器使用了测试集的均值和方差测试信息间接参与了训练。另一种常见数据泄漏是用全量数据做特征选择后再划分训练测试集。解决严格按“先划分再在训练集上 fit测试集只 transform”的顺序执行。不仅是标准化任何需要从数据中估计统计量的预处理步骤都要遵守这条规则。特征选择也一样先切分再选择。5.2 KNN 不标准化导致距离计算被单特征主导现象KNN 精度远低于其他模型甚至低于朴素贝叶斯同组同学的结果却正常。原因KNN 依赖欧氏距离而原始四个特征的量纲不同。花萼长度范围约 4.3~7.9花萼宽度约 2.0~4.4花瓣宽度约 0.1~2.5。未标准化时花萼长度的数值差异在距离计算里权重过大花瓣宽度几乎不起作用。解决在统一框架里对训练集做StandardScaler().fit_transform测试集做transform。如果做完标准化后 KNN 精度没有显著提升检查是不是测试集被重复标准化了一次。5.3 忽略了随机种子的作用现象每次运行打印的精度都不同提交给老师的报告里写的精度和自己电脑上重新跑出来的对不上。原因训练测试划分、模型初始化里的随机过程没固定种子。有的算法如 SVM、逻辑回归存在随机成分不固定种子时结果天然有波动。解决在所有引入随机性的地方固定random_state42包括训练测试划分和各模型内部参数。为了保证整份报告可复现也可以在文档开头写明“全部实验固定 random_state42”并把环境依赖列出来这一点在很多课程里是加分项。5.4 混淆矩阵显示某两个类别永远混在一起现象Versicolor 和 Virginica 互误率特别高Setosa 全部判断正确。原因这是数据本身的分布特征造成的不是代码 bug。从 2.1 的散点图矩阵可以看到Setosa 和其他两类在任意二维投影下都是完全分离的而 Versicolor 和 Virginica 有显著重叠区域分类器必然在重叠处出错。解决在文档里明确写出这一观测说明这两个类别在原始特征空间中并非线性可完全分割所有模型在这种情况下精度上限受限。然后可以尝试构造新特征比如花瓣长度和花瓣宽度的比值看看能否降低混淆——这个尝试本身就是很好的实验内容。5.5 决策树出现过拟合报告里却只报训练集精度现象决策树训练集精度 1.00测试集精度 0.84被老师一眼看出没有做模型验证。原因决策树默认会一直生长到所有叶子纯净为止训练集被完全记住。没有限制max_depth或min_samples_leaf时小数据集上极易过拟合。解决给决策树设置max_depth3或min_samples_leaf3然后跑交叉验证。如果让决策树保持默认参数至少要在文档中对比不同深度下的训练精度和交叉验证精度用差距来量化过拟合程度。6. 文档说明怎么写把实验过程讲成一套可信的技术报告期末作业的文档说明往往是决定分数上限的部分。模型精度大家都差不多比的就是谁能把自己的实验过程讲清楚、讲得有依据。我的做法是把文档组织成五个部分和前面实验的逻辑一一对应。6.1 用可视化支撑结论散点图矩阵、学习曲线、混淆矩阵三件套文档里至少要有三张图。第一张是散点图矩阵用来展示数据的分布特性和类别重叠情况为后面的“为什么某些算法精度更高”的叙述做铺垫。第二张是 KNN 的 K 值学习曲线说明超参数的选取不是拍脑袋。第三张是混淆矩阵把精度数字拆解成具体的错误形态。这三张图不需要多花哨但要有针对性说明每张图下面配三四行文字即可。提示写图注时不要写“模型精度高”这类废话写“从混淆矩阵可见Virginica 有 2 条被误判为 Versicolor集中于花瓣特征重叠区域”让图和结论一一对应。6.2 文档结构模板照着填就能交文档我习惯按下面这个顺序组织它天然对应“机器学习应用流程”的标准脉络实验目的明确说明本次实验是对比多个分类算法在 Iris 数据集上的分类性能考察不同算法在小规模多分类任务中的适用性。数据概览Iris 数据集来源、样本量、特征含义、类别分布附散点图矩阵作为探索性分析结果。实验设计说明数据划分比例、随机种子、交叉验证策略、标准化流程强调“训练集与测试集严格分开”的原则。模型原理简述每个模型写两三句算法思路和核心假设不堆公式但要点出假设与数据结构的匹配关系。实验结果与分析呈现精度对比表用交叉验证分数说明模型的稳定性结合混淆矩阵分析错误类型。总结与反思不写“本文实现了……”这种话而是写“通过实验发现线性模型在小规模均衡数据集上表现稳定朴素贝叶斯的特征独立性假设与实际数据不符精度受限”以及“本次实验的局限性与改进方向”比如引入特征工程。6.3 让代码交付物可直接复现环境说明和文件清单最后在文档里附上运行说明这是很多作业容易忽略但老师很看重的一环。写明 Python 版本、Sklearn 版本、运行方式让拿到代码的人能一次跑通。文件清单我一般写清楚清理后不含妥协的、可复现的脚本主体、生成的图表文件和最终的 PDF/Word 文档分别放哪些位置。这里有个实用习惯把每个模型的交叉验证分数连同模型的学号、姓名信息输出到一个 CSV 文件里交给老师前再按分数从高到低排序。这既方便自查也能避免答辩时因为手滑打印出一张没排序的乱表。这个习惯是我做第一份期末作业时因为打乱了输出顺序被老师点名才养成的从那以后所有实验输出都统一走文件落盘。希望这份笔记能帮你少走这些弯路把精力放在真正值得写的分析和结论上做出一份自己心里有底的期末作业。本文还有配套的精品资源点击获取
📝

华诺云谱内容团队

资深建站顾问 · 行业研究员

10年+企业数字化服务经验,专注智能建站、SEO优化与品牌营销,持续输出建站技巧、行业洞察与营销干货,已帮助5000+企业实现数字化增长。

你可能需要的服务

订阅华诺云谱资讯周报

每周一封,精选建站技巧、SEO与营销干货,直达邮箱。已有 8,000+ 企业主订阅,助你少走弯路。

↑