☰
基于心理健康数据集的大学生心理预警AI模型实战
2026/10/3 4:21:46 网站建设 项目流程

简介:这份资源面向希望用真实数据练手机器学习的大学生、数据分析初学者与心理健康研究爱好者,围绕大学生心理健康数据集展开完整的分析与预测实战。包内共9个文件,以7个Python源代码为主,另含1个CSV数据文件与1个说明文档,压缩包约25KB,代码手工整理、无语法错误,可直接运行。内容覆盖探索性数据分析、可视化、回归与分类建模等环节,涉及pandas、matplotlib、seaborn、statsmodels、scipy、sklearn与xgboost等模块,包含线性回归、SVR、K近邻、多层感知机、随机森林回归与分类等模型,并配有MAE、MSE、R²、准确率、混淆矩阵及学习曲线等评估手段,还用到标准化、归一化、标签编码与训练集划分等预处理流程。已有221人学习下载,适合作为课程作业、毕设选题或技能练手的参考案例,帮助读者快速理解从数据清洗、特征处理到建模评估的完整链路。

1. 从一份 59.63 KB 的心理健康数据集说起:大学生心理预警到底能不能用 AI 做

大学生心理健康数据集分析预测这个方向,这两年被反复提起,但真正动手的人不多。原因很直接:公开可用的心理健康数据集本来就少,能拿到手的往往只有几十 KB 到几 MB,字段还大多是量表题项,不像图像、文本那样直观。我手上这份标题里提到的资源,就是典型的小体量样本——59.63 KB 的完整数据集,配 7 个源代码文件,覆盖从读取、清洗、特征处理到建模预测的完整链路。它解决的不是"做一个心理医生 AI"这种大命题,而是一个更务实的问题:给定一批学生的量表得分和基础信息,能不能用机器学习把高风险人群筛出来,给辅导员做初筛参考。适合谁?适合想入门表格类分类任务、又不想拿泰坦尼克号练手到吐的在校生和初级算法工程师;也适合高校信息化岗位的技术人员,想看看心理预警系统底层到底长什么样。这一篇就顺着这份数据集,把分析预测的完整路径拆开讲清楚。

2. 心理健康数据集长什么样:字段、标签与 7 个源代码的分工

2.1 先搞清楚这份数据集的结构再动手

拿到一份心理健康相关的表格数据,第一件事不是急着read_csv,而是先判断它属于哪一类。常见的心理健康数据集分三种:量表型(PHQ-9、GAD-7、SCL-90 等标准化问卷得分)、行为型(校园卡消费、图书馆进出、门禁记录)、混合型(量表 + 基础人口学信息)。这份 59.63 KB 的数据集大概率属于第一类或第三类,因为体量太小,不可能装下行为日志。

我一般会先用下面这段代码把数据的"骨架"摸清楚,而不是直接扔进模型:

import pandas as pd # 读取数据集,注意编码,中文量表数据常见 gbk / utf-8 混用 df = pd.read_csv("mental_health.csv", encoding="utf-8") # 1. 看形状:多少样本、多少字段 print("shape:", df.shape) # 2. 看字段类型和缺失情况 print(df.info()) print("缺失值统计:\n", df.isnull().sum()) # 3. 看标签分布,判断是否类别不平衡 print("标签分布:\n", df.iloc[:, -1].value_counts()) # 4. 看数值型字段的描述统计,快速发现异常值 print(df.describe().T)

这段代码的逻辑是层层递进的:shape告诉你样本量够不够撑起训练集和测试集;info()和isnull()告诉你哪些字段是数值、哪些是字符串、缺失多不多;value_counts()看标签是否严重偏斜——心理健康数据里"高风险"样本通常只占 5% 到 15%,这是后面必须处理的核心问题;describe()则帮你发现比如年龄写成 999、量表得分超出理论范围这类脏数据。

参数上要注意两点:encoding一定要试,中文数据用gbk读进来乱码是血泪经验;df.iloc[:, -1]默认最后一列是标签,但实际项目里标签列不一定在最后,最好用列名显式指定,避免翻车。

2.2 7 个源代码文件通常怎么分工

标题里提到 7 个源代码,这类教学向的小项目,文件划分一般遵循"一个文件一件事"的原则。根据我做过的同类项目,常见的分工是这样的:

文件名(典型命名)职责关键点
data_loader.py读取数据、编码处理处理中文编码、列名映射
preprocess.py缺失值、异常值、标准化量表得分不做归一化也能跑,但树模型之外建议做
feature_engine.py特征构造与筛选总分、因子分、交互项
train.py模型训练与交叉验证分层抽样、类别权重
evaluate.py指标计算与混淆矩阵重点看召回率,不是准确率
predict.py单条/批量预测输出风险概率而非硬标签
config.py路径、超参数集中管理避免硬编码

这个分工不是死的,但核心思想是:数据处理和建模分离,配置和逻辑分离。如果你拿到的 7 个文件里有utils.py之类的,那多半是把画图、保存模型这些杂活单独拎出来了。理解分工之后,你改代码就知道该动哪个文件,而不是在一个几百行的脚本里大海捞针。

提示:小数据集项目最容易犯的错是把所有逻辑塞进一个文件,7 个文件的价值恰恰在于让你养成模块化习惯,别嫌麻烦。

3. 从原始量表到模型输入:特征工程与类别不平衡处理

3.1 量表题项怎么变成模型能吃的特征

心理健康数据的原始字段往往是一道道量表题,比如"过去两周,你是否感到情绪低落"这种,取值 0 到 3。直接把每道题当特征扔给模型不是不行,但效果通常一般,因为单题噪声大、维度还可能比样本量还高。我一般会做三层特征构造:

第一层是总分特征,把同一量表的题项加总,比如 PHQ-9 的 9 道题加总得到抑郁总分,这是临床上最常用的指标,信息密度高。第二层是因子分,如果量表有明确的维度划分(比如焦虑、躯体化、社交回避),按维度分别加总。第三层是衍生特征,比如总分是否超过临床切分点、关键题项是否单独异常。

# 假设 phq_items 是 9 道题的列名列表 phq_items = [f"phq{i}" for i in range(1, 10)] # 第一层:总分 df["phq_total"] = df[phq_items].sum(axis=1) # 第二层:因子分(示例:情绪因子取前 4 题,躯体因子取后 5 题) df["phq_mood"] = df[phq_items[:4]].sum(axis=1) df["phq_somatic"] = df[phq_items[4:]].sum(axis=1) # 第三层:是否超过临床切分点(PHQ-9 常用 10 分作为中度阈值) df["phq_above_cutoff"] = (df["phq_total"] >= 10).astype(int) # 关键题项单独保留(比如自杀意念相关题,临床上权重极高) df["critical_item"] = df["phq9"]

逻辑说明:总分和因子分把分散的题项信息聚合,降低维度同时保留临床意义;切分点特征把连续变量二值化,帮助线性模型捕捉非线性边界;关键题项单独保留是因为某些题在临床上就是"一票否决"级别的信号,不能被平均掉。参数上,切分点不要拍脑袋,PHQ-9 用 5/10/15/20 对应轻中重,GAD-7 用 5/10/15,这些是量表自带的标准,用错了模型输出的风险等级就没有解释力。

3.2 类别不平衡:心理健康预测绕不过去的坎

前面说过,高风险样本通常只占少数。如果直接训练,模型会学会"全部预测为低风险",准确率能到 90% 以上,但召回率是 0——这种模型在心理预警场景里毫无价值,因为漏掉一个真正需要帮助的学生,代价远大于误报。

处理不平衡有三条常见路径,我一般组合使用:

from sklearn.model_selection import train_test_split from imblearn.over_sampling import SMOTE X = df.drop(columns=["label"]) y = df["label"] # 关键:先划分再过采样,绝不能在全量数据上 SMOTE,否则测试集信息泄漏 X_train, X_test, y_train, y_test = train_test_split( X, y, test_size=0.2, stratify=y, random_state=42 ) # 只在训练集上做 SMOTE smote = SMOTE(random_state=42, k_neighbors=5) X_train_res, y_train_res = smote.fit_resample(X_train, y_train) print("过采样前:", y_train.value_counts().to_dict()) print("过采样后:", pd.Series(y_train_res).value_counts().to_dict())

逻辑说明:stratify=y保证划分后训练集和测试集的类别比例一致,这是小数据集必须做的;SMOTE 通过插值生成少数类样本,k_neighbors控制插值参考的邻居数,样本极少时(比如少数类不到 20 条)要调小到 3 甚至 1,否则会生成离谱的合成样本。另一条路径是给模型设class_weight="balanced",让损失函数对少数类更敏感,这个不需要生成新样本,更稳妥,我通常两个都试,看验证集召回率谁高。

注意:SMOTE 之后不要用准确率评估,一定要看召回率、F1 和 AUC。心理健康场景里,召回率优先级最高。

4. 模型选型与训练:为什么我在这类数据上首选树模型

4.1 逻辑回归、随机森林、XGBoost 怎么选

心理健康量表数据有几个特点:样本量小(几百到几千)、特征以数值和类别为主、存在非线性交互(比如"总分高 + 睡眠差"比单独任一指标风险高得多)、可解释性要求高(辅导员需要知道为什么判定为高风险)。基于这些,我的选型顺序是:

逻辑回归作为基线,因为它可解释性最强,系数直接告诉你哪个因素影响大,而且在小样本上不容易过拟合。随机森林作为主力,能自动捕捉交互和非线性,对缺失和异常值也鲁棒。XGBoost 或 LightGBM 作为冲刺,但样本量低于 500 时要非常小心,很容易过拟合,必须配合强正则。

from sklearn.linear_model import LogisticRegression from sklearn.ensemble import RandomForestClassifier from sklearn.model_selection import cross_val_score, StratifiedKFold cv = StratifiedKFold(n_splits=5, shuffle=True, random_state=42) models = { "LR": LogisticRegression(max_iter=1000, class_weight="balanced"), "RF": RandomForestClassifier( n_estimators=300, max_depth=6, min_samples_leaf=5, class_weight="balanced", random_state=42 ), } for name, model in models.items(): scores = cross_val_score( model, X_train_res, y_train_res, cv=cv, scoring="recall" ) print(f"{name} 召回率: {scores.mean():.3f} ± {scores.std():.3f}")

逻辑说明:用StratifiedKFold而不是普通 KFold,保证每折里都有少数类;scoring="recall"直接优化我们最关心的指标;随机森林的max_depth=6和min_samples_leaf=5是防过拟合的关键,小数据集上树不能太深,叶子不能太细。参数上,n_estimators300 通常够用,再往上收益递减;class_weight="balanced"和 SMOTE 二选一或叠加都行,但叠加时要注意别把少数类过度放大。

4.2 训练完必须看的三个东西

模型跑完不能只看一个数字。我固定会看三样:混淆矩阵、特征重要性、阈值-召回曲线。

混淆矩阵告诉你漏报和误报各多少,心理预警里漏报(假阴性)是重点关注的。特征重要性帮你验证模型是不是学到了合理的东西——如果最重要的特征是"学号"或者某个明显无关的字段,那说明数据泄漏了。阈值-召回曲线则是因为默认 0.5 的判定阈值未必合适,心理预警通常要把阈值调低,宁可多报也要少漏。

from sklearn.metrics import confusion_matrix, classification_report import numpy as np # 用验证集调阈值,再在测试集上评估 y_prob = model.predict_proba(X_test)[:, 1] threshold = 0.35 # 低于默认 0.5,提高召回 y_pred = (y_prob >= threshold).astype(int) print(confusion_matrix(y_test, y_pred)) print(classification_report(y_test, y_pred, digits=3)) # 特征重要性(树模型) importances = pd.Series( model.feature_importances_, index=X_train.columns ).sort_values(ascending=False) print(importances.head(10))

逻辑说明:predict_proba拿到概率而不是硬标签,这样才能自由调阈值;阈值从 0.5 降到 0.35 是常见操作,具体降多少要看验证集上召回和误报的权衡;classification_report一次性给出精确率、召回率、F1,比单看准确率全面得多。特征重要性排序后,如果前几名是总分、关键题项、睡眠相关字段,说明模型逻辑合理;如果出现 ID 类字段,立刻回去查数据泄漏。

5. 避坑指南:心理健康预测里最容易翻车的 5 个地方

5.1 数据泄漏:准确率 99% 往往是噩梦的开始

现象:模型在测试集上准确率 0.99,召回率也高得离谱,兴奋地拿去汇报,结果一上线全错。

原因:最常见的是在划分训练测试集之前就做了标准化或 SMOTE,导致测试集的信息"渗"进了训练过程;其次是特征里混入了标签的衍生字段,比如"是否被干预"这种事后信息。

解决:严格遵循"先划分、再处理"的顺序,所有 fit 类操作(标准化、SMOTE、特征选择)只在训练集上做,然后 transform 测试集。用Pipeline把流程串起来能从根本上避免这个问题。

5.2 把相关当因果:总分高不等于抑郁

现象:模型发现"图书馆待得久"和"高风险"负相关,就得出"多去图书馆能防抑郁"的结论。

原因:量表数据和行为的关联是统计相关,不是因果。小数据集上这种伪相关尤其多。

解决:模型输出只做风险筛查参考,不做因果解释。汇报时明确说"这些特征与风险相关",不说"这些特征导致风险"。涉及干预建议,必须由专业人员判断。

5.3 样本量太小还硬上深度学习

现象:几百条数据上跑神经网络,训练集 loss 降到 0.01,验证集一塌糊涂。

原因:参数量远超样本量,模型把训练集背下来了。

解决:样本量低于 1000 时,老老实实用逻辑回归和随机森林。真要用复杂模型,必须配合强正则、早停和交叉验证,并且和基线对比,没有明显提升就别用。

5.4 忽略缺失值的含义

现象:直接把缺失值填 0 或均值,模型效果忽好忽坏。

原因:心理健康量表里的缺失往往不是随机的——学生可能故意跳过敏感题(比如自杀意念题),这种缺失本身就是信号。

解决:对关键题项的缺失单独构造"是否缺失"的指示特征,而不是简单填充。填充策略上,量表总分可以用均值,但关键题项建议用中位数或单独处理。

5.5 用准确率汇报,被问召回率时哑口无言

现象:汇报时只说"准确率 92%",被问到"那漏掉了多少高风险学生"时答不上来。

原因:不平衡数据里准确率是虚高的,多数类占比多少,全预测多数类就能拿到多少准确率。

解决:汇报固定带上召回率、精确率、F1 和 AUC,并且明确说明当前阈值下漏报和误报各多少。心理预警场景,先讲召回率。

6. 让这份数据集真正有用的两个进阶技巧

第一个技巧是把预测概率做成风险分层,而不是二分类。二分类只有"高风险/低风险"两档,实际工作中辅导员需要的是分级:低关注、中关注、高关注、紧急干预。做法是把predict_proba的输出按分位数切成几段,比如概率前 5% 为紧急、5% 到 15% 为高关注、15% 到 30% 为中关注。这样输出的信息量更大,也更容易和现有的心理预警流程对接。

# 基于预测概率做风险分层 probs = model.predict_proba(X_test)[:, 1] risk_level = pd.cut( probs, bins=[0, 0.15, 0.35, 0.6, 1.0], labels=["低关注", "中关注", "高关注", "紧急干预"] ) print(risk_level.value_counts())

分层的边界不要照搬,要根据你所在学校的实际人力和历史数据调。切分点定得太松,高关注人群太多,辅导员处理不过来;定得太紧,又会漏掉边缘案例。我一般会拿历史干预记录反推,看当年真正被干预的学生落在哪个概率区间,以此校准边界。

第二个技巧是做简单的模型可解释性输出。辅导员不是算法工程师,你给他一个概率值他没法用。用 SHAP 或者逻辑回归系数,把每个高风险学生的"主要风险因素"列出来,比如"总分 18(重度)+ 睡眠题项 3 分 + 关键题项阳性",这样他拿到名单就知道该重点问什么。

import shap # 树模型用 TreeExplainer explainer = shap.TreeExplainer(model) shap_values = explainer.shap_values(X_test) # 取第一个高风险样本,看哪些特征把它推向高风险 sample_idx = int(np.argmax(probs)) shap.force_plot( explainer.expected_value[1], shap_values[1][sample_idx], X_test.iloc[sample_idx], matplotlib=True )

SHAP 在小数据集上计算很快,不用担心性能。输出的图能直观看到每个特征是把预测推向高风险还是低风险,以及推了多少。把这个图和风险分层结合,你交付的就不是一个冷冰冰的模型,而是一份辅导员能直接用的初筛报告。

最后说个我自己的习惯:这类项目我从来不在测试集上反复调参。测试集只用一次,调参全在验证集上做。小数据集经不起反复"偷看"测试集,看多了模型就会在测试集上虚高,上线就现原形。这份 59.63 KB 的数据集不大,但把上面这套流程走一遍,你对表格类分类任务的理解会比刷十个泰坦尼克号项目都扎实。希望帮到你。

本文还有配套的精品资源,点击获取

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询