简介月亮数据预测项目完整代码包面向机器学习初学者与数据分析人员演示如何用决策树和随机森林对月亮数据完成建模与预测覆盖数据预处理、特征选择、模型训练、交叉验证与测试评估等完整流程。包内共13个文件以3个Python脚本为核心包含决策树与随机森林分类器实现及简单调用示例配套iml工程配置与xml项目文件便于在IDE中打开另有doc文档说明算法原理、实验步骤和结果分析整个压缩包约1.23MB轻量易用。当前已有874人学习下载。通过源码可直接对比两类算法在月亮数据集上的分类表现理解随机森林如何通过集成多棵树降低过拟合参照文档和脚本可快速复现实验、调整超参数并替换为自己的数据场景适合课程设计、毕业设计或入门实战练习。1. 决策树和随机森林预测月亮数据为什么单棵树会翻车拿到这份月亮数据预测资源时我第一反应是确认它是不是用 sklearn 的make_moons生成的数据集——果然moon.py里就是生成月亮形二分类数据的脚本。月亮数据是入门决策树和随机森林最经典的合成数据集之一它并非线性可分正好用来观察单棵决策树怎样过拟合、随机森林又是靠什么把准确率拉回来的。整个项目包含决策树分类器和随机森林分类器两份独立实现外加homework5.doc的作业说明流程覆盖数据生成、训练、评估和对比。适合正在写机器学习作业、想弄清决策树调参边界、以及准备把随机森林当基线模型的从业者。这篇笔记我按“数据长什么样 → 决策树怎么建 → 随机森林怎么集成 → 坑在哪 → 怎么验证”的顺序拆开讲。2. 月亮数据到底长什么样用 make_moons 生成二分类样本2.1 为什么选月亮数据做算法对比月亮数据来自 sklearn 的make_moons函数生成的是两个交错的半月牙形点簇。每个点有x1、x2两个特征标签y只有 0 或 1。数据量默认 100 个样本通过noise参数控制噪声大小。这类数据的价值在于它天然不是线性可分的——你没法画一条直线把两个月亮分开必须靠非线性模型或者足够深的树才能拟合出像样的边界。对比之下make_classification生成的数据虽然也是分类问题但不同类别的分布往往是高斯簇状决策树和逻辑回归都能处理体现不出算法差异。而月亮数据交错形状决策树会因为特征空间被不断切分而表现敏感随机森林则能通过多棵树投票把不稳定的切分平滑掉很适合做“单模型 vs 集成模型”的教学演示。再加上样本点只有两个特征可以直接二维可视化训练完画决策边界一眼能看出模型是好是坏。2.2 生成数据的标准写法先看项目里moon.py的核心逻辑常见做法是这样from sklearn.datasets import make_moons from sklearn.model_selection import train_test_split X, y make_moons(n_samples200, noise0.2, random_state42) X_train, X_test, y_train, y_test train_test_split( X, y, test_size0.3, stratifyy, random_state42 ) print(训练集样本数:, X_train.shape[0]) print(测试集样本数:, X_test.shape[0]) print(标签分布:, {0: sum(y 0), 1: sum(y 1)})这里n_samples200是样本总数noise0.2表示在样本坐标上叠加标准差为 0.2 的高斯噪声random_state42固定随机种子保证每次生成的样本分布一致。stratifyy让训练集和测试集中的类别比例与原始数据一致避免随机划分导致某一类全跑到测试集里。月亮数据本身类别均衡不加stratify问题也不大但加上是更稳的习惯。运行后你会得到 140 个训练样本和 60 个测试样本x1和x2的取值范围大致在 -1.5 到 2.5 之间。这个阶段不需要做标准化或归一化因为决策树和随机森林都基于特征阈值切分对特征尺度不敏感跟 SVM 或逻辑回归不一样。2.3 可视化确认数据形态生成数据后第一步应该是画散点图而不是直接丢进模型。写一小段代码看分布import matplotlib.pyplot as plt plt.figure(figsize(6, 5)) plt.scatter(X[:, 0], X[:, 1], cy, cmapbwr, edgecolorsk, s40) plt.xlabel(x1) plt.ylabel(x2) plt.title(Moons Dataset (noise0.2)) plt.show()如果noise0.3以上两个半月牙的尾部会大量重叠视觉上几乎看不出月牙形状。此时不管用什么模型测试集准确率都会明显下降。所以调noise时需要心里有数在本项目里noise0.15到0.2是决策树和随机森林对比最舒服的区间噪声太小体现不出随机森林的优势太大则两个模型都救不回来。3. 决策树分类器从根节点到叶节点的切分逻辑3.1 决策树的划分准则与参数选型决策树分类器DecisionTreeClassifier的核心是按特征阈值递归切分样本空间每次切分都试图让子节点尽可能“纯”。判断纯度有两个常用准则gini和entropy。基尼不纯度计算的是从节点中随机抽取两个样本类别不同的概率信息熵则基于香农熵。实践里这两个准则在月亮数据上的结果差别很小默认criteriongini就够了不必纠结。真正影响模型表现的关键参数是max_depth、min_samples_split和min_samples_leaf。max_depth控制树的深度不限制时决策树会把训练样本划分到每个叶节点只剩一类导致训练集准确率冲到 100%测试集却一塌糊涂。min_samples_split控制内部节点继续划分所需的最小样本数调大它可以限制树继续生长。min_samples_leaf则限制叶节点的最小样本数对平滑决策边界更直接。3.2 训练一棵不设限的决策树decision_tree_classifier.py里的逻辑大致如下我拆开逐步说from sklearn.tree import DecisionTreeClassifier from sklearn.metrics import accuracy_score, classification_report dt_clf DecisionTreeClassifier(random_state42) dt_clf.fit(X_train, y_train) y_pred dt_clf.predict(X_test) print(决策树测试集准确率:, accuracy_score(y_test, y_pred)) print(classification_report(y_test, y_pred))random_state42在这里同样重要。决策树在特征选择时如果遇到多个特征的信息增益相同会随机选一个不固定种子的话每次运行得到的树结构都不同。首次训练我故意不设max_depth目的是看出问题运行结果通常会显示训练集准确率 100%测试集准确率大概在 85% 到 90% 之间。这个差距就是过拟合的直接证据。在noise0.2的月亮数据上树为了把噪声点也正确分类会生长出很多细碎的切分把两个月牙边缘的噪声区域切成小块。3.3 给决策树加限制条件把max_depth4加上再训练测试集准确率不降反升的情况很常见。这就是决策树在月亮数据上的典型特征深度太浅欠拟合深度太深过拟合max_depth4到6往往落在甜区。dt_clf DecisionTreeClassifier( criteriongini, max_depth4, min_samples_split4, min_samples_leaf2, random_state42 ) dt_clf.fit(X_train, y_train) y_pred dt_clf.predict(X_test) print(受限决策树测试集准确率:, accuracy_score(y_test, y_pred))min_samples_split4表示节点样本数少于 4 就不再继续划分min_samples_leaf2确保每个叶节点至少包含两个样本。这两个参数在月亮数据上的作用是压制尾部的过拟合切分。参数值不建议照搬先跑一组再调样本数增加时min_samples_leaf相应调大max_depth也同步放宽。3.4 把决策树画出来看切分行为只看准确率会漏掉很多信息。用plot_tree把树结构画出来能直观看到哪些特征被优先选中、切分阈值是多少from sklearn.tree import plot_tree import matplotlib.pyplot as plt plt.figure(figsize(12, 8)) plot_tree( dt_clf, filledTrue, roundedTrue, feature_names[x1, x2], class_names[0, 1], max_depth4 ) plt.show()每个节点里会显示划分条件如x1 0.231、基尼不纯度、样本数和类别分布。月亮数据上常见模式是根节点先按x1切因为x1在 -1.5 到 2.5 之间的分布差异比x2更明显之后左右子树再根据x2细切。如果看到某个叶节点的samples已经很小但gini还是 0.4 以上说明这个区域两类样本严重混叠继续生长也没用。4. 随机森林分类器多棵决策树投票的稳定性来源4.1 Bagging 怎么解决单棵树的不稳定随机森林的本质是 bagging 加随机特征选择。bagging 的思想是从训练集里做有放回抽样每棵树用一份不同的自助样本训练最后通过多数投票决定预测结果。单棵决策树对数据微小变化非常敏感——训练集换几个样本树结构可能整个变掉决策边界也随之剧烈摆动。随机森林把几十棵这种“敏感”的树组合起来每棵树的错误方向不同投票后错误互相抵消整体预测就稳定了。随机森林在 bagging 的基础上又加了一层随机性每次节点划分时不是从全部特征里挑最优而是从随机选取的max_features个特征里挑。默认max_featuressqrt即每层划分只看特征总数的平方根个候选特征。月亮数据只有 2 个特征sqrt(2)约等于 1.41取整后每个节点只考虑 1 个特征相当于每棵树都退化成在随机特征上切分。这时需要手动把max_features设为2或None全部特征否则随机森林的多样性不如预期。4.2 训练随机森林并对比准确率random_forest_classifier.py的实现逻辑如下from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score rf_clf RandomForestClassifier( n_estimators100, max_depthNone, max_features2, min_samples_leaf1, random_state42, n_jobs-1 ) rf_clf.fit(X_train, y_train) y_pred_rf rf_clf.predict(X_test) print(随机森林测试集准确率:, accuracy_score(y_test, y_pred_rf))n_estimators100表示构建 100 棵决策树月亮数据样本量小几百棵树训练也很快。max_depthNone让每棵树充分生长不限制深度因为随机森林靠投票抑制过拟合单棵树深一点不会像单棵决策树那样致命。max_features2在只有两个特征时让每棵树都能看到全部特征。n_jobs-1表示用满所有 CPU 核心随机森林的每棵树互相独立天然适合并行。对比前面单棵决策树的测试集准确率随机森林通常能高出 3 到 6 个百分点在noise0.2时大约从 88% 提升到 93% 左右。这个提升不等于随机森林一定比决策树好——在特征极少、样本极小的场景里随机森林的优势会被削弱但综合稳定性仍然占优。4.3 检查袋外分数随机森林有个单棵决策树没有的能力袋外样本评估。每棵树训练时大约会有 37% 的样本没被抽到这些样本可以直接用于评估该树全部树的袋外预测汇总起来就得到oob_score相当于免费的验证集。rf_clf RandomForestClassifier( n_estimators100, max_features2, oob_scoreTrue, random_state42 ) rf_clf.fit(X_train, y_train) print(袋外分数:, rf_clf.oob_score_)袋外分数和测试集准确率通常比较接近可以作为调参时的内部指标。不过要注意oob_score是在训练集上算的不能完全替代独立的测试集评估它更多是帮你快速判断一轮参数调整是否有效的信号。调参时可以只看oob_score的变化趋势减少对测试集的反复触碰。4.4 查看特征重要性随机森林可以直接输出特征重要性原理是统计每个特征在所有树的所有节点上带来的不纯度下降总量然后归一化。月亮数据只有两个特征重要性数值的意义更多是确认模型确实同时利用了x1和x2importance rf_clf.feature_importances_ for name, imp in zip([x1, x2], importance): print(f{name}: {imp:.4f})在noise0.2时x1的重要性通常会明显高于x2因为两个月牙在x1方向上的分离度更高。当噪声增大导致两类在x2方向也开始重叠时x2的重要性会下降。这个信息可以在写作业报告时作为“特征选择依据”放进去。5. 决策树和随机森林的常见问题五个我踩过的坑5.1 训练集 100%测试集只有 86%这是不设max_depth的单棵决策树最容易出现的现象也是很多初学者最困惑的点。问题在于决策树把每个训练样本都当作“真理”去拟合噪声点也被完整记住树可以一直生长到每个叶节点只有一个样本为止。解决办法是给max_depth或min_samples_leaf加限制。我的习惯是先固定min_samples_leaf2然后从max_depth2开始每轮加 1 观察测试集准确率变化直到连续两轮没有提升就停。5.2 不固定随机种子导致结果飘忽不定同样的代码跑两次决策树准确率差 3 个百分点随机森林差 1 个百分点这个现象在月亮数据上很常见。原因在前面提过决策树在特征增益相同时随机选择划分特征随机森林的样本抽样和特征选择也都带随机性。不固定random_state的话你根本分不清效果变化是参数调整带来的还是随机波动带来的。做对比实验时决策树和随机森林的random_state都要固定最好统一设为同一个值比如42保证其他条件完全一致。5.3 决策树可视化输出太乱节点挤成一团plot_tree默认按树的完整深度绘制不设max_depth时可能有几十个节点图像挤得完全看不清。两个解决办法一是给plot_tree传max_depth3只画树的上三层二是先训练一棵浅层决策树再画。真正要展示树结构时用filledTrue让节点按类别着色比纯黑白输出直观得多。如果你还用export_graphviz导出了.dot文件但打不开通常是因为没装 graphviz 的 C 库装完并配置好系统环境变量后直接plt.show()是最省事的路子。5.4 max_features 默认值让随机森林退化成“随机切分”月亮数据只有两个特征max_featuressqrt时每个节点只看 1 个随机特征导致每棵树无法选择当前最优的切分特征树的独立性是有了但单棵树的性能太差投票效果反而不理想。这不是随机森林算法的问题是特征维度太小时没调整参数的问题。如果你在月亮数据上发现随机森林比单棵决策树还差先检查max_features是不是设成了sqrt改成2或None再试。None表示每棵树使用全部特征在两特征场景下相当于只保留 bagging 的随机性。5.5 train_test_split 不设 stratify数据划分偏移月亮数据默认类别均衡但如果手动改了样本数或者噪声设置导致类别不平衡随机划分可能让训练集里某一类样本过少。例如训练集中只有 30% 的类别 1测试集中却有 60% 的类别 1模型的评估结果就失真了。stratifyy可以在划分时保持类别比例一致加上它不需要额外成本属于随手就能规避的风险。同样的道理模型训练前先打印sum(y_train)和sum(y_test)确认分布也算是基本流程。6. 交叉验证和网格搜索把模型的稳定性验证落到实处6.1 用交叉验证替代单次划分单次train_test_split的结果受随机划分影响较大测试集可能恰好落在容易或难分类的区域。交叉验证把数据分成 K 份轮流拿其中 1 份做验证其余 K-1 份训练最后取 K 次结果的平均值得到的评估指标更接近模型真实水平。月亮数据样本量小K 折交叉验证是非常合适的验证方式。from sklearn.model_selection import cross_val_score scores_dt cross_val_score( DecisionTreeClassifier(max_depth4, random_state42), X, y, cv5, scoringaccuracy ) print(决策树交叉验证平均准确率:, scores_dt.mean()) scores_rf cross_val_score( RandomForestClassifier(n_estimators100, max_features2, random_state42), X, y, cv5, scoringaccuracy ) print(随机森林交叉验证平均准确率:, scores_rf.mean())cv5表示五折交叉验证每一折的训练集有 160 个样本、验证集 40 个样本。交叉验证能比较稳定地反映随机森林相对决策树的优势但需要在交叉验证里同样保持random_state一致否则每组分数也会有波动。6.2 用 GridSearchCV 找决策树和随机森林的最优参数手工试参数效率低项目里调参时我一般用GridSearchCV跑一组网格。以随机森林为例重点是max_depth和min_samples_leaf的组合from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [50, 100, 200], max_depth: [3, 5, 8, None], min_samples_leaf: [1, 2, 4], max_features: [2] } grid_search GridSearchCV( RandomForestClassifier(random_state42), param_grid, cv5, scoringaccuracy, n_jobs-1 ) grid_search.fit(X, y) print(最优参数:, grid_search.best_params_) print(最优交叉验证平均准确率:, grid_search.best_score_)网格搜索的代价是组合数量上述参数网格有 3×4×3×136 种组合每组跑五折交叉验证共 180 次模型训练。月亮数据上这个量级秒级完成但换到大数据集时就该考虑RandomizedSearchCV了它在参数空间中随机采样指定组合数能显著缩短搜索时间。搜索完成后再把best_params_映射回训练脚本里重跑一次确认测试集表现与交叉验证分数接近——如果差距过大说明数据划分或者模型泛化有问题需要重新检查。从那以后我每次拿到这类分类项目都会强制走一遍完整的验证流程先画数据分布图再固定随机种子跑基线模型最后用交叉验证加网格搜索把模型参数定型。这套流程在月亮数据上帮我快速看清了决策树的过拟合倾向和随机森林的稳定性优势希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
C语言函数深度剖析:从栈帧与指针到回调工程实战 我不是来跟你讲语法手册的。C语言的函数,网上教程一抓一大把,但大部分都停在“怎么用”的层面,很少有人把“为什么这样设计”“底层到底发生了什么”讲透。你去看热搜里那些词,什么“单片机C语言没有堆栈吗为什么”“C语言指针”“… · 2026/9/24 22:21:23
从2019到2025:全球独角兽榜单背后的估值逻辑与产业变迁 世界上极少有哪组数据,能像“全球独角兽榜”一样,把整个创投圈的兴奋、焦虑和风向变化压缩在同一个指标里。独角兽这个词从2013年诞生到现在,已经从一个神话概念变成了产业界的常规军备竞赛。我自己从2019年开始持续跟踪这个榜单一期的更新&a… · 2026/9/24 22:21:23
Smurf攻击原理与实验:ICMP放大机制、GNS3/eNSP复现及PPT制作指南 简介:这份PPT资源聚焦Smurf攻击这一典型的分布式拒绝服务攻击方式,面向网络安全初学者、运维人员及信息安全课程学习者,帮助其系统理解攻击原理、检测手段与防御策略。压缩包内仅含1个pptx文件,体积约220KB,以图文并茂… · 2026/9/24 22:21:23
深度学习新闻分类推荐系统:从TextCNN到个性化推荐 简介:这份基于深度学习的新闻分类推荐系统Python实现源码,是专为课程设计与期末大作业准备的高分项目,下载后无需修改即可运行,适用于需要快速交付完整课题的高校学生。系统涵盖新闻数据预处理、文本分类模型训练、推荐逻辑展示等… · 2026/9/24 23:59:53
汽车电子底层软件开发:AUTOSAR与CAN总线实战解析 1. 这门“汽车电子底层软件开发就业课”到底在教什么?——不是写个LED闪烁就能上岗的很多人看到“汽车电子底层软件开发就业课”这个标题,第一反应是:不就是嵌入式C语言单片机CAN通信?刷几道LeetCode、调通一个STM32 CAN收发例程&… · 2026/9/24 23:59:53
Vim基础操作全攻略:保存退出、模式切换与高频命令实战 1. 项目概述1.1 核心需求解析今天聊聊Vim。写这个题目的原因是:几乎每个后端开发者、运维人员、数据工程师某天都会遇到一个场景——深夜加班,服务器登录界面只有黑底白字,编辑器只有vi/vim,你必须在五分钟内完成一次配置修改并保… · 2026/9/24 23:59:53
Python+CNN车牌识别实战:从数据预处理到模型训练与部署 简介:基于Python与卷积神经网络的车牌识别项目,面向计算机视觉初学者及智能交通开发者,目标是帮助用户掌握从数据预处理、模型构建到实际部署的完整流程。压缩包共25个文件,包含jpg/png图像样本、py训练脚本、md说明文档、dat数据… · 2026/9/24 23:59:53
AI元人文:从工具使用到思维重构的深度探索 最近半年我一直在琢磨一件事:AI元人文到底是什么?说白了,就是“用元视角重新审视人与AI的关系”,也在“探索AI如何反向逼着我们发现自己的思考边界”。标题里的“元探索”,在我看就是一层套一层的追问——当你用AI解决… · 2026/9/24 23:59:53