ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Python机器学习实战:学生成绩预测分类项目全解析

Python机器学习实战:学生成绩预测分类项目全解析 简介这是一个基于Python的机器学习入门项目面向想了解分类预测流程与成绩影响因素分析的学习者。资源通过学生个人信息、家庭背景、学校信息等CSV数据演示了数据清洗、特征选择、特征缩放等预处理步骤并利用决策树、支持向量机、随机森林等模型进行训练与调优辅以混淆矩阵和图表展示结果可帮助读者快速建立从数据探索到模型评估的完整认知。压缩包共包含3个文件以Python脚本、CSV数据集和Markdown说明为主体积仅8KB轻量易用适合初学者对照练习。目前已有966人学习下载资源附带的代码注释清晰能助力理解Pandas、NumPy、Scikit-Learn的实际用法与交叉验证、网格搜索等调优技巧。1. 用 Python 跑通学生成绩预测这不是 Kaggle 竞赛是能落地的分类项目做机器学习最怕什么不是模型不收敛而是数据集和代码都齐了却不知道每一步在干什么。这个学生成绩预测项目就是为打破这种黑匣子状态准备的——它用一份包含国籍、年级、举手次数、出勤率、学习时数等字段的 CSV 数据配合 Pandas 做清洗、NumPy 做数值计算、Scikit-Learn 跑分类器把哪些因素影响了学生成绩这个问题拆成了一个完整的分类任务。适合正在学机器学习、想找一份带数据和完整代码的实战案例来复现的从业者也适合准备课程设计答辩的学生。你能从里面拿走一套可复用的预处理流程、三套分类器对比模板以及一份能直接解释给业务方听的结果报告。2. 数据集和预处理先把 AI-Data.csv 拆开看明白2.1 字段结构哪些是特征哪一列是标签打开 AI-Data.csv第一眼要分清特征和标签。这个数据集里的字段分三类学生个人行为举手次数、出勤率、学习时数、家庭背景父母学历、家庭经济情况、学校信息年级、学校类型。我处理这类数据的第一步永远是df.info()和df.describe()比直接跑模型有用得多。import pandas as pd df pd.read_csv(AI-Data.csv) print(df.shape) # (行数, 列数)先确认数据量级 print(df.info()) # 看每列类型、非空数量一眼找出缺失值 print(df.describe()) # 看数值列的均值、方差、min/max判断是否有异常值逻辑说明info()能直接暴露两件事——列类型是否合理比如把年级读成了 float和有没有空值。describe()则帮我确认数值特征的量纲差异比如学习时数可能是 0-10而出勤率是 0-100这种差异直接决定后面要不要做特征缩放。参数说明shape返回的不是函数而是元组属性别写成df.shape()。如果describe()里某列的标准差是 0说明这列所有值都一样属于无效特征建议直接 drop。这个项目最终预测的标签是成绩等级通常映射为 High/Middle/Low 三个类别原始数据里可能是字符串也可能是数字编码。先用value_counts()看一眼分布如果三类数量差距过大比如 High 占了 80%后面做训练集切分时就必须加stratify参数不能让某类样本在测试集里消失。2.2 标签编码和特征缩放顺序问题和量纲问题的两种解法拿到手的数据几乎不可能是干净的。类别列比如国籍、父母职业是字符串SVM 和随机森林都吃不下数值列量纲差异大SVM 这类基于距离的模型会直接被大数值特征带偏。这个项目用了标准的预处理管线我来拆开说。from sklearn.preprocessing import LabelEncoder, StandardScaler from sklearn.model_selection import train_test_split # 1. 标签编码把字符串类别转成 0/1/2 le LabelEncoder() df[Class] le.fit_transform(df[Class]) # High-2, Middle-1, Low-0 # 2. 分离特征和标签 X df.drop(Class, axis1) y df[Class] # 3. 数值列标准化SVM 必须做树模型可做可不做 scaler StandardScaler() X_scaled scaler.fit_transform(X) # 4. 分层切分保证三个类别在训练/测试集中比例一致 X_train, X_test, y_train, y_test train_test_split( X_scaled, y, test_size0.2, random_state42, stratifyy )逻辑说明LabelEncoder适合对标签列做编码不建议用它处理所有特征列——因为它会给类别强加大小顺序中国变 0、美国变 1这个 0 和 1 的大小毫无意义。特征列里的类别变量应该用OneHotEncoder或pd.get_dummies()。这里先用 LabelEncoder 是因为目标是标签列类别间没有顺序关系也不影响分类器计算损失。参数说明test_size0.2是常见切分比例数据量小几百行时也可以改成 0.3。random_state42固定随机种子保证每次跑出来的切分结果一致这是复现的基本前提。stratifyy是分层抽样类别不均衡时必加。标准化这步有个常见争议随机森林、决策树这类树模型不依赖距离计算缩放不影响结果但 SVM 和 KNN 这类基于距离度量的模型不缩放的话量纲大的特征会主导距离计算。这个项目同时跑了 SVM 和随机森林稳妥做法是统一走StandardScaler代价只是多几行代码。2.3 数据可视化先画图再建模避免盲跑预处理完之后别急着训练。先用可视化确认特征和标签的相关性这一步能帮你砍掉无效特征也能让你在答辩或汇报时有图可讲。这个项目里准备了一些图表和混淆矩阵来展示结果。import matplotlib.pyplot as plt import seaborn as sns # 1. 特征相关性热力图 plt.figure(figsize(12, 8)) sns.heatmap(df.corr(numeric_onlyTrue), annotTrue, cmapcoolwarm) plt.title(Feature Correlation Heatmap) plt.tight_layout() plt.savefig(correlation_heatmap.png, dpi150) plt.show()逻辑说明df.corr()默认计算 Pearson 相关系数取值 -1 到 1。我要找的是与Class列相关性绝对值较高的特征比如学习时数如果和成绩等级有 0.6 的正相关那它就是强预测因子如果某两个特征之间相关系数超过 0.9说明存在多重共线性建议只保留其中一个。可视化这块除了热力图还可以画各类别在举手次数上的分布箱线图或者画成绩等级的饼图。目的只有一个在跑模型前对数据分布有个直觉判断而不是把数据丢进fit()就完事。保存图片时用dpi150既能保证清晰度又不至于文件过大。3. 三个分类器轮番上阵决策树、支持向量机、随机森林的实测对比3.1 为什么同时跑三个模型而不是只挑一个这个项目的核心卖点不是单模型精度而是对比。决策树的优势是可解释性强跑完能直接画出树结构告诉业务方举手次数少于 20 且出勤率低于 60% 的学生大概率成绩低SVM 擅长处理高维小样本数据但参数敏感核函数选错了精度直接崩随机森林是 Bagging 集成的代表抗过拟合能力强但解释性差。既然数据集只有几百到上千行三个模型都能在几秒内跑完没有理由不做对比。真正的坑在于三个模型的评价指标不能只看 accuracy尤其当类别不均衡时accuracy 会骗人。下面这段代码把三个模型统一封装用同一套训练集和测试集评估保证对比公平。from sklearn.svm import SVC from sklearn.tree import DecisionTreeClassifier from sklearn.ensemble import RandomForestClassifier from sklearn.metrics import accuracy_score, classification_report, confusion_matrix models { SVM: SVC(kernelrbf, C1.0, gammascale, random_state42), Decision Tree: DecisionTreeClassifier(max_depth5, random_state42), Random Forest: RandomForestClassifier(n_estimators100, max_depth8, random_state42) } for name, model in models.items(): model.fit(X_train, y_train) y_pred model.predict(X_test) acc accuracy_score(y_test, y_pred) print(f{name} Accuracy: {acc:.4f}) print(classification_report(y_test, y_pred, target_names[Low, Middle, High]))逻辑说明把三个模型放在字典里循环训练避免重复写 9 行 fit/predict 代码。classification_report会同时输出 precision、recall、f1-score 和各自类别的样本量比只看 accuracy 靠谱得多。如果某个类别样本少它的 f1-score 会明显偏低这才是模型真正的问题所在。参数说明SVM 里kernelrbf是默认也是通常最先尝试的核函数C1.0控制误分类惩罚C 越大越容易过拟合gammascale让 sklearn 根据特征数量自动计算 gamma 初始值。决策树的max_depth5是刻意限制深度防止树把训练集背下来。随机森林的n_estimators100是树的数量再往上加收益递减max_depth8同样是剪枝手段。3.2 混淆矩阵看清模型到底错在哪一类准确率只能告诉你对了多少混淆矩阵能告诉你错在哪。三分类的混淆矩阵是 3×3 矩阵对角线是正确预测非对角线是错误类型。比如把 High 错判成 Middle和把 Middle 错判成 High对业务来说完全是两码事——一个是低估学生一个是高估学生。import numpy as np import matplotlib.pyplot as plt from sklearn.metrics import confusion_matrix, ConfusionMatrixDisplay cm confusion_matrix(y_test, y_pred) disp ConfusionMatrixDisplay(confusion_matrixcm, display_labels[Low, Middle, High]) disp.plot(cmapBlues) plt.title(SVM Confusion Matrix) plt.savefig(svm_confusion_matrix.png, dpi150) plt.show()逻辑说明注意上面这段代码用的是上一节循环结束后最后一个模型随机森林的y_pred如果你只想画 SVM 的混淆矩阵需要把代码挪到循环内部。我习惯把每个模型的混淆矩阵都保存成独立 PNG 文件后面做对比汇报时直接拼图。手动调用confusion_matrix(y_test, y_pred)而不是model.score()是因为我要拿到矩阵数据本身不只是分数。ConfusionMatrixDisplay是 sklearn 提供的可视化封装省去了手动plt.imshow的麻烦。如果你用的 sklearn 版本较老没有这个类可以用sns.heatmap(cm, annotTrue)代替。3.3 结果解读哪个模型赢了以及为什么跑完三个模型常见的结果是随机森林 accuracy 略高于 SVM决策树垫底。原因不复杂随机森林通过随机采样特征和样本训练多棵树再投票方差比单棵决策树小得多而决策树不剪枝时容易过拟合剪枝狠了又欠拟合对参数太敏感。但这不代表项目到此结束。翻车现场往往出现在这里有人看到随机森林精度最高就直接上随机森林完全忽略了可解释性需求。如果这个项目的使用场景是教育机构要解释哪些因素影响学生成绩决策树反而更合适——它能输出一棵可视化的树直接告诉老师举手次数少于 20 次的学生中有 80% 成绩处于中低水平。SVM 的精度可能介于两者之间但它的决策边界在高维空间里几乎无法向非技术背景的人解释。所以我的建议是最终选型不取决于单次 accuracy而是取决于你的交付对象。如果交付报告随机森林 特征重要性排序最实用如果交付可解释规则决策树 剪枝是唯一选择如果数据集小且维度高SVM 值得优先尝试。4. 实战避坑这个项目最容易翻车的四个地方4.1 标签编码翻车把无序类别当成有序数值现象直接用LabelEncoder处理所有字符串列比如国籍、父母职业模型跑完 accuracy 不低但换一份数据就崩。原因LabelEncoder给类别强行编号比如中国→0、美国→1、日本→2这个序号的大小关系对模型来说是虚假信息。树模型还能靠切分点硬扛SVM 的距离计算直接乱套。解决特征列里的类别变量全部改用pd.get_dummies()做独热编码。标签列才用LabelEncoder。一句话记牢编码特征用 OneHot编码标签用 Label。4.2 random_state 不固定复现不了结果现象同一份数据、同一个模型两次运行 accuracy 差 3-5 个百分点。原因train_test_split、决策树、随机森林内部都有随机性。不固定随机种子每次切分的训练集和测试集都不同模型结果自然有波动。解决所有涉及随机过程的步骤都加random_state42包括train_test_split、DecisionTreeClassifier、RandomForestClassifier、SVC里的random_state。42 只是个习惯数字重点是要固定。4.3 类别不均衡时只用 accuracy 评估现象数据集里 Low 类有 400 条High 类只有 50 条。模型把所有样本都预测为 Lowaccuracy 高达 80%看起来表现优秀。原因accuracy 是全体样本的预测正确率样本量大的类别主导了指标。解决切换评估视角。一是在classification_report里重点看 macro avg 和 weighted avg二是加stratifyy保证切分时各类别比例一致三是必要时候用class_weightbalanced给少数类更高权重。这三招能让你看到模型的真实水平。4.4 特征缩放只做了一半现象SVM 的 accuracy 比随机森林低一大截而且怎么调参都上不去。原因SVM 基于距离计算如果特征量纲差异大比如学习时数0-10出勤率0-100大数值特征会主导距离度量。项目里用StandardScaler是标准做法但有人只对数值列归一化、忘了编码后的 0/1 列或者先切分再缩放导致数据泄露。解决先切分训练集和测试集再在训练集上fit缩放器然后用同一个缩放器transform测试集。顺序不能反否则测试集信息混入缩放参数等于作弊。用colab或jupyter调试时最稳妥的方式是把预处理封装成一个函数每次跑通全流程时把缩放器同时保存下来。5. 网格搜索和特征重要性把模型的最后一个价值榨出来跑完三个模型对比、选定了随机森林之后项目看起来已经完整了但还有两步能让整个项目产生额外价值用网格搜索找到当前模型的最优参数组合以及用特征重要性排序回答业务方最关心的到底什么因素影响了学生成绩。from sklearn.model_selection import GridSearchCV param_grid { n_estimators: [50, 100, 200], max_depth: [4, 6, 8, 10], min_samples_split: [2, 5, 10] } rf RandomForestClassifier(random_state42) grid_search GridSearchCV( rf, param_grid, cv5, # 5 折交叉验证 scoringf1_macro, # 多分类用 macro f1 比 accuracy 更稳 n_jobs-1 ) grid_search.fit(X_train, y_train) print(Best Params:, grid_search.best_params_) print(Best CV Score:, grid_search.best_score_) best_rf grid_search.best_estimator_ # 特征重要性排序 importances best_rf.feature_importances_ feature_names df.drop(Class, axis1).columns for name, imp in sorted(zip(feature_names, importances), keylambda x: x[1], reverseTrue): print(f{name}: {imp:.4f})逻辑说明GridSearchCV做的事情是穷举参数组合每组参数都跑 5 折交叉验证最终选择平均分最高的一组。scoringf1_macro是这里关键的选择——多分类且类别可能有偏斜时macro f1 对所有类别一视同仁。参数说明cv5表示把训练集切成 5 份轮流拿 4 份训练、1 份验证。n_jobs-1用满所有 CPU 核心数据量小的时候无所谓数据量大了这个参数能省一半时间。param_grid里三个参数共 3×4×336 组组合每组跑 5 折一共 180 次训练好在随机森林单次训练很快。再说特征重要性。feature_importances_是随机森林自带的属性值越大说明该特征在树分裂中贡献的纯度提升越多。这一步的价值在于把模型从黑匣子变成可以解释的结论——比如跑完你会发现举手次数和学习时数排在前两位而国籍几乎不贡献信息。这个结论对班主任、对教务系统做干预方案都是有实际参考价值的。最后收个尾从那以后我每次做完模型对比都会强制走一遍网格搜索和特征排序这两步再写结论报告。不只是因为这个项目需要而是因为这两步能把我跑了个模型准确率 90%提升到我找到了最优参数组合并且我能告诉你哪个因素最关键。希望这个项目的完整流程能帮你把机器学习的每个环节从玄学变成可解释的工程实践。本文还有配套的精品资源点击获取
返回列表