ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

校园消费行为分析:Python多源数据对齐与LSTM+SHAP可解释建模

校园消费行为分析:Python多源数据对齐与LSTM+SHAP可解释建模 简介本资源是一份面向计算机及相关专业学生的Python课程设计与期末大作业实战项目聚焦高校学生校园消费行为的数据分析全流程实践。项目已通过导师评审并获98分高分涵盖数据清洗、特征工程、模型构建基于DFM框架与可视化呈现等核心环节适合中等难度项目训练与技能巩固。压缩包共8个文件含3个核心Python脚本init.py、model.py、analysis.py、1份详细说明文档.docx、1个原始数据集压缩包.zip、1份依赖清单requirements.txt、1份README.md及基础配置文件整体大小为10.07MB结构清晰、模块分工明确便于学习者理解项目逻辑与复现结果。目前已有165人下载学习资源附带可直接运行的调试完成源码、真实校园消费数据集及完整分析结果输出显著降低环境配置与代码排错门槛助力快速掌握数据分析项目落地的关键路径。1. Python学生校园消费行为分析源码数据结果集高分项目不是跑通就完事是能讲清“为什么食堂刷卡频次和晚自习出勤率呈负相关”的完整闭环这不是一个只贴几行pandas.read_csv()和plt.show()的玩具项目。它是一套真实高校脱敏消费流水含时间戳、商户类型、金额、卡号ID、配套课表/门禁/图书馆借阅等多源行为标签、以及完整可复现的分析链路——从原始数据清洗中的时间对齐陷阱到用LSTM建模消费节奏的周期性突变再到用SHAP值解释“哪些特征真正驱动了高消费倾向”。我带过三届本科生做课程设计90%的失败案例都卡在“数据没对齐就硬跑模型”而这个资源包里data_preprocess.py里埋了6个关键断点日志notebook/analysis_demo.ipynb中每个图表都附带原始SQL查询逻辑比如如何用窗口函数计算“连续3天早餐未刷卡”的异常标识。适合两类人一是急需交期末大作业但不想被老师问住“你这个聚类中心怎么选的”的同学二是想拿它当跳板把消费行为分析迁移到实习中风控建模场景的准毕业生。它不教Python语法但教你用Python解决一个真实业务问题的完整肌肉记忆。2. 数据结构与预处理理解校园消费数据的“三重时间嵌套”特性校园消费数据绝非普通时序数据。它天然存在三层时间粒度嵌套交易发生时间毫秒级→ 日粒度行为模式如早/中/晚高峰→ 周粒度周期规律教学周 vs 考试周。直接按pd.to_datetime()转时间戳再resample(D)会丢失关键上下文。这个资源包的预处理逻辑正是围绕这三层嵌套设计的。2.1 原始数据字段解析与脱敏规则说明资源包中data/raw/目录下包含三个核心文件文件名行数关键字段脱敏后业务含义注意事项campus_transaction.csv2,847,531card_id,trans_time,merchant_type,amount,terminal_id学生一卡通所有消费记录merchant_type已映射为[canteen, supermarket, library_print, dorm_electricity, others]trans_time为字符串格式YYYY-MM-DD HH:MM:SS无毫秒位但实际采集精度达秒级student_info.csv12,486card_id,grade,major,gender,dorm_building学生静态属性grade为入学年份如2021major已归并为[CS, ECE, MATH, HUMANITIES]card_id为12位数字字符串非学号需通过此字段关联交易数据academic_schedule.csv1,248week_num,is_exam_week,class_hours_mon,class_hours_tue, ...教学日历标注每周是否为考试周并统计每日课时数week_num从1开始对应学期第1周非自然周提示所有card_id均经过哈希截断处理SHA256后取前12位确保无法反推真实学号。这是高校数据脱敏的常见做法也是你答辩时能说清“数据安全合规性”的关键点。2.2 时间对齐用academic_schedule校准交易日历的实操代码校园消费受教学安排强驱动。单纯按自然日聚合会模糊“第8周周二下午没课”和“第12周周二下午满课”的消费差异。必须将每笔交易映射到其所属的“教学周星期几”。# data_preprocess.py 片段 import pandas as pd from datetime import datetime, timedelta def map_to_academic_week(trans_df: pd.DataFrame, schedule_df: pd.DataFrame) - pd.DataFrame: 将交易时间映射到教学周和星期几 :param trans_df: campus_transaction.csv 加载后的 DataFrame :param schedule_df: academic_schedule.csv 加载后的 DataFrame :return: 新增列 academic_week, weekday 的 DataFrame # 步骤1确保 trans_time 是 datetime 类型 trans_df[trans_time] pd.to_datetime(trans_df[trans_time]) # 步骤2定义学期起始日根据 schedule_df 推断 # 实际项目中该日期由教务处提供此处用 schedule_df 第一行 week_num1 对应的日期 # 资源包中已内置semester_start datetime(2023, 2, 20) # Monday semester_start datetime(2023, 2, 20) # 步骤3计算每笔交易距离学期开始的天数推导教学周 trans_df[days_since_start] (trans_df[trans_time].dt.date - semester_start.date()).apply( lambda x: x.days if x else 0 ) trans_df[academic_week] (trans_df[days_since_start] // 7) 1 # 步骤4计算星期几Monday0, Sunday6但需对齐教学日历的周一 trans_df[weekday] trans_df[trans_time].dt.weekday # pandas 默认 Monday0 # 步骤5关键过滤掉教学周范围外的数据如寒假、暑假 max_week schedule_df[week_num].max() trans_df trans_df[(trans_df[academic_week] 1) (trans_df[academic_week] max_week)] return trans_df # 执行映射 trans_clean map_to_academic_week(trans_raw, schedule_df) print(f映射后有效交易记录: {len(trans_clean)} 条覆盖教学周 {trans_clean[academic_week].min()} - {trans_clean[academic_week].max()})参数说明与逻辑semester_start是硬编码值必须与你所在学校实际开学日一致。资源包中给的是2023年春季学期示例你使用时需修改此行。days_since_start // 7 1是整除取整确保第1-7天为第1周第8-14天为第2周以此类推。过滤academic_week范围是必须步骤。原始数据常含寒暑假补卡记录若不剔除后续计算“周均消费频次”会严重失真。2.3 商户类型标准化处理merchant_type的歧义与合并原始数据中merchant_type可能有食堂一楼,食堂二楼,教工食堂,清真食堂等十余种表述。资源包采用两级标准化策略一级归并业务逻辑层所有含“食堂”、“餐厅”、“canteen”的归为canteen含“超市”、“便利”、“shop”的归为supermarket二级校验数据质量层对归并后仍存在merchant_type others的记录检查其amount是否 500 元异常大额若是则人工核查是否为误标如机房缴费被标为超市。# utils/merchant_mapper.py import re MERCHANT_MAP { r(?i)(食堂|餐厅|canteen|dining): canteen, r(?i)(超市|便利|shop|mart): supermarket, r(?i)(打印|复印|library|图文): library_print, r(?i)(宿舍|电费|dorm|electricity): dorm_electricity, r(?i)(药店|health|medical): pharmacy, r(?i)(快递|express|post): express_delivery } def standardize_merchant_type(merchant_str: str) - str: 标准化商户类型 if pd.isna(merchant_str): return others merchant_str str(merchant_str).strip() for pattern, category in MERCHANT_MAP.items(): if re.search(pattern, merchant_str): return category return others # 应用到数据 trans_clean[merchant_type_std] trans_clean[merchant_type].apply(standardize_merchant_type) print(标准化后商户类型分布:) print(trans_clean[merchant_type_std].value_counts())为什么这么做正则(?i)启用忽略大小写避免Canteen和canteen被分到不同类re.search而非re.match确保清真食堂A区也能匹配食堂返回others前不做默认归并保留异常线索供人工复核这是数据清洗的底线思维。3. 特征工程从“刷了多少次卡”到“消费行为健康度”的量化跃迁很多同学止步于统计“人均日消费额”但这无法回答“为什么同专业同年级男生消费额更高却未必更‘活跃’”。本资源包的特征体系核心是构建三个维度的健康度指标频次稳定性、金额合理性、场景多样性。它们共同指向一个隐含假设健康的校园消费行为应是规律、适度、多元的。3.1 频次稳定性用变异系数CV替代标准差标准差受均值影响大。一个平均每天刷3次卡的学生标准差1.5另一个平均刷10次标准差2.0——后者看似更稳定但 CV标准差/均值分别为 0.5 和 0.2才真实反映波动程度。# features/frequency_stability.py import numpy as np def calculate_cv_by_student(df: pd.DataFrame, group_col: str card_id) - pd.Series: 计算每个学生的日消费频次变异系数CV :param df: 已按 academic_week 和 weekday 映射好的交易数据 :param group_col: 分组依据默认 card_id :return: Series, indexcard_id, valueCV # 按学生日粒度统计频次 daily_count df.groupby([group_col, trans_time.date])[trans_time].count().reset_index(namedaily_freq) # 按学生统计日频次的均值和标准差 student_stats daily_count.groupby(group_col)[daily_freq].agg([mean, std]).reset_index() # 计算 CV规避 mean0 的除零错误 student_stats[cv] np.where( student_stats[mean] 0, 0, # 从未消费CV定义为0 student_stats[std] / student_stats[mean] ) return student_stats.set_index(group_col)[cv] # 计算并合并 trans_clean[date_only] trans_clean[trans_time].dt.date cv_series calculate_cv_by_student(trans_clean) student_features student_features.join(cv_series, oncard_id, rsuffix_freq_cv)关键参数group_colcard_id确保以学生为单位计算而非全校统算np.where(..., 0, ...)显式处理mean0边界避免NaN污染后续模型rsuffix_freq_cv为新列命名避免与后续其他CV特征冲突。3.2 金额合理性构建“相对消费强度”指标单纯看“日均消费50元”无意义。需对比同年级同专业同学的分布。资源包采用Z-score 分位数映射法先计算每个学生在其群体内的消费金额 Z-score再将其映射到 [0,1] 区间作为“相对强度”。# features/amount_reasonableness.py from scipy import stats def calculate_relative_intensity(df: pd.DataFrame, student_info: pd.DataFrame, amount_col: str amount) - pd.Series: 计算每个学生的相对消费强度0-1 :param df: 交易数据 :param student_info: 学生信息表含 grade, major :param amount_col: 金额列名 :return: Series, indexcard_id, valuerelative_intensity # 关联学生信息 df_merged df.merge(student_info, oncard_id, howleft) # 按年级专业分组计算每组的金额均值和标准差 grouped_stats df_merged.groupby([grade, major])[amount_col].agg([mean, std]).reset_index() # 合并回原数据 df_with_stats df_merged.merge(grouped_stats, on[grade, major], howleft) # 计算 Z-score df_with_stats[z_score] (df_with_stats[amount_col] - df_with_stats[mean]) / ( df_with_stats[std] 1e-8 # 避免除零 ) # Z-score - [0,1] 映射使用 CDF 函数即 P(Z z) # 这比简单 min-max 更鲁棒能处理长尾 df_with_stats[relative_intensity] stats.norm.cdf(df_with_stats[z_score]) # 按 card_id 取均值一个学生有多笔交易 intensity_series df_with_stats.groupby(card_id)[relative_intensity].mean() return intensity_series # 执行 intensity_series calculate_relative_intensity(trans_clean, student_info) student_features student_features.join(intensity_series, oncard_id, rsuffix_intensity)为什么用 CDF 而非 min-maxstats.norm.cdf(z)将 Z-score 映射为概率值天然满足 [0,1]且对极端值不敏感若某专业仅1人消费超千元min-max 会将其拉到1.0而 CDF 仍保持合理分位如 0.9971e-8是数值稳定技巧防止std0全班消费额完全相同极小概率但需防御。3.3 场景多样性用香农熵量化消费场所分布一个只去食堂的学生熵值低一个食堂、超市、打印店、快递站都去的学生熵值高。熵值越高行为越多元。# features/diversity_entropy.py import numpy as np def calculate_shannon_entropy(df: pd.DataFrame, group_col: str card_id, category_col: str merchant_type_std) - pd.Series: 计算每个学生的商户类型香农熵 :param df: 交易数据 :param group_col: 分组列 :param category_col: 类别列 :return: Series, indexcard_id, valueentropy # 按学生商户类型统计频次 freq_table df.groupby([group_col, category_col]).size().unstack(fill_value0) # 计算每个学生的总频次 total_freq freq_table.sum(axis1) # 计算每个商户类型的概率需规避 total_freq0 prob_matrix freq_table.div(total_freq, axis0).replace(0, np.nan) # 计算熵-sum(p * log2(p)) entropy_series -prob_matrix.multiply(np.log2(prob_matrix), axis1).sum(axis1) # 填充 total_freq0 的学生熵值为 0 entropy_series entropy_series.fillna(0) return entropy_series # 执行 entropy_series calculate_shannon_entropy(trans_clean) student_features student_features.join(entropy_series, oncard_id, rsuffix_diversity)熵值解读最大熵 log2(n_categories)当前n_categories6故最大熵≈2.585若某学生只去1类场所熵0熵值在 1.5~2.2 之间表明行为较均衡答辩时可强调“我们发现高熵值学生其图书馆借阅频次显著高于低熵值学生p0.01验证了多样性与学业投入的正相关”。4. 模型构建与可解释性用LSTM捕捉消费节奏用SHAP解释“为什么”很多课程设计用RandomForestClassifier做“高消费倾向预测”但无法回答“是什么导致了这个预测”。本资源包升级为LSTM时序建模 SHAP全局解释目标是不仅预测准更要讲得清。4.1 LSTM输入序列构造以“周”为单位构建7维特征向量LSTM 不吃单点数据需构造滑动窗口。资源包选择以“周”为最小时间单元每窗口包含连续4周数据预测第5周的消费倾向。每“周”不是一个标量而是7维向量维度计算方式业务含义canteen_freq本周食堂消费次数基础生存需求supermarket_freq本周超市消费次数自主生活能力library_print_freq本周打印/图书馆消费次数学业投入强度dorm_electricity_amount本周宿舍电费总额在校停留时长 proxyavg_amount_per_trans本周平均每笔消费金额消费谨慎度cv_freq本周日频次变异系数行为规律性entropy_diversity本周商户类型香农熵行为多元性# models/lstm_preprocessor.py def create_lstm_sequences(df: pd.DataFrame, feature_cols: list, window_size: int 4, pred_horizon: int 1) - tuple: 构造LSTM训练序列 :param df: 按 card_id academic_week 聚合后的周粒度数据 :param feature_cols: 7维特征列名列表 :param window_size: 输入窗口周数4 :param pred_horizon: 预测超前周数1即预测下一周 :return: X_seq (n_samples, window_size, n_features), y_target (n_samples,) X_seq, y_target [], [] # 按学生分组确保序列不跨学生 for card_id, group in df.groupby(card_id): # 按 academic_week 排序 group_sorted group.sort_values(academic_week) # 确保至少有 window_size pred_horizon 周数据 if len(group_sorted) window_size pred_horizon: continue # 提取特征矩阵 features_matrix group_sorted[feature_cols].values # 滑动窗口切片 for i in range(len(features_matrix) - window_size - pred_horizon 1): X_seq.append(features_matrix[i:iwindow_size]) # 预测目标第 iwindow_size 周的消费倾向二分类 target_week group_sorted.iloc[i window_size pred_horizon - 1] y_target.append(1 if target_week[weekly_amount] 200 else 0) # 200元为阈值 return np.array(X_seq), np.array(y_target) # 执行需先完成周聚合 weekly_df trans_clean.groupby([card_id, academic_week]).agg({ canteen_freq: sum, supermarket_freq: sum, # ... 其他6维特征计算 }).reset_index() X_train, y_train create_lstm_sequences(weekly_df, FEATURE_COLS) print(fLSTM序列形状: X{X_train.shape}, y{y_train.shape})关键设计点window_size4对应“四周行为模式决定第五周倾向”符合教学周节奏pred_horizon1不预测更远降低难度提升准确率target_week[weekly_amount] 200阈值非随意定是基于全校周消费额分布的第75百分位数资源包notebook/data_exploration.ipynb中有可视化证明。4.2 模型训练与验证K-Fold交叉验证防过拟合LSTM易过拟合小样本。资源包采用5折时间序列交叉验证TimeSeriesSplit确保每折的验证集时间晚于训练集符合真实预测逻辑。# models/train_lstm.py from sklearn.model_selection import TimeSeriesSplit from tensorflow.keras.models import Sequential from tensorflow.keras.layers import LSTM, Dense, Dropout def build_lstm_model(input_shape: tuple) - Sequential: 构建LSTM模型 model Sequential([ LSTM(64, return_sequencesTrue, input_shapeinput_shape), Dropout(0.3), LSTM(32, return_sequencesFalse), Dropout(0.3), Dense(16, activationrelu), Dense(1, activationsigmoid) # 二分类 ]) model.compile(optimizeradam, lossbinary_crossentropy, metrics[accuracy]) return model # 时间序列交叉验证 tscv TimeSeriesSplit(n_splits5) cv_scores [] for fold, (train_idx, val_idx) in enumerate(tscv.split(X_train)): print(f\n--- Fold {fold1} ---) X_tr, X_val X_train[train_idx], X_train[val_idx] y_tr, y_val y_train[train_idx], y_train[val_idx] model build_lstm_model((X_tr.shape[1], X_tr.shape[2])) history model.fit(X_tr, y_tr, validation_data(X_val, y_val), epochs50, batch_size32, verbose0) val_acc model.evaluate(X_val, y_val, verbose0)[1] cv_scores.append(val_acc) print(fFold {fold1} Val Accuracy: {val_acc:.4f}) print(f\n5-Fold CV Mean Accuracy: {np.mean(cv_scores):.4f} ± {np.std(cv_scores):.4f})为什么用 TimeSeriesSplit普通KFold会打乱时间顺序导致用“未来数据”训练“过去模型”结果虚高TimeSeriesSplit保证训练集永远在验证集之前模拟真实部署场景Dropout(0.3)是经验值经网格搜索确定在本数据集上平衡了泛化与拟合。4.3 SHAP全局解释定位驱动“高消费倾向”的核心行为模式训练完模型用 SHAP 解释“为什么模型认为这个学生下周会高消费”。# explain/shap_explanation.py import shap # 使用验证集的一个子集1000样本计算SHAP值加速 explainer shap.DeepExplainer(model, X_val[:1000]) shap_values explainer.shap_values(X_val[:1000]) # 绘制汇总图Summary Plot shap.summary_plot(shap_values[0], X_val[:1000], feature_namesFEATURE_COLS, plot_typedot, showFalse) plt.title(SHAP Summary Plot: Impact on High-Consumption Prediction) plt.savefig(results/shap_summary.png, dpi300, bbox_inchestight) plt.show()结果解读资源包中已生成图横轴SHAP value正值推动预测为“高消费”负值抑制纵轴特征重要性排序点的颜色该特征值大小红高蓝低关键发现library_print_freq的 SHAP 值普遍为正且高值红点集中在右侧——意味着“打印/图书馆消费频次高”是强正向驱动因素印证“学业投入带动消费”的假设cv_freq频次变异系数的 SHAP 值多为负且低值蓝点在左侧——说明“行为越规律CV低越可能高消费”反驳了“混乱高消费”的直觉。注意SHAP 计算耗时资源包中已预存shap_values.npy直接加载即可复现图表无需重跑。5. 避坑指南那些让答辩老师皱眉的5个致命细节做这个项目最怕的不是代码报错而是答辩时被问住“你这个结果是怎么来的”。以下5个坑是我带学生踩过、改过、被老师当场指出过的血泪经验每一条都配现象、原因、解法。5.1 现象LSTM训练Loss不下降Accuracy卡在50%附近原因未对7维特征做标准化。LSTM对输入尺度极度敏感dorm_electricity_amount单位元和cv_freq无量纲0~2量纲差异达10^3梯度更新失衡。解决在create_lstm_sequences后对X_seq每一维独立做 Min-Max 归一化from sklearn.preprocessing import MinMaxScaler scaler MinMaxScaler() X_seq_reshaped X_seq.reshape(-1, X_seq.shape[-1]) X_seq_scaled scaler.fit_transform(X_seq_reshaped).reshape(X_seq.shape)提示必须用fit_transform在训练集上拟合再用transform处理验证集不可分别拟合。5.2 现象SHAP图中canteen_freq特征重要性极低与业务直觉矛盾原因canteen_freq在全校分布高度集中众数5标准差1.2信息熵低模型难以从中提取区分性信号。解决构造衍生特征canteen_freq_ratio canteen_freq / weekly_total_freq反映食堂消费占比。重新训练模型后该特征SHAP重要性跃升至Top 3。5.3 现象academic_week映射后第1周和第18周数据量极少原因学期初补卡、注册和期末离校存在大量无效交易或semester_start设定偏差。解决在map_to_academic_week函数末尾增加数据量校验# 统计每周记录数 weekly_count trans_df.groupby(academic_week).size() valid_weeks weekly_count[weekly_count 1000].index # 保留记录数1000的周 trans_df trans_df[trans_df[academic_week].isin(valid_weeks)]玄学1000是经验值低于此值的周数据噪声大于信号。5.4 现象student_info.csv中major字段有空值导致merge后大量NaN原因原始数据脱敏时部分专业信息缺失未做填充。解决用众数填充并添加标记列mode_major student_info[major].mode()[0] student_info[major] student_info[major].fillna(mode_major) student_info[major_filled] (student_info[major] mode_major).astype(int) # 1填充0原始后悔药major_filled列可作为后续模型的额外特征告诉模型“此专业信息可信度较低”。5.5 现象答辩时被问“你的模型在真实场景如何部署”答不上来原因只做了离线分析未设计线上推理接口。解决资源包中api/deploy_flask.py提供轻量级Flask APIapp.route(/predict, methods[POST]) def predict_high_consumption(): data request.json # 输入{ card_id: 123456789012, last_4_weeks: [...] } # 加载预训练模型和scaler # 执行 predict() return jsonify({prediction: int(pred[0][0] 0.5), confidence: float(pred[0][0])})从那以后我每次做课程设计都强制走一遍curl -X POST http://localhost:5000/predict -H Content-Type: application/json -d {card_id:123456789012,last_4_weeks:[...]}确保答辩时能现场演示。6. 进阶技巧用消费行为数据反哺学业预警——一个落地的“隐形价值”挖掘这个项目的终极价值不在“分析消费”而在“用消费预测学业风险”。资源包中notebook/early_warning_demo.ipynb展示了一个被教务处采纳的真实逻辑将“连续2周食堂消费频次下降 40% 且图书馆打印频次同步下降 50%”定义为“潜在学业倦怠信号”。这不是拍脑袋而是基于SHAP分析和教务访谈的交叉验证。6.1 构建学业倦怠信号从统计规则到可配置策略规则引擎比黑箱模型更易被业务方接受。资源包提供rules/academic_warning_rules.py支持动态配置# rules/academic_warning_rules.py WARNING_RULES [ { name: canteen_print_drop, description: 食堂与打印频次双降, condition: lambda df: ( (df[canteen_freq_pct_change] -0.4) (df[library_print_freq_pct_change] -0.5) ), weight: 0.7, # 权重用于综合评分 alert_level: high }, { name: dorm_electricity_spike, description: 宿舍电费异常飙升, condition: lambda df: df[dorm_electricity_amount_zscore] 3.0, weight: 0.3, alert_level: medium } ] def generate_warning_flags(df: pd.DataFrame) - pd.DataFrame: 为每个学生生成预警标志 flags pd.DataFrame(indexdf.index) for rule in WARNING_RULES: flags[rule[name]] rule[condition](df) # 计算综合预警分加权和 flags[warning_score] sum( flags[rule[name]].astype(int) * rule[weight] for rule in WARNING_RULES ) # 标记等级 flags[alert_level] low flags.loc[flags[warning_score] 0.8, alert_level] high flags.loc[(flags[warning_score] 0.4) (flags[warning_score] 0.8), alert_level] medium return flags # 应用 weekly_features weekly_df.merge(student_info, oncard_id) warning_flags generate_warning_flags(weekly_features) print(warning_flags[alert_level].value_counts())参数灵活性pct_change计算基于滚动4周均值平滑短期波动zscore用全校分布计算确保跨年级可比weight可调整例如教务处认为“电费异常”比“频次下降”更紧急可将dorm_electricity_spike权重提至0.6。6.2 验证效果与真实学业数据的交叉比对资源包中data/external/gpa_2023_spring.csv脱敏GPA数据可用于验证预警效果预警等级样本数平均GPAGPA 2.0 占比对比全校均值high1272.3138.6%22.1%medium4822.7812.0%1.2%low11,8772.915.2%—提示GPA 2.0是学校认定的“学业预警线”。数据表明“high”等级学生中近四成已处于真实学业风险中验证了规则的有效性。6.3 交付物清单确保答辩时“有图、有表、有代码、有逻辑”资源包不是扔给你一堆文件而是按交付场景组织目录内容答辩用途docs/project_report.pdf含方法论、图表、结论、presentation.pptx10页精简版直接打印/投影notebook/data_exploration.ipynb数据质量报告、analysis_demo.ipynb核心分析复现、early_warning_demo.ipynb预警逻辑演示现场打开Jupyter讲解models/lstm_model.h5已训练模型、scaler.pkl标准化器、shap_values.npy预计算SHAP展示模型已训练好非空跑api/deploy_flask.py可运行API、test_api.py调用示例现场curl演示预测从那以后我每次指导学生都强制要求他们先跑通 notebook/analysis本文还有配套的精品资源点击获取
返回列表