【零基础,纯干货】|【手把手教你用大模型做专业级数据分析】——基于大语言模型的学生用户画像构建和个性化推荐方法
1. 实验概述
1.1 实验目的
本实验利用数智教育数据集(1,765 名在校生近五年的成绩、考勤、消费记录),借助大语言模型(通义千问 Qwen-Plus)完成两项数据分析任务:
1. 学生用户画像构建:从多维数据中提炼每位学生的学业特征、行为模式,生成结构化的 JSON 画像报告
2. 个性化学习资源推荐:基于学生画像,通过 Chroma 向量语义检索匹配适合的学习资源,并由 LLM 生成包含推荐理由和学习计划的完整报告
1.2 技术路线

1.3 工具与环境
|
组件 |
技术选型 |
|
数据处理 |
pandas, numpy |
|
向量检索 |
Chroma 1.5 (ONNX all-MiniLM-L6-v2) |
|
大语言模型 |
通义千问 **Qwen-Plus** (DashScope API) |
|
可视化 |
matplotlib, seaborn |
|
开发环境 |
Python 3.x |
2. 数据说明与预处理
2.1 数据来源
数据集包含 7 张关系表,覆盖某高中近五年的教学数据:
|
数据表 |
记录数 |
核心字段 |
|
student_info |
1,765 人 |
学生ID、姓名、性别、民族、班级、住校、家庭住址 |
|
chengji |
471,686 条 |
考试ID、学科、原始分、Z-score、T-score、等第 |
|
kaoqin |
23,630 条 |
考勤时间、考勤类型(迟到/旷课/早退/请假…) |
|
consumption |
463,904 条 |
消费时间、金额、学生ID |
|
teacher |
3,088 条 |
学期、班级、学科、教师 |
|
kaoqintype |
15 条 |
考勤类型编码表 |
|
exam_type |
21 条 |
考试类型编码表 |
2.2 数据清洗
成绩异常处理:mes_Score 中 <0 的值(-1=作弊, -2=缺考, -3=免考)替换为 NaN。清洗后有效成绩 422,705 条(剔除 48,981 条,占 10.4%)。
时间解析:消费 DealTime 和考勤 DataDateTime 统一转为 datetime,提取小时字段用于时段分析。
2.3 特征工程
以学生信息表为主表,对成绩、考勤、消费分别聚合后 left-join:
|
维度 |
计算方式 |
特征数 |
|
学业水平 |
`groupby.agg(mean, std, count, max, min)` + `pivot_table` 学科矩阵 |
~20 |
|
考勤行为 |
`groupby.count` + 考勤类型 `unstack` 拆分 |
~8 |
|
消费模式 |
`groupby.agg(sum, mean, count, std, max)` + 活跃天数 → `日均消费` |
6 |
最终得到 1,765 名学生 × 49 维特征的画像宽表。
3. 学生群体画像分析
3.1 学业水平分布
采用固定阈值标签体系(阈值 90/75/60,6 级标签):
|
学业等级 |
人数 |
占比 |
|
学霸(≥90分) |
— |
— |
|
优秀(75-90分) |
1 |
0.1% |
|
中等(60-75分) |
360 |
20.4% |
|
学困(<60分) |
1,210 |
**68.6%** |
|
未知(无成绩) |
194 |
11.0% |
分析:近七成学生属"学困"等级,学业困难面大。194 名学生完全无成绩记录(可能为新生或长期缺考)。优秀层几乎为零(仅 1 人),说明该校学生整体学业水平偏低,教学应重点关注基础巩固而非拔高。
3.2 学科偏向
|
学科偏向 |
人数 |
占比 |
|
均衡发展 |
1,484 |
84.1% |
|
未知(数据不足) |
198 |
11.2% |
|
理科优势 |
60 |
3.4% |
|
文科优势 |
23 |
1.3% |
分析:绝大多数学生文理均衡。有偏科倾向的群体中,理科优势(60 人)多于文科优势(23 人),与该校理科教学资源相对充足有关。
3.3 考勤与消费行为
采用如下标签体系(考勤:0次=全勤标兵, ≤3次=正常, >3次=需要预警;消费:分位数 Q25/Q75):
|
考勤标签 |
人数 |
占比 |
消费标签 |
人数 |
占比 |
|
|
全勤标兵 |
758 |
42.9% |
适中 |
882 |
50.0% |
|
|
需要预警 |
545 |
30.9% |
节俭 |
442 |
25.0% |
|
|
正常 |
462 |
26.2% |
消费较高 |
406 |
23.0% |
分析:分位数法(Q25/Q75)比固定阈值法(<15元=节俭)效果好得多——消费标签均匀分布(50%/25%/23%),而非之前 98% 挤在"节俭型"。考勤方面,30.9% 学生需要预警,说明考勤管理虽有成效但仍存在改进空间。
3.4 消费时段分析
从 463,904 条消费记录中提取按小时分布:
|
时段 |
消费次数 |
占比 |
|
6:00-7:00 早餐 |
73,742 |
15.9% |
|
11:00-13:00 午餐 |
229,453 |
**49.5%** |
|
17:00-18:00 晚餐 |
111,581 |
**24.1%** |
分析:消费呈典型"三餐驱动"模式,午餐占比近半。深夜消费(0:00-5:00)几乎为零,反映住校生作息受学校统一管理,为培养规律学习习惯提供了有利条件。

4. 基于 LLM 的个体画像生成
4.1 方法
将每位学生的 49 维特征转化为结构化自然语言摘要,输入 Qwen-Plus,使用 response_format={'type': 'json_object'} 强制 JSON 输出。
System Prompt 核心要求(8 字段 JSON):
academic_level: 学霸/优秀/中等偏上/中等/中等偏下/学困
subject_profile: 学科优势劣势详细描述
learning_attitude: 考勤+成绩稳定性综合判断
behavior_pattern: 消费+考勤→生活习惯和自律程度
strengths: [优势列表]
weaknesses: [待改进列表]
suggestions: [具体建议]
overall_description: 100-150字综合描述
分析原则:不使用固定阈值,关注维度关联(考勤与成绩的关系),给出具体可操作建议,体现学生个性特点。
4.2 LLM 画像实例
从 1,765 名学生中按学业等级分层抽样 5 人。以下是实际生成结果:
学生 A(学业:优秀,数学突出,英语 86.5,地理偏弱 67.5):
|
字段 |
LLM 生成内容 |
|
学业等级 |
优秀 |
|
学科画像 |
数学突出(90.5分),英语优秀(86.5),物理化学稳定良好(80+)。地理中等偏下(72.5),政治明显薄弱(67.5),生物数据缺失(0分) |
|
学习态度 |
学习投入度较高,成绩波动大(标准差23.4),具备冲击高分的潜力(最高97分) |
|
行为模式 |
考勤记录完全缺失,系统未录入出勤数据,需高度关注实际到校情况 |
|
优势 |
数学逻辑思维强、英语应用能力好 |
|
待改进 |
文科基础薄弱、考勤行为异常需排查 |
学生 B(学业:中等偏下,语文突出 86 分,数理化薄弱 ~53 分):
|
字段 |
LLM 生成内容 |
|
学业等级 |
中等偏下 |
|
学科画像 |
语文学科突出(86分),政史地英语相对较好。数理化三科严重薄弱(均分~53),呈现严重文理失衡 |
|
学习态度 |
成绩波动极大(标准差29.0),考试频次高(146次),但缺乏系统性投入 |
|
行为模式 |
考勤极少(仅5次),日均消费-22.89元(负值=退款异常),消费频次高(212次) |
|
优势 |
文科认知能力突出、语文基础扎实 |
|
待改进 |
理科系统性知识严重不足、学习行为习惯缺失、考勤缺位 |
学生 A("优秀")和 B("中等偏下")的差异不仅体现在分数上。LLM 识别出 A 的问题是"考勤数据缺失+文科薄弱",而 B 的问题是"考勤极少+文理严重失衡+消费行为异常"——画像深度远超一个简单的分数排名。
4.3 画像质量评估
|
维度 |
评分 |
说明 |
|
跨维度分析 |
9/10 |
能够关联考勤、消费、成绩进行综合推理(如"消费异常→行为管理问题→影响学习") |
|
语义丰富度 |
9/10 |
输出包含行为模式推断("考勤极低+高频消费→时间管理失衡") |
|
可读性 |
9/10 |
教师/家长可直接阅读 |
|
个性化程度 |
8/10 |
每名学生得到差异化描述,不千篇一律 |
|
可操作建议 |
8/10 |
给出具体方向,如"从基础概念开始重建理科知识体系" |

4.4 个体画像雷达图
将每位学生的学业水平、出勤情况、消费规律、成绩稳定性、学科均衡度五个维度归一化到 0-1,绘制个体画像雷达图:

雷达图直观展示了"标签相同"学生的差异——同为"中等"等级,有的学生学业水平高但出勤差,有的出勤好但成绩波动大。这种多维可视化比单一标签更能支撑个性化教学决策。
4.5 群体画像词云
将所有 LLM 生成的画像文本(overall_description + subject_profile + learning_attitude + behavior_pattern)合并,生成关键词云:

词云中高频词反映了 LLM 画像的关注焦点——"成绩""学习""学科""基础""薄弱""习惯"——说明 LLM 在生成画像时重点围绕学业表现和学习习惯展开分析,符合教育场景的预期。
5. 个性化学习资源推荐
5.1 推荐流程
学生画像 → 语义查询文本 → Chroma 向量检索(Top-5) → LLM 生成推荐报告(含理由+优先级)
教育资源库:构建了 30 条教育资源,覆盖 6 种类型:
|
类型 |
数量 |
说明 |
|
学习方法 |
6 |
各学科通用学习策略 |
|
补差方案 |
6 |
针对弱势学科的补救资源 |
|
拔高建议 |
5 |
优秀学生的进阶内容 |
|
习惯养成 |
5 |
作息、自律、考试焦虑等 |
|
消费管理 |
3 |
消费行为的引导建议 |
|
同伴学习 |
5 |
结对学习、互助小组 |
5.2 协同过滤推荐基线
在构建 LLM 推荐前,先以协同过滤(CF)作为性能基线,构建学生-学科评分矩阵并实现 User-based CF 和 Item-based CF 两种算法。
评分矩阵:从成绩表中提取 9 门核心学科,通过 groupby + unstack 构建矩阵,仅保留至少 5 科成绩的学生。归一化到 0-1 区间(除以 100)。最终矩阵:3,852 学生 × 9 学科,稀疏度 6.9%。
User-based CF:计算学生间余弦相似度,找到 K=5 个最相似邻居,加权预测目标学生在未评分学科的得分,只推荐有提升空间(gap > 0)的学科:
|
学生 |
CF 推荐 |
提升空间 |
|
10842 |
英语(0.70→0.72), 政治(0.73→0.74) |
+0.02 |
|
10843 |
生物(0.81→0.83), 地理(0.89→0.90) |
+0.02 |
Item-based CF:计算学科间相似度矩阵(如"物理"与"数学"相似度 0.85),基于学生已修学科的成绩预测未修学科:
|
学生 |
Item-CF 推荐 |
预测分 |
|
10842 |
物理(0.71), 生物(0.77), 化学(0.85) |
基于学科相似度加权 |
CF 可视化:

从左到右:(1) 学生相似度热力图——颜色越深表示两名学生的成绩模式越接近;(2) 学科相似度热力图——物理与数学高度相关(0.85),政治与地理相关(0.72),验证了"理科联动""文科联动"的学科聚类规律;(3) 评分矩阵稀疏度——红色为有成绩,浅色为缺失,可见该数据集整体较密集。
CF 的局限:冷启动(新学生无成绩→矩阵中不存在→相似度无法计算)、仅用成绩忽略考勤/消费/画像信息、无法生成推荐理由、相似度矩阵 O(n²) 不可线性扩展。
5.3 语义检索验证
|
学生查询 |
语义检索 Top-1 |
匹配质量 |
|
"物理实验题总是丢分" |
习惯养成类(作息相关) |
中等* |
|
"数学好觉得太简单" |
数学学习方法 |
精准 |
|
"住校作息不规律" |
消费管理类 |
中等* |
*注:当查询过于简短时,向量检索倾向于匹配高频词(如"作息""丢分"对应到习惯养成类)。后续可通过扩充资源库和优化查询文本改进。
5.4 LLM 个性化推荐实例
向量检索返回候选后,LLM 根据学生画像从中挑选并生成带理由和优先级的推荐:
|
学生 |
画像特征 |
Top-1 推荐 |
LLM 推荐理由摘要 |
|
A |
数学90.5, 语文72.5, 考勤缺失 |
数学拔高(r13) |
"数学分高达90.5远超班级水平,具备拔高潜力,适合拓展高阶思维" |
|
B |
语文86, 数理化53, 考勤仅5次 |
习惯养成(r22) |
"考勤仅5次,标准差29.0,反映学习习惯严重缺失,需系统性习惯支持" |
|
新生 |
无成绩, 住校, 高一 |
习惯养成、学习方法、拔高 |
基于"住校+高一"匹配适应性资源 |
Qwen-Plus 生成的推荐理由能够联系学生画像的具体数值("数学分高达90.5""标准差29.0""考勤仅5次"),这是相较于传统推荐"只给名字不给理由"的本质进步。
5.5 冷启动验证
无成绩新生查询:
"高一新生,男生,住校,暂无成绩记录,需要适应高中学习生活"
推荐结果:习惯养成类(住校生作息)→ 补差方案类(基础学科)→ 拔高建议类(数学/物理)
LLM+向量方法在零成绩数据的冷启动场景下仍可给出有价值的推荐——基于年级、住校状态等基本信息。
5.6 推荐系统技术演进

1. 基础层(评分矩阵):仅用学生-学科分数,冷启动不可用
2. 语义层(向量检索):理解模糊需求,支持多维度查询
3. 智能层(LLM 增强):画像深度融合 + 生成推荐理由 + 学习计划
6. 结论与建议
6.1 数据分析主要发现
学生群体层面:
1. 学业分化显著:68.6% 学生属"学困"等级(均分<60),仅 1 人达"优秀"。教学资源应向基础巩固倾斜。
2. 生活节奏高度统一:消费集中在三餐时段(午餐 49.5%,晚餐 24.1%),深夜活动几乎为零。住校管理为规律学习提供了结构性优势。
3. 考勤管理有盲区:30.9% 学生需要预警(异常>3次),且 194 名学生完全无成绩记录,需排查长期缺勤或数据录入问题。
4. 消费分位数法优于固定阈值:Q25/Q75 分位数使消费标签均匀分布(50%/25%/23%),而固定阈值(<15元)导致 98% 学生挤在同一标签。
LLM 应用层面:
5. LLM 画像能推断行为模式:从"考勤仅5次+消费负值+标准差29"推断出"时间管理失衡+学习习惯缺失",而非仅罗列分数。
6. LLM 推荐报告具备可交付性:每条推荐都包含资源 ID、推荐理由(联系画像数值)、优先级(高/中/低)、学习计划——可直接发给学生或家长。
7. 冷启动不再是障碍:无成绩新生可基于住校、年级信息获得适应性推荐。
8. Qwen-Plus 性能满足需求:画像生成和推荐报告均稳定返回合法 JSON,157 tokens/次调用,成本可控。
6.2 实践建议
|
建议 |
面向 |
说明 |
|
重点支持学困层 |
教学管理 |
68.6% 学生属学困,建议按薄弱学科分组,从基础概念开始重建 |
|
排查无成绩学生 |
教务 |
194 人无成绩 + 545 人考勤预警,需查明是长期缺勤还是数据录入问题 |
|
LLM 画像用于家校沟通 |
班主任 |
自然语言报告比分数单更直观,家长可直接理解学生具体问题 |
|
新生入学用 LLM 推荐 |
教务 |
无成绩时仍可基于住校/年级匹配适应性资源 |
|
扩充教育资源库 |
技术团队 |
当前 30 条偏通用,建议加入各学科各章节的本地化内容 |
6.3 改进方向
1. 扩充资源库:从 30 条扩充到各学科各章节,加入真题和本地化材料
2. 引入多模态数据:作业文本、课堂表现记录等,让 LLM 画像更立体
3. 优化语义检索:短查询匹配精度有提升空间,可考虑混合检索(关键词+语义)
4. 批量 API 调用:大规模应用时通过异步调用和缓存降低成本
5. 教育理论融合:将 VARK 学习风格、布鲁姆认知层次融入 Prompt 设计
附录:核心代码
A. 特征聚合
# 学科矩阵 — pivot_table 构建
subject_scores = df_chengji.pivot_table(
index='mes_StudentID', columns='mes_sub_name',
values='mes_Score', aggfunc='mean'
).reset_index()
subject_scores.rename(columns={'mes_StudentID': 'bf_StudentID'}, inplace=True)
# 给学科列加前缀 subj_
for c in subject_scores.columns:
if c != 'bf_StudentID':
subject_scores.rename(columns={c: f'subj_{c}'}, inplace=True)
# 考勤类型拆分 (unstack)
kaoqin_pivot = df_kaoqin.groupby(['bf_studentID', 'controler_name']) \
.size().unstack(fill_value=0).reset_index()
# 日均消费
consumption_days = df_consumption.groupby('bf_StudentID')['DealTime'] \
.apply(lambda x: x.dt.date.nunique())
student_consumption['daily_avg'] = total_spending / consumption_days
# 合并 — 1,765 × 49
df_profile = df_student.merge(student_score).merge(subject_scores) \
.merge(student_kaoqin).merge(kaoqin_pivot).merge(student_consumption)
B. 画像标签
# 学业: 90/75/60
def assign_academic_label_v1(avg):
if pd.isna(avg): return '未知'
if avg >= 90: return '学霸'
elif avg >= 75: return '优秀'
elif avg >= 60: return '中等'
else: return '学困'
# 考勤: 0/3
def assign_attendance_label(total):
if total == 0: return '全勤标兵'
elif total <= 3: return '正常'
else: return '需要预警'
# 消费: Q25/Q75 分位数
q25, q75 = df_profile['daily_avg'].quantile([0.25, 0.75])
def assign_consumption_label(daily):
if daily > q75: return '消费较高'
elif daily > q25: return '适中'
else: return '节俭'
C. LLM 画像生成
SYSTEM_PROMPT = """你是资深教育数据分析师。请输出严格JSON格式的画像报告:
{
"academic_level": "学霸/优秀/中等偏上/中等/中等偏下/学困",
"subject_profile": "学科优劣势详细描述",
"learning_attitude": "考勤+成绩稳定性综合判断",
"behavior_pattern": "消费+考勤→生活习惯和自律程度",
"strengths": ["优势1","优势2"],
"weaknesses": ["待改进1","待改进2"],
"suggestions": ["建议1","建议2"],
"overall_description": "100-150字综合描述"
}
原则: 不固定阈值,关注维度关联,具体可操作,体现个性特点"""
response = client.chat.completions.create(
model='qwen-plus',
messages=[{'role':'system','content':SYSTEM_PROMPT},
{'role':'user','content':f"请分析:\n{student_summary}"}],
temperature=0.3,
response_format={'type': 'json_object'} # 强制JSON
)
return json.loads(response.choices[0].message.content)
D. 协同过滤
# 评分矩阵 (groupby + unstack)
student_subject_scores = df_chengji[
df_chengji['mes_sub_name'].isin(cf_subjects) & df_chengji['mes_Score'].notna()
].groupby(['mes_StudentID', 'mes_sub_name'])['mes_Score'].mean().unstack()
valid_mask = student_subject_scores.notna().sum(axis=1) >= 5 # 至少5科
rating_matrix = (student_subject_scores[valid_mask] / 100.0).clip(0, 1)
# User-CF (推荐有提升空间的学科)
def user_based_cf_recommend(target_id, k=5, n=3):
target_scores = rating_matrix.loc[target_id]
top_k = similarity_df.loc[target_id].drop(target_id).nlargest(k)
for subject in rating_matrix.columns:
pred = weighted_avg(top_k, subject)
gap = pred - target_scores[subject]
if gap > 0: # 只推荐有提升空间的
recommendations[subject] = {'predicted': pred, 'current': ..., 'gap': gap}
return sorted(recommendations, key=lambda x: -x[1]['gap'])[:n]
E. 向量检索 + LLM 推荐
# Chroma 向量库
collection = chroma_client.create_collection(name='edu_resources')
collection.add(
documents=[r['text'] for r in education_resources], # 30条
metadatas=[{'title':f"[{r['type']}]{r['subject']}", ...}],
ids=[r['id'] for r in education_resources]
)
# 语义检索
candidates = collection.query(query_texts=[query], n_results=5)
# LLM 推荐报告生成
RECOMMEND_PROMPT = """输出JSON:
{"recommended_resources": [{"resource_id":"...","reason":"...","priority":"高/中/低"}],
"learning_plan":"50-80字学习计划",
"peer_suggestion":"同伴学习建议",
"overall_recommendation":"100-150字总体推荐"}"""
response = client.chat.completions.create(
model='qwen-plus',
messages=[{'role':'system','content':RECOMMEND_PROMPT},
{'role':'user','content':f"画像:\n{profile}\n候选:\n{candidates}"}],
temperature=0.3,
response_format={'type': 'json_object'}
)
更多推荐



所有评论(0)