资讯动态

机器学习预测学生成绩:基于Python的模型对比实战

发布时间:2026/10/12 20:42:58 来源:尧图企业网站定制
简介这是一份用机器学习预测学生成绩表现的Python实现面向数据分析初学者及教学场景聚焦“哪些因素影响学生成绩”这一分类问题并比较多种算法的效果。压缩包共3个文件内含Python脚本、CSV数据集与说明文档整体仅8KB轻量易上手。目前已有九百六十六人学习下载适合课堂演示或自学。项目基于Pandas、NumPy、Scikit-Learn考虑了国籍、年级、举手人数、出勤人数、学习时数等特征覆盖数据清洗、特征选择与特征缩放采用决策树、支持向量机、随机森林等模型并通过图表和混淆矩阵直观展示分类结果还演示了交叉验证与网格搜索调优。读者可从中掌握从数据预处理到模型评估的完整流程也能替换自有数据快速验证是入门机器学习分类任务的实用参考资料。1. 机器学习预测学生成绩这份 Python 项目到底能拿来干什么如果你正愁课程设计、毕业设计或者期末大作业缺一个“能跑通、有图表、有模型对比”的机器学习项目这份基于 Python 实现的学生成绩预测资源就是典型的拿来即用型底稿。它不是一个空壳 demo而是把“数据读取 → 预处理 → 分类器训练 → 混淆矩阵可视化”整条链路都串好了数据集是 CSV 格式里面包含了学生国籍、年级、举手次数、出勤次数、学习时长这类与学业表现相关的特征字段。项目里已经写好了 Project.py 主脚本和 README 说明文档核心逻辑是用 Pandas 和 NumPy 做数据清洗与特征缩放再用 Scikit-Learn 里的决策树、支持向量机、随机森林等分类器分别建模最后通过图表和混淆矩阵对比哪个模型对“哪些因素影响成绩”预测得最准。适合的人群很明确正在学机器学习但不想从零造轮子的初学者以及需要短时间交付一个完整项目的从业者。2. 项目结构与数据形态先用 Pandas 把 CSV 里的学生特征摸清楚2.1 解压后的文件清单与各自职责拿到StudentPerformancePrediction-ML-main.zip解压后核心就三个东西AI-Data.csv、Project.py、README.md。我第一次打开这个项目时最关心的不是代码多花哨而是数据长什么样、脚本能不能直接跑。README.md里写的是项目简介和运行方式真正干活的是Project.py而所有模型训练都建立在AI-Data.csv这个数据集上。unzip StudentPerformancePrediction-ML-main.zip cd StudentPerformancePrediction-ML-main ls -la这段命令解压并进入项目目录ls -la能让你看到文件大小和权限。常见做法是先用head -5 AI-Data.csv瞄一眼数据长什么样再打开 Project.py 看它读取了哪些列。别急着跑先确认你的 Python 环境里有没有 pandas、numpy、scikit-learn、matplotlib、seaborn缺哪个就补哪个。2.2 用 Pandas 探查数据集的字段与缺失值数据集的字段描述里提到“来自不同国籍、不同年级的学生”还有举手人数、出勤人数、学习时数等所谓 SOE 决定因素。对于这种表格型数据我一般会先写几行 Pandas 代码做快速探查搞清楚每列的数据类型、缺失值比例和类别分布而不是直接丢给分类器。import pandas as pd df pd.read_csv(AI-Data.csv) print(df.shape) print(df.dtypes) print(df.isnull().sum()) print(df.describe(includeall))这段代码做了四件事shape看行数列数dtypes看每列类型isnull().sum()看缺失值数量describe(includeall)看数值列的统计量以及类别列的频次。参数说明includeall是关键默认describe()只统计数值列加上它才能看到文本类特征的非空计数和唯一值个数。跑完之后你会对“哪些特征适合做数值输入、哪些需要编码”有一个直观判断。实际项目中如果某列缺失值超过三成我一般会考虑直接丢弃或做填充而不是硬着头皮编码。2.3 特征缩放的必要性与 StandardScaler 的用法决策树对特征尺度不敏感但支持向量机和很多基于距离的模型非常敏感。这个项目的技术栈里明确提到了特征缩放所以在预处理阶段把学习时数这种大数值特征和举手次数这种小数值特征统一到同一量纲是保证 SVM 不翻车的关键一步。from sklearn.preprocessing import StandardScaler features [raised_hands, visited_resources, announcements_viewed, Discussion] X df[features] scaler StandardScaler() X_scaled scaler.fit_transform(X) print(X_scaled.mean(axis0)) print(X_scaled.std(axis0))StandardScaler把每个特征减去均值再除以标准差转换后每列均值接近 0、标准差接近 1。fit_transform是在训练数据上拟合并转换打印出来的均值向量和标准差向量可以验证缩放是否生效。这里有个习惯先 split 再 fit也就是用训练集fit_transform测试集只transform防止数据泄露。我见过不少初学者把整个数据集拿去fit_transform后再切分测试集的信息提前进了缩放器严格来说会让评估结果偏乐观。3. 分类器选型与建模决策树、SVM、随机森林在成绩预测上的对比逻辑3.1 为什么用分类器而不是回归器来预测成绩项目标题写的是“预测学生成绩表现”但摘要里反复出现“分类器”和“混淆矩阵”说明这是一个分类问题而不是回归问题。也就是说我们要预测的不是“考了 85 分”这种具体数值而是“成绩属于高/中/低哪个档位”。“影响学生成绩的因素”这个表述也印证了建模目标用特征去解释和预测成绩等级。常见做法是把成绩列划分成几个区间比如低于某个阈值是低、高于某个阈值是高或者直接用原有数据集里的类别标签。分类比起回归的优势在于结果更直观混淆矩阵一眼就能看出模型在哪个档位容易混淆。对于课程设计而言分类器对比还能自然地引出精确率、召回率、F1 这些指标让报告内容更充实。3.2 决策树可解释性最强但容易过拟合决策树在这个场景里是很好的基线模型因为它的树结构可以直接画出图来解释“举手次数对成绩的影响路径”。训练代码很短但要注意剪枝参数。from sklearn.tree import DecisionTreeClassifier from sklearn.model_selection import train_test_split from sklearn.metrics import classification_report X_train, X_test, y_train, y_test train_test_split( X_scaled, y, test_size0.2, random_state42, stratifyy ) clf_tree DecisionTreeClassifier( max_depth5, min_samples_split10, min_samples_leaf5, random_state42 ) clf_tree.fit(X_train, y_train) y_pred clf_tree.predict(X_test) print(classification_report(y_test, y_pred))train_test_split里的test_size0.2表示留出 20% 作为测试集stratifyy保证训练测试两边的成绩等级比例一致这在类别不平衡时特别重要。max_depth5限制树深min_samples_split10要求内部节点至少 10 个样本才继续分裂min_samples_leaf5保证叶子节点至少 5 个样本。这三组参数就是控制决策树不过拟合的常用旋钮。如果不加限制决策树会把训练集背下来测试集表现惨不忍睹。3.3 支持向量机小数据集上的分类利器项目里提到的“向量机”就是支持向量机SVM它在样本量不大、特征维度适中的表格数据上往往表现不错。SVM 的核心是找一个间隔最大的超平面来分开不同类别但如果特征量纲不一致距离计算会被大数值特征主导所以前面做的标准化在这里就派上了用场。from sklearn.svm import SVC clf_svm SVC( kernelrbf, C1.0, gammascale, random_state42 ) clf_svm.fit(X_train, y_train) y_pred_svm clf_svm.predict(X_test) print(classification_report(y_test, y_pred_svm))kernelrbf是高斯核适用于特征与标签呈非线性关系的场景C1.0是误分类惩罚系数C 越大越注重正确分类训练集但过大容易过拟合gammascale让模型根据特征数量自动计算 gamma这个默认值在多数表格数据上都比较稳。实际调参时我会用网格搜索对 C 和 gamma 做交叉验证而不是手动一个个试。3.4 随机森林集成决策树来稳定预测结果随机森林是决策树的集成版本通过随机采样样本和随机选择特征来训练多棵树最后投票决定预测结果。它的优势是比单棵决策树稳定得多对异常值也不太敏感缺点是解释性比单棵树弱。from sklearn.ensemble import RandomForestClassifier clf_rf RandomForestClassifier( n_estimators100, max_depth8, min_samples_leaf3, random_state42, n_jobs-1 ) clf_rf.fit(X_train, y_train) y_pred_rf clf_rf.predict(X_test) print(classification_report(y_test, y_pred_rf))n_estimators100表示森林里有 100 棵树树越多越稳定但训练时间也越长n_jobs-1让所有 CPU 核心一起干活数据集不大时几乎感觉不到耗时。max_depth8比单棵树的 5 层更深一些因为随机森林本身有随机性适当加深可以提升表达能力。跑完这三个模型后对比它们的精确率、召回率和 F1你就能看出哪种模型更适配这份学生数据。4. 交叉验证与网格搜索别让随机划分的运气决定模型好坏4.1 K 折交叉验证的写法与结果解读只用一次train_test_split得到的评估指标受随机划分影响很大不同random_state可能让准确率波动好几个点。交叉验证的做法是把训练集切成 K 份每次拿 K-1 份训练、剩下 1 份验证轮转 K 次取平均这样评估结果更可信。from sklearn.model_selection import cross_val_score scores cross_val_score(clf_rf, X_scaled, y, cv5, scoringf1_macro) print(scores) print(fF1 mean: {scores.mean():.4f}, std: {scores.std():.4f})cv5表示五折交叉验证scoringf1_macro是对每个类别算 F1 后取算术平均适合多分类且各类别样本数差不多的场景。输出是一组 5 个分数看均值和标准差均值代表模型整体水平标准差越小说明模型在不同数据划分上表现越稳定。我一般会用scores.std()是否小于 0.02 来判断模型是否稳定如果标准差很大说明数据划分对结果影响太强需要检查是不是特征里有离群点或者类别分布有问题。4.2 网格搜索自动寻找最优参数组合手动调参只能靠经验和猜测网格搜索则是把所有候选参数组合都跑一遍用交叉验证挑出最优组合。对于 SVM 的 C 和 gamma以及随机森林的树深和叶子样本数网格搜索能省不少时间。from sklearn.model_selection import GridSearchCV param_grid { C: [0.1, 1, 10], gamma: [scale, 0.01, 0.1], kernel: [rbf] } grid GridSearchCV( SVC(random_state42), param_grid, cv5, scoringf1_macro, n_jobs-1 ) grid.fit(X_train, y_train) print(grid.best_params_) print(grid.best_score_)GridSearchCV会把param_grid里的 C 有 3 个值、gamma 有 3 个值组合成 9 种参数组合每种组合做 5 折交叉验证一共跑 45 次训练。best_params_给出最优参数best_score_是对应的平均 F1。网格搜索的代价是计算量随参数数量指数增长所以参数候选值不要给太多我一般先粗后细第一轮用跨度大的值定位区域第二轮在最好值附近缩小范围再来一次。4.3 交叉验证与网格搜索常见误用最容易翻车的地方是把网格搜索直接用在完整数据上然后再拿去和之前的结果比较。正确的流程是把数据先切出独立的测试集网格搜索只在训练集内部做交叉验证选好参数后再在测试集上评估一次。如果一开始就把测试集混进网格搜索就相当于考试前偷偷看了答案。另一个常见问题是网格搜索的评分指标和最终评估指标不一致。比如网格搜索用准确率accuracy但类别不平衡时准确率会虚高最后报告里却写精确率和召回率导致“调参调了个寂寞”。我的习惯是全程统一用f1_macro除非项目明确要求看准确率。5. 数据可视化与混淆矩阵把模型结果变得能直接放进报告里5.1 特征分布与相关性的可视化代码项目摘要里提到“创建了一些视觉辅助工具如图表和混淆矩阵以显示结果”。对于学生成绩预测这种场景最常用的图包括成绩等级的柱状分布图、特征之间的相关性热力图、不同特征在各成绩等级下的箱线图。这些图能帮助你在建模前发现哪些特征有区分度。import matplotlib.pyplot as plt import seaborn as sns sns.set_style(whitegrid) plt.figure(figsize(10, 6)) sns.countplot(datadf, xclass, order[Low, Middle, High]) plt.title(Student Performance Class Distribution) plt.show()countplot按class列统计每个成绩等级的出现次数order参数强制按 Low、Middle、High 排序避免图表按字母顺序排列导致阅读混乱。如果你用的 seaborn 版本较新countplot没有x参数会报错直接传datadf, xclass即可。这张图能快速暴露类别是否平衡——如果 High 比 Low 多一倍后面建模就要考虑类别权重。5.2 混淆矩阵的可视化与三个重点指标混淆矩阵是分类模型评估的核心图它显示每个真实类别被预测成了什么类别。对角线上的数字是正确预测的数量非对角线则是混淆情况。from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay cm confusion_matrix(y_test, y_pred_rf) disp ConfusionMatrixDisplay(confusion_matrixcm, display_labels[Low, Middle, High]) disp.plot(cmapBlues) plt.title(Random Forest Confusion Matrix) plt.show()ConfusionMatrixDisplay是 scikit-learn 提供的封装cmapBlues让颜色深浅反映数值大小。看混淆矩阵时我只看三个地方对角线是否明显偏大、哪两个类别最容易互相混淆、错误预测是偏向相邻等级还是跨级跳跃。如果 Middle 经常被误判成 Low 或 High说明特征在区分中等级别时不够有力可能需要构造更细的特征比如把学习时数和举手次数做成交叉特征。5.3 特征重要性排序找出影响成绩的关键因素项目目标之一是“预测哪些因素会影响学生的分数”随机森林自带feature_importances_可以直接输出每个特征的重要性分数。这一步对于报告里的结论部分几乎是必写的。import numpy as np importances clf_rf.feature_importances_ feature_names features indices np.argsort(importances)[::-1] for i in indices: print(f{feature_names[i]}: {importances[i]:.4f}) plt.figure(figsize(8, 5)) plt.barh([feature_names[i] for i in indices], importances[indices]) plt.xlabel(Importance) plt.title(Feature Importance from Random Forest) plt.show()argsort()[::-1]先得到从小到大的索引再反转变成从大到小这样能按重要性降序打印。barh画水平条形图从小到大排序显示更容易阅读。特征重要性给出的是相对贡献不是因果关系的证明。比如raised_hands重要性高只能说明在这个数据集中它和成绩等级关联强不代表“多举手就能提高成绩”。5.4 避坑图表中文乱码与混淆矩阵颜色过浅用 matplotlib 画图时默认字体不支持中文标题里的“学生成绩等级分布”会显示成方框。解决办法是显式指定支持中文的字体常见做法是设置plt.rcParams[font.sans-serif] [SimHei]同时用plt.rcParams[axes.unicode_minus] False解决负号显示问题。如果你系统里没有 SimHei可以直接把图里的中文改成英文避免为字体折腾半天。混淆矩阵颜色过浅是另一个常见问题cmapBlues在数值都很小时颜色几乎看不清。我一般会在disp.plot()后加disp.ax_.set_xlabel(Predicted)并检查颜色映射是否因数据范围而失效必要时改用cmapYlOrRd这类对比更强的色带。可视化是给评委和读者看的清晰是第一优先级。6. 进阶验证与技巧从复现到改造成自己的课程设计6.1 用特征组合和模型对比找到最优方案当你把 Project.py 完整跑通之后真正让项目“变成自己的”是在现有基础上做增量改进。我通常会先记录三组基线模型的结果然后尝试两件事一是构造新特征比如把raised_hands和visited_resources相加成“课堂参与度”二是尝试更多模型比如逻辑回归和 K 近邻甚至集成它们做投票。from sklearn.ensemble import VotingClassifier voting VotingClassifier( estimators[ (tree, clf_tree), (svm, clf_svm), (rf, clf_rf) ], votingsoft ) voting.fit(X_train, y_train) y_pred_voting voting.predict(X_test) print(classification_report(y_test, y_pred_voting))VotingClassifier把三个训练好的模型组合起来votingsoft表示按类别概率加权平均投票通常比hard直接多数投票效果更平滑。注意这里传入的是已经拟合过的分类器实例所以VotingClassifier内部的fit会重新训练它们但不会覆盖原来的clf_tree等对象因为VotingClassifier在fit时默认克隆估计器。如果要严格对比最好把原始模型重新fit一次避免任何意外状态。6.2 如何验证你的模型不是“瞎预测”很多初学者跑完模型看到准确率 0.9 就觉得大功告成但忽略了一个关键动作和基线对比。最弱的基线是“多数类分类器”也就是把所有样本都预测成数量最多的那个类别。如果数据集里 High 占 60%那么一个无脑预测 High 的模型准确率就有 0.6。你的随机森林如果只有 0.65那其实没学到什么东西。验证方法是写一个简单的DummyClassifierfrom sklearn.dummy import DummyClassifier dummy DummyClassifier(strategymost_frequent) dummy.fit(X_train, y_train) print(classification_report(y_test, dummy.predict(X_test)))strategymost_frequent表示永远预测训练集中出现次数最多的类别。把这个结果和真实模型的 F1 对比如果差距很小说明你的特征或模型需要重新审视。另一个验证方法是绘制 ROC 曲线但多分类的 ROC 要按 one-vs-rest 处理比较复杂。对于课程设计而言报告里多写一句“与多数类基线相比提升 X%”比堆一堆图表更有说服力。6.3 我的调参习惯与收尾建议从那以后我每次跑这类机器学习项目都强制自己走一遍这套流程先DummyClassifier打底再做特征标准化然后训练决策树、SVM、随机森林三个基线模型记录 F1接着用交叉验证确认稳定性最后用网格搜索微调表现最好的模型。整个过程下来项目报告里能写的东西就非常丰富了数据探索、预处理、模型对比、调参过程、混淆矩阵分析、特征重要性排序。这份资源里的 Project.py 已经把主线都铺好了你要做的就是替换数据集、调整特征列表、加入自己的理解然后重新跑通。希望帮到你。本文还有配套的精品资源点击获取

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

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

免费获取报价 →
↑