新闻详情

新闻详情

首页 / 资讯中心 / 详情

机器学习决策树分类算法实验报告:毒蘑菇数据集完整案例与代码

发布时间:2026/10/2 11:22:54来源:尧图网络
机器学习决策树分类算法实验报告:毒蘑菇数据集完整案例与代码
简介这份资源是一份面向高校机器学习课程学习者的决策树分类算法实验报告以毒蘑菇分类为应用场景适合正在完成课程大作业或需要参考完整实验流程的学生。压缩包内仅含1个docx文档大小约1.21MB内容涵盖研究意义、数据描述、模型描述、算法实现、运行结果与总结等完整章节。报告基于UCI Mushroom数据集包含8124个样本、22个原始特征经预处理扩展至117维并对比ID3与CART两种特征选择策略结合后剪枝优化与混淆矩阵评估重点讨论召回率在食品安全分类中的意义。文档还附有算法流程图与伪代码注释可帮助读者理解决策树从特征划分到剪枝的完整构建逻辑并掌握准确率、精度、召回率等指标的计算方式。目前已有7564人学习下载适合作为实验报告撰写与算法复现的参考材料。1. 一份能直接交的决策树实验报告到底该长什么样如果你正在搜「机器学习决策树分类算法实验报告」大概率不是想从零学一遍信息熵公式而是手里有个 deadline需要一份结构完整、代码能跑、图表能贴、结论能写的高分作业。这份资源就是冲着这个场景来的以毒蘑菇数据集Mushroom Dataset为分类对象用决策树完成从数据加载、特征编码、模型训练、可视化到性能评估的全流程附带算法流程图和实验报告框架。它适合两类人——一类是刚入门机器学习、需要一份可复现模板照着改的本科生另一类是做课程设计或大作业、想快速拿到一个「能讲清楚原理 有实验数据支撑」的完整案例的从业者。毒蘑菇数据集只有 8124 条样本、22 个类别型特征标签是 edible / poisonous 二分类干净、无缺失、类别均衡是决策树算法最理想的教学载体不会让你在数据清洗上先耗掉一半时间。2. 毒蘑菇数据集与决策树选型为什么这个组合适合交作业2.1 数据集结构拆解与特征语义毒蘑菇数据集来自 UCI Machine Learning Repository原始文件agaricus-lepiota.data共 8124 行每行 23 个字段第一个字段是类别标签e代表可食用p代表有毒后 22 个字段全部是离散类别特征比如菌盖形状cap-shape、菌盖颜色cap-color、气味odor、菌褶颜色gill-color等。每个特征取值都是单个字母编码例如 odor 字段中aalmond、lanise、nnone、ppungent 等。这种全离散、无缺失的结构意味着你不需要做归一化、不需要处理连续值分箱直接上编码就能喂给决策树。常见做法是用 pandas 读入并指定列名因为原始文件没有表头。列名可以按 UCI 官方文档给的字段顺序手动定义也可以只关注部分核心特征。我一般会保留全部 22 个特征先跑一版基线再根据特征重要性做裁剪。需要特别注意的是stalk-root字段存在缺失值原始数据中用?表示缺失样本有 2480 条占比约 30.5%。处理方式有两种直接删除这些行或者把?当作一个独立类别。两种做法对最终准确率影响不大但删除后样本量降到 5644 条报告里需要说明你的选择理由。2.2 为什么选决策树而不是逻辑回归或 SVM决策树在这个数据集上有三个天然优势。第一特征全是离散类别决策树的每一次分裂就是对一个特征取值的判断不需要像逻辑回归那样做 one-hot 编码后处理稀疏矩阵也不需要像 SVM 那样选核函数。第二决策树的可解释性极强你可以直接把树画出来每个节点写清楚「如果 odor pungent 且 spore-print-color green则判定为有毒」这种规则在实验报告里是加分项。第三训练速度快8124 条样本在普通笔记本上毫秒级完成拟合方便你做多组参数对比实验。对比随机森林单棵决策树在毒蘑菇数据集上的准确率通常能到 99% 以上因为 odor 这个特征本身就极具判别力——几乎所有 pungent 气味的蘑菇都是有毒的。随机森林虽然更稳但在这个任务上提升空间极小反而增加了报告里需要解释的复杂度。如果你的作业要求里明确写了「对比两种以上算法」那可以加一个随机森林做对照但主模型用决策树完全够用。2.3 信息增益、基尼指数与分裂准则的选择决策树的核心是每次分裂时选哪个特征、按什么标准选。ID3 用信息增益C4.5 用信息增益率CART 用基尼指数。scikit-learn 的DecisionTreeClassifier默认用基尼指数criteriongini也支持entropy即信息增益。在毒蘑菇数据集上两者最终准确率差异通常在 0.1% 以内但树的形状会不同。基尼指数计算不涉及对数速度略快信息增益在报告里更容易和「熵」的概念串起来讲。我的建议是实验报告里两个都跑用表格对比训练集准确率、测试集准确率和树深度。这样既展示了你对分裂准则的理解又有了对比数据。参数上max_depth先不限制跑一版看树长到多深然后分别设max_depth3/5/7观察准确率变化找一个「准确率不降但树更简洁」的拐点。min_samples_split和min_samples_leaf在小数据集上影响不大可以不动但报告里提一句「为防止过拟合设置了最小分裂样本数」会显得更专业。3. 从原始数据到可交作业的完整代码流程3.1 数据加载与列名映射原始文件没有表头直接读会得到0,1,2...这样的列名后面画图和分析都不方便。我一般先按 UCI 文档把列名补上再做编码。import pandas as pd import numpy as np from sklearn.tree import DecisionTreeClassifier, export_text, plot_tree from sklearn.model_selection import train_test_split from sklearn.metrics import accuracy_score, classification_report, confusion_matrix import matplotlib.pyplot as plt # 按 UCI 官方字段顺序定义列名 columns [ class, cap-shape, cap-surface, cap-color, bruises, odor, gill-attachment, gill-spacing, gill-size, gill-color, stalk-shape, stalk-root, stalk-surface-above-ring, stalk-surface-below-ring, stalk-color-above-ring, stalk-color-below-ring, veil-type, veil-color, ring-number, ring-type, spore-print-color, population, habitat ] df pd.read_csv(agaricus-lepiota.data, headerNone, namescolumns) print(df.shape) # (8124, 23) print(df[class].value_counts()) # e:4208, p:3916这段代码做了三件事指定列名、加载数据、检查类别分布。headerNone是因为原始文件第一行就是数据不是表头。namescolumns把 23 个字段名一次性赋上。打印shape确认行列数打印class的value_counts确认标签均衡——4208 条可食用、3916 条有毒比例接近 1:1不需要做重采样。3.2 缺失值处理与特征编码stalk-root列有?缺失值需要先处理。同时所有特征都是字符串要转成数值才能喂给 sklearn。# 查看缺失情况 print((df ?).sum().sum()) # 2480 # 方案一把 ? 当作独立类别不做删除 df df.replace(?, missing) # 分离特征和标签 X df.drop(class, axis1) y df[class] # 用 pandas 的 factorize 做标签编码或者用 sklearn 的 OrdinalEncoder from sklearn.preprocessing import OrdinalEncoder encoder OrdinalEncoder() X_encoded encoder.fit_transform(X) # 标签也转成 0/1 y_encoded (y p).astype(int) # p1, e0 print(X_encoded.shape) # (8124, 22) print(np.unique(y_encoded)) # [0 1]这里我选了「把?当独立类别」而不是删除原因是保留全部 8124 条样本能让报告里的数据量更好看而且决策树本身能处理这种类别。OrdinalEncoder会把每个特征的每个取值映射成一个整数虽然对决策树来说整数大小没有实际意义但树的分裂只关心「等于某个值」还是「不等于」所以这种编码是安全的。标签用(y p).astype(int)把有毒设为 1、可食用设为 0后面混淆矩阵和分类报告的可读性更好。3.3 训练集测试集划分与模型拟合X_train, X_test, y_train, y_test train_test_split( X_encoded, y_encoded, test_size0.3, random_state42, stratifyy_encoded ) clf DecisionTreeClassifier( criteriongini, max_depthNone, min_samples_split2, min_samples_leaf1, random_state42 ) clf.fit(X_train, y_train) y_pred clf.predict(X_test) print(Accuracy:, accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred, target_names[edible, poisonous]))test_size0.3表示 70% 训练、30% 测试stratifyy_encoded保证划分后训练集和测试集的标签比例与原始一致。random_state42固定随机种子保证你每次跑的结果一样报告里的数字可复现。不设max_depth让树完全生长先看基线准确率。在毒蘑菇数据集上这版基线通常能到 99.5% 以上因为 odor 特征太强了。3.4 决策树可视化与算法流程图对应实验报告里通常要求画算法流程图和决策树结构图。流程图可以用 draw.io 或 Visio 画核心节点是数据加载 → 缺失值处理 → 特征编码 → 划分训练测试集 → 决策树拟合 → 预测评估 → 可视化。决策树本身的结构图用 sklearn 的plot_tree导出。plt.figure(figsize(20, 10)) plot_tree(clf, feature_namesX.columns, class_names[edible, poisonous], filledTrue, roundedTrue, max_depth3, fontsize8) plt.savefig(tree_visualization.png, dpi150, bbox_inchestight) plt.show() # 也可以用文本形式导出规则 tree_rules export_text(clf, feature_nameslist(X.columns), max_depth3) print(tree_rules)max_depth3是为了让图不至于太大看不清只展示前三层分裂逻辑。filledTrue给节点上色颜色越深表示该节点样本越多。export_text输出的是纯文本规则适合直接贴进报告里当「决策规则说明」。如果你想把整棵树都画出来去掉max_depth参数即可但 8124 条样本完全生长的树可能有几十层图会非常宽建议只画前 3 到 5 层。4. 参数调优与评估让报告数据经得起追问4.1 树深度与准确率的权衡实验不限制深度的树在训练集上准确率接近 100%但测试集可能略低这是过拟合的信号。你可以做一组对照实验把不同max_depth下的训练集和测试集准确率列成表。max_depth训练集准确率测试集准确率树节点数None100%99.6%约 120599.8%99.4%31398.9%98.7%15297.2%97.0%7这张表能直接放进报告里说明「深度为 5 时准确率损失极小但模型复杂度大幅下降」。节点数可以用clf.tree_.node_count获取。注意具体数字会因随机种子和编码方式略有浮动但趋势一致。4.2 特征重要性排序与业务解释决策树自带feature_importances_属性返回每个特征对分类的贡献度。在毒蘑菇数据集上odor 的重要性通常排第一其次是 spore-print-color 和 gill-color。importances pd.Series(clf.feature_importances_, indexX.columns) importances importances.sort_values(ascendingFalse) print(importances.head(10)) importances.head(10).plot(kindbarh, figsize(8, 5)) plt.xlabel(Importance) plt.gca().invert_yaxis() plt.tight_layout() plt.savefig(feature_importance.png, dpi150)这段代码输出前 10 个重要特征并画水平条形图。报告里可以写「odor 特征的重要性达到 0.85 以上说明气味是判断蘑菇毒性的最关键指标这与领域知识一致——有毒蘑菇常带有刺鼻气味。」这种结合业务解释的结论比单纯贴数字更有说服力。4.3 混淆矩阵与分类报告的正确解读cm confusion_matrix(y_test, y_pred) print(cm) import seaborn as sns sns.heatmap(cm, annotTrue, fmtd, cmapBlues, xticklabels[edible, poisonous], yticklabels[edible, poisonous]) plt.xlabel(Predicted) plt.ylabel(Actual) plt.savefig(confusion_matrix.png, dpi150)混淆矩阵的四个格子分别代表真正例有毒判为有毒、真负例可食用判为可食用、假正例可食用误判为有毒、假负例有毒误判为可食用。在毒蘑菇场景下假负例的代价最大——把有毒蘑菇判成可食用会出人命。所以报告里除了准确率还应该单独提一下召回率recall。classification_report会输出每个类别的 precision、recall、f1-score直接引用即可。5. 避坑与常见问题跑通代码只是第一步5.1 列名对不上导致特征错位现象模型准确率异常低或者feature_importances_里某个明显不重要的特征排第一。原因手动定义的列名顺序和原始文件字段顺序不一致导致特征和标签错位。解决对照 UCI 官方文档逐个核对字段顺序或者先用pd.read_csv不指定列名读一遍打印前几行确认每个位置的取值含义再补列名。5.2 把?当字符串直接编码后类别数暴增现象OrdinalEncoder报错或编码后某个特征的取值数量远超预期。原因?被当作普通字符串参与编码如果同时还有其他缺失符号比如空格会多出无意义的类别。解决在读入后立刻执行df.replace(?, missing)或df.replace(?, np.nan)统一处理确保缺失值只有一种表示。5.3 不设 random_state 导致每次结果不一样现象同一份代码跑两次准确率差了 0.5% 以上报告里的数字对不上。原因train_test_split和DecisionTreeClassifier都有随机成分不固定种子每次划分和分裂点都不同。解决在train_test_split和DecisionTreeClassifier里都加上random_state42保证结果可复现。如果作业要求「多次实验取平均」那就用循环跑 10 次不同种子报告里写均值和标准差。5.4 可视化图太大导致保存后看不清现象plot_tree保存的图片节点重叠、文字模糊。原因完全生长的树节点太多figsize不够大或者dpi太低。解决限制max_depth3或max_depth5只画前几层figsize设为(20, 10)dpi150以上bbox_inchestight去掉多余白边。如果必须展示完整树可以导出为 PDF 矢量图而不是 PNG。5.5 把测试集当验证集反复调参现象报告里测试集准确率 99.8%但换一组数据就掉到 95%。原因反复用测试集调max_depth相当于让模型「偷看」了测试集测试集失去了评估泛化能力的意义。解决从训练集里再切一部分做验证集train_test_split两次用验证集调参测试集只在最终评估时用一次。如果数据量小用交叉验证代替单次划分。6. 进阶技巧把实验报告从「能交」推到「高分」6.1 用交叉验证替代单次划分单次train_test_split的评估结果受划分随机性影响较大换成 5 折或 10 折交叉验证能给出更稳的准确率估计。代码上只需把clf.fit和clf.predict换成cross_val_score。from sklearn.model_selection import cross_val_score clf_cv DecisionTreeClassifier(criteriongini, max_depth5, random_state42) scores cross_val_score(clf_cv, X_encoded, y_encoded, cv10, scoringaccuracy) print(CV Accuracy: %.4f /- %.4f % (scores.mean(), scores.std()))cv10表示 10 折交叉验证scores返回 10 个准确率值报告里写「10 折交叉验证平均准确率 99.4%标准差 0.3%」比单次划分的 99.6% 更有说服力。scoringaccuracy可以换成f1或recall取决于你报告里强调哪个指标。6.2 代价敏感学习让模型更怕「漏判有毒」在毒蘑菇场景下假负例有毒判成可食用的代价远高于假正例。sklearn 的DecisionTreeClassifier支持class_weight参数可以给有毒类别更高的权重。clf_weighted DecisionTreeClassifier( criteriongini, max_depth5, class_weight{0: 1, 1: 5}, # 有毒类权重设为可食用的 5 倍 random_state42 ) clf_weighted.fit(X_train, y_train) y_pred_w clf_weighted.predict(X_test) print(classification_report(y_test, y_pred_w, target_names[edible, poisonous]))class_weight{0: 1, 1: 5}表示有毒样本的权重是可食用样本的 5 倍模型在分裂时会更倾向于把有毒样本分对。跑完后对比加权前后的召回率变化如果有毒类召回率从 99% 提升到 99.8%而可食用类准确率只降了 0.5%这就是一个很好的报告结论。6.3 导出决策规则用于报告附录export_text输出的规则可以直接贴进报告附录但默认格式比较粗糙。可以自己写一个递归函数把树转成「如果…那么…」的中文规则。def tree_to_rules(tree, feature_names, class_names): tree_ tree.tree_ rules [] def recurse(node, depth, condition): if tree_.feature[node] ! -2: # 非叶子节点 name feature_names[tree_.feature[node]] threshold tree_.threshold[node] left_cond condition [f{name} {int(threshold)}] right_cond condition [f{name} ! {int(threshold)}] recurse(tree_.children_left[node], depth 1, left_cond) recurse(tree_.children_right[node], depth 1, right_cond) else: # 叶子节点 value tree_.value[node][0] pred class_names[np.argmax(value)] rules.append(f如果 { 且 .join(condition)}则判定为 {pred}) recurse(0, 0, []) return rules rules tree_to_rules(clf, list(X.columns), [edible, poisonous]) for r in rules[:5]: print(r)这段代码递归遍历树的每个节点把分裂条件拼成中文规则。tree_.feature[node] ! -2判断是否是叶子节点tree_.value[node]取该叶子节点的类别分布np.argmax选样本最多的类别作为预测结果。输出的规则可以直接放进报告附录展示「模型学到的具体判断逻辑」。6.4 一个我踩过的坑第一次做这个实验时我把OrdinalEncoder用在了标签列上导致y变成了浮点数classification_report的target_names对不上输出全是0.0和1.0的标签。后来我养成习惯特征编码和标签编码分开做标签用astype(int)显式转换并且在fit之前打印y_train[:10]确认类型。从那以后我每次跑分类任务都强制走一遍「打印前 10 个标签值」的检查省得在评估阶段才发现标签格式不对。希望帮到你。本文还有配套的精品资源点击获取
网站建设高端定制企业官网
RELATED

相关资讯

更多精彩内容,欢迎继续阅读

较早相关资讯

最新相关资讯

踩坑记录 Ubuntu+Intel ARC A770显卡+pytorch+intel_extension_for_pytorch 环境搭建与 TaoToken 统一 Key 接入 2026/10/2 12:03:58

踩坑记录 Ubuntu+Intel ARC A770显卡+pytorch+intel_extension_for_pytorch 环境搭建与 TaoToken 统一 Key 接入

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
AIoT与大模型边缘部署实战:TaoToken统一API通道下的架构设计与工程落地解析 2026/10/2 12:03:52

AIoT与大模型边缘部署实战:TaoToken统一API通道下的架构设计与工程落地解析

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
【含安装包】深度实测 OpenClaw 2.7.9,本地 AI 自动化安装避坑完整指南:TaoToken 统一 Key 接入与 Windows11/macOS 双端验证 2026/10/2 12:03:52

【含安装包】深度实测 OpenClaw 2.7.9,本地 AI 自动化安装避坑完整指南:TaoToken 统一 Key 接入与 Windows11/macOS 双端验证

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Qwen3-Max参数规模超万亿,多项基准测试达SOTA,预告推理增强版本达奥数竞赛满分水平 2026/10/2 12:03:52

Qwen3-Max参数规模超万亿,多项基准测试达SOTA,预告推理增强版本达奥数竞赛满分水平

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
告别云API!本地AI编程神器Qwen3.6-27B部署全攻略:24G显存流畅运行,支持图像视频理解 2026/10/2 12:03:52

告别云API!本地AI编程神器Qwen3.6-27B部署全攻略:24G显存流畅运行,支持图像视频理解

/* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views …

阅读更多 →
Modbus协议详解:从RTU报文、寄存器到工业数据采集调试实战 2026/10/2 12:03:51

Modbus协议详解:从RTU报文、寄存器到工业数据采集调试实战

刚接触工业数据采集那会儿,我接到一个任务:把车间里十几台数控机床的运行状态,包括开关机、报警、主轴转速、当前坐标,全部汇总到一个屏幕上。原本以为要拿着售后手册逐个对接厂商私有协议,结果跑了一圈发现&#xff0…

阅读更多 →

今日资讯

本周资讯

本月资讯

看完文章仍有疑问?

联系尧图顾问,获取一对一建站咨询

立即免费咨询 📞 400-888-8888
📞 ✉