简介本资源为基于阿里天池大赛学习赛的天猫复购预测案例的完整源代码与文档说明面向计算机、数据科学相关专业的在校学生及机器学习入门者可用于期末大作业、课程设计或毕业设计场景。项目围绕天猫用户复购行为预测这一经典赛题展开涵盖数据读取、特征工程、模型训练与结果输出等完整流程代码注释详尽新手也能快速理解并部署运行。压缩包共8个文件约4.64MB包含3个Python脚本数据加载、训练与测试、1个已训练模型文件、1个结果CSV、1份README说明文档及特征重要性图等结构清晰、便于按模块查阅。目前已有92人学习下载。通过该资源读者可获得一套可直接运行的赛题解决方案理解复购预测的建模思路与特征处理技巧并借助文档说明快速完成环境搭建与结果复现适合作为课程实践与竞赛练手的参考范例。1. 天猫复购预测这套源码为什么值得你花一个晚上跑通电商复购预测听起来像大厂算法团队的专属课题但阿里天池学习赛把它拆成了一个普通开发者能上手的二分类问题给你一批用户在天猫上的行为日志预测他们在未来某个时间窗口内会不会再次购买。这套「基于阿里天池大赛学习赛的天猫复购预测案例源代码文档说明」把整个流程打包好了——数据读取、特征工程、模型训练、结果输出外加一份文档说明拿来就能跑。适合谁正在找 Python 期末大作业或毕业设计选题的学生想补一个完整机器学习项目经历的转行者以及需要快速验证复购预测思路的运营或数据从业者。它不教你从零推导公式而是让你看到一个真实赛题从原始日志到提交文件的完整链路这个链路本身就是最值钱的部分。2. 拆开源码包数据流、特征工程与模型选型2.1 先搞清楚赛题在预测什么天猫复购预测的原始数据通常包含两张表用户行为日志表和用户画像表。行为日志记录每个用户对每个品牌的浏览、收藏、加购、购买四类动作及时间戳画像表则包含性别、年龄、消费层级等静态属性。预测目标是在给定的时间窗口内某个用户对某个品牌是否会复购。注意这里的「复购」不是简单看用户有没有买过而是要在训练集和测试集之间划一条时间线——用较早时间段的行为预测较晚时间段的结果。这个时间切分逻辑是整场比赛的核心也是很多新手第一个翻车的地方。源码里一般会先做时间边界处理把行为日志按时间排序然后以某个时间点为界之前的数据用来构造特征之后的数据用来生成标签。这一步如果搞错比如用了未来信息去构造特征线下验证分数会虚高线上提交直接崩盘。我一般会先画一条时间轴把训练窗口、验证窗口、测试窗口标清楚再动手写代码。2.2 特征工程把行为日志变成模型能吃的数字原始日志是「用户-品牌-时间-行为类型」的长表模型没法直接吃。源码里的做法通常是做多张透视表再拼接。下面这段代码展示了如何从行为日志中提取用户对品牌的四类行为计数import pandas as pd # 假设 df 是行为日志包含 user_id, brand_id, action_type, timestamp # action_type: 0-浏览 1-收藏 2-加购 3-购买 # 按用户-品牌分组统计各类行为次数 behavior_count df.groupby([user_id, brand_id, action_type]).size().unstack(fill_value0) behavior_count.columns [view_cnt, fav_cnt, cart_cnt, buy_cnt] # 统计最近一次行为距今天数假设参考时间点为 t_ref t_ref df[timestamp].max() last_action df.groupby([user_id, brand_id])[timestamp].max().reset_index() last_action[days_since_last] (t_ref - last_action[timestamp]).dt.days behavior_count behavior_count.merge(last_action[[user_id, brand_id, days_since_last]], on[user_id, brand_id], howleft) # 统计用户总行为数、品牌总行为数等交叉特征 user_total df.groupby(user_id).size().rename(user_total_actions) brand_total df.groupby(brand_id).size().rename(brand_total_actions) behavior_count behavior_count.merge(user_total, onuser_id, howleft) behavior_count behavior_count.merge(brand_total, onbrand_id, howleft) print(behavior_count.head())这段代码的逻辑是先把长表按「用户-品牌-行为类型」做透视得到每个用户对每个品牌的浏览、收藏、加购、购买次数再计算最近一次行为距参考时间的天数这个特征能反映用户的活跃衰减最后拼接用户维度和品牌维度的总量特征给模型提供全局视角。参数方面t_ref的选择很关键一般取训练集的最后一天不能取测试集的时间否则就是标签泄露。fill_value0保证没有某类行为的组合不会出现缺失值。除了计数特征源码里通常还会做转化率特征比如加购转化率 购买次数 / 加购次数收藏转化率 购买次数 / 收藏次数。这些比率特征比原始计数更能反映用户意图。注意分母为 0 的情况要处理一般加一个平滑项或者直接置 0。2.3 模型选型为什么是 LightGBM 而不是深度学习打开源码的模型部分大概率看到的是 LightGBM 或 XGBoost。这不是偷懒而是这类表格型赛题的常见选择。行为日志经过特征工程后变成了一张宽表每行是一个「用户-品牌」对每列是数值特征这种结构树模型天然适配。LightGBM 的优势在于训练速度快支持类别特征直接输入对缺失值不敏感而且调参相对直观。深度学习在这类问题上不是不能做但需要处理序列结构调参成本高收益不一定明显。源码里一般会这样组织训练流程import lightgbm as lgb from sklearn.model_selection import train_test_split from sklearn.metrics import roc_auc_score # X 是特征矩阵y 是标签0/1 X_train, X_val, y_train, y_val train_test_split(X, y, test_size0.2, random_state42, stratifyy) # 构造 Dataset dtrain lgb.Dataset(X_train, labely_train) dval lgb.Dataset(X_val, labely_val, referencedtrain) # 参数设置 params { objective: binary, metric: auc, boosting_type: gbdt, num_leaves: 63, learning_rate: 0.05, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 5, verbose: -1, seed: 42 } # 训练 model lgb.train( params, dtrain, num_boost_round1000, valid_sets[dval], callbacks[lgb.early_stopping(50), lgb.log_evaluation(100)] ) # 验证 y_pred model.predict(X_val, num_iterationmodel.best_iteration) print(AUC:, roc_auc_score(y_val, y_pred))参数说明num_leaves63控制树的复杂度太大容易过拟合太小欠拟合learning_rate0.05配合num_boost_round1000和早停是比较稳的组合feature_fraction和bagging_fraction都是 0.8增加随机性防过拟合。early_stopping(50)表示验证集 AUC 连续 50 轮不提升就停省时间也防过拟合。stratifyy保证训练集和验证集的标签比例一致避免验证集正样本太少导致 AUC 波动大。如果源码里用的是 XGBoost参数逻辑类似但num_leaves换成max_depth类别特征需要自己做编码。LightGBM 可以直接声明类别特征列省一步。2.4 文档说明里容易被忽略的细节源码包里的文档说明通常不会写太长但有几个地方值得逐字看一是数据路径的配置很多跑不通的情况就是路径写死了或者相对路径不对二是依赖库版本LightGBM 和 pandas 的版本差异可能导致 API 不兼容三是提交文件的格式要求天池比赛一般要求 CSV 两列一列是 user_id 和 brand_id 的组合一列是预测概率列名和顺序错了提交会报错。我一般会先把文档里的「运行环境」和「文件说明」两节看完再动手比直接跑代码省时间。3. 从零跑通环境配置、数据准备与训练脚本3.1 环境配置别在版本上栽跟头拿到源码包后第一步不是急着python main.py而是先看依赖。常见做法是创建一个干净的虚拟环境然后按文档说明安装指定版本。如果文档没写版本我一般会按以下组合来这套组合在多数天池学习赛代码里都能跑通# 创建虚拟环境 python -m venv venv source venv/bin/activate # Windows 用 venv\Scripts\activate # 安装核心依赖 pip install pandas1.3.5 pip install numpy1.21.6 pip install scikit-learn1.0.2 pip install lightgbm3.3.5 pip install matplotlib3.5.3为什么锁版本因为 LightGBM 4.x 和 3.x 在lgb.train的 callback 参数上有差异pandas 2.x 对groupby的默认行为也有调整。不锁版本可能报一些莫名其妙的错比如TypeError: train() got an unexpected keyword argument callbacks其实就是版本对不上。如果源码里带了requirements.txt直接pip install -r requirements.txt最省事。3.2 数据准备路径、格式与内存天池学习赛的数据一般通过官方页面下载格式是 CSV。源码里通常会有一个data/目录里面放train.csv、test.csv、user_info.csv等文件。你需要把下载的数据放到对应位置或者修改代码里的路径配置。常见做法是在代码开头定义一个DATA_PATH变量所有读取都基于它import os import pandas as pd DATA_PATH ./data train pd.read_csv(os.path.join(DATA_PATH, train.csv)) test pd.read_csv(os.path.join(DATA_PATH, test.csv)) user_info pd.read_csv(os.path.join(DATA_PATH, user_info.csv)) print(train shape:, train.shape) print(test shape:, test.shape) print(user_info shape:, user_info.shape) print(train columns:, train.columns.tolist())这段代码先检查数据是否读进来、形状对不对。如果train.shape是(0, 0)说明路径错了或者文件没放对。如果内存不够可以只读需要的列用usecols参数或者把数据类型从int64降为int32能省一半内存。行为日志表可能几百万行16G 内存的机器要留意。3.3 训练脚本从特征到提交文件源码的主训练脚本一般叫train.py或main.py流程是读数据 → 构造特征 → 划分训练验证集 → 训练模型 → 预测测试集 → 生成提交文件。下面是一个简化的端到端示例把关键步骤串起来import pandas as pd import numpy as np import lightgbm as lgb from sklearn.model_selection import train_test_split from sklearn.metrics import roc_auc_score # 1. 读取数据 DATA_PATH ./data train pd.read_csv(f{DATA_PATH}/train.csv) test pd.read_csv(f{DATA_PATH}/test.csv) # 2. 构造特征以行为计数为例 def build_features(df): # 按用户-品牌-行为类型计数 cnt df.groupby([user_id, brand_id, action_type]).size().unstack(fill_value0) cnt.columns [faction_{c}_cnt for c in cnt.columns] # 最近行为时间 t_ref df[timestamp].max() last df.groupby([user_id, brand_id])[timestamp].max().reset_index() last[days_since_last] (t_ref - last[timestamp]).dt.days cnt cnt.merge(last[[user_id, brand_id, days_since_last]], on[user_id, brand_id], howleft) return cnt.reset_index() train_feat build_features(train) test_feat build_features(test) # 3. 生成标签假设 train 里有 label 列 y train.groupby([user_id, brand_id])[label].max().reset_index() train_feat train_feat.merge(y, on[user_id, brand_id], howleft) train_feat[label] train_feat[label].fillna(0) # 4. 准备训练数据 feature_cols [c for c in train_feat.columns if c not in [user_id, brand_id, label]] X train_feat[feature_cols] y train_feat[label] X_train, X_val, y_train, y_val train_test_split(X, y, test_size0.2, random_state42, stratifyy) # 5. 训练 dtrain lgb.Dataset(X_train, labely_train) dval lgb.Dataset(X_val, labely_val, referencedtrain) params { objective: binary, metric: auc, num_leaves: 63, learning_rate: 0.05, feature_fraction: 0.8, bagging_fraction: 0.8, bagging_freq: 5, verbose: -1, seed: 42 } model lgb.train(params, dtrain, num_boost_round1000, valid_sets[dval], callbacks[lgb.early_stopping(50), lgb.log_evaluation(100)]) # 6. 验证 y_pred_val model.predict(X_val, num_iterationmodel.best_iteration) print(Validation AUC:, roc_auc_score(y_val, y_pred_val)) # 7. 预测测试集并生成提交文件 X_test test_feat[feature_cols] test_pred model.predict(X_test, num_iterationmodel.best_iteration) submission test_feat[[user_id, brand_id]].copy() submission[prob] test_pred submission.to_csv(submission.csv, indexFalse) print(Submission saved.)逻辑说明第 2 步的build_features是核心把原始日志转成用户-品牌粒度的特征表第 3 步从训练集里提取标签注意用max是因为同一个用户-品牌对可能有多条记录只要有一次购买就算正样本第 4 步把特征列和标签分开第 5 步训练时用验证集做早停第 7 步生成提交文件列名要和比赛要求一致。参数方面test_size0.2是常见划分比例如果数据量很大可以降到 0.1random_state固定住保证可复现。跑完这个脚本你会得到一个submission.csv可以提交到天池看分数。如果 AUC 在 0.6 到 0.7 之间说明特征工程还有提升空间如果低于 0.5大概率是标签或者时间切分出了问题。4. 避坑与排查那些让分数崩掉的细节4.1 现象线下 AUC 很高线上提交分数很低原因最常见的是标签泄露。比如在构造特征时用了未来时间窗口的行为数据或者把测试集的信息混进了训练集。另一个可能是训练集和测试集的用户-品牌对分布差异大线下验证集划分没有按时间切分而是随机划分导致验证集和训练集有重叠用户。解决严格按时间切分训练集和验证集比如用前 80% 时间的数据做训练后 20% 做验证。特征构造时只使用当前时间点之前的数据。检查代码里有没有t_ref取了全局最大值的情况应该取训练集的最大时间戳。4.2 现象LightGBM 训练报错Cannot convert auto to int原因LightGBM 版本和 pandas 版本不兼容或者num_leaves参数传了浮点数。有时候feature_fraction传了整数也会报类似错误。解决检查params里所有数值参数是不是 Python 原生类型num_leaves必须是intlearning_rate必须是float。如果版本冲突降级 LightGBM 到 3.3.x 或者升级 pandas 到兼容版本。我一般会在params定义后加一行print({k: type(v) for k, v in params.items()})来排查。4.3 现象提交文件格式错误平台提示「列名不匹配」原因天池比赛的提交格式通常要求两列列名可能是user_id和prediction或者user_id_brand_id和prob。不同比赛要求不一样源码里的提交代码可能没更新到最新要求。解决先看比赛页面的「提交说明」确认列名和顺序。如果要求user_id和brand_id合并成一列用submission[id] submission[user_id].astype(str) _ submission[brand_id].astype(str)再输出。概率值保留 4 到 6 位小数即可太多位数没必要。4.4 现象内存不足程序被 Kill原因行为日志表太大groupby和merge操作产生大量中间变量。pandas 默认用int64和float64内存占用是实际数据的两倍以上。解决读数据时用dtype参数指定更小的类型比如{user_id: int32, brand_id: int32, action_type: int8}。groupby之后及时del掉不用的变量用gc.collect()回收内存。如果还是不够可以分块读取或者只取部分用户做实验。4.5 现象验证集 AUC 波动很大每次跑结果不一样原因正负样本比例不均衡验证集里正样本太少AUC 对随机种子敏感。或者bagging_fraction设得太小模型方差大。解决用stratifyy做分层抽样保证验证集正负比例和训练集一致。把bagging_fraction调到 0.8 以上bagging_freq设为 1 到 5。如果数据量允许做 5 折交叉验证取平均比单次划分更稳。5. 进阶技巧把 AUC 从 0.65 推到 0.72 的几个动作跑通基础版之后你会发现分数卡在 0.65 左右上不去。这不是模型不行而是特征太粗。下面几个动作是我在实际比赛中验证过有效的按优先级排列。第一个动作是加时间衰减特征。用户上周买过和半年前买过复购概率完全不同。做法是给每个行为按时间加权越近的行为权重越高。常见做法是用指数衰减weight exp(-lambda * days_since_action)lambda取 0.1 到 0.3 之间。这个特征加进去AUC 通常能涨 1 到 2 个点。第二个动作是加品牌热度特征。热门品牌的自然复购率就高模型需要知道这个先验。统计每个品牌在训练窗口内的总购买人数、总购买次数、复购率作为品牌维度的特征拼进去。注意要用训练窗口的数据算不能用全量数据。第三个动作是加用户活跃度分层。把用户按总行为数分成高活、中活、低活三档每档单独看复购率差异。这个特征可以用pd.qcut做分箱然后做 one-hot 或者保留序数。树模型对序数特征处理得很好不需要 one-hot。第四个动作是调参。基础版的num_leaves63和learning_rate0.05是通用配置但针对复购预测这种正样本比例低的场景可以试试scale_pos_weight参数把正样本权重调高。一般设成负样本数除以正样本数比如 10:1 的比例就设 10。另外min_child_samples可以调到 50 到 100防止模型在稀疏特征上过拟合。下面是一个加时间衰减特征的代码片段import numpy as np def add_time_decay_feature(df, t_ref, decay_rate0.2): 给每个行为加时间衰减权重按用户-品牌聚合 df: 行为日志包含 user_id, brand_id, timestamp t_ref: 参考时间点 decay_rate: 衰减系数越大衰减越快 df df.copy() df[days_diff] (t_ref - df[timestamp]).dt.days df[weight] np.exp(-decay_rate * df[days_diff]) # 按用户-品牌聚合加权行为数 decay_feat df.groupby([user_id, brand_id])[weight].sum().reset_index() decay_feat.columns [user_id, brand_id, weighted_action_sum] return decay_feat # 使用示例 t_ref train[timestamp].max() decay_feat add_time_decay_feature(train, t_ref, decay_rate0.2) train_feat train_feat.merge(decay_feat, on[user_id, brand_id], howleft) train_feat[weighted_action_sum] train_feat[weighted_action_sum].fillna(0)这段代码的逻辑是先算每个行为距参考时间的天数再用指数函数转成权重最后按用户-品牌求和。decay_rate控制衰减速度0.2 表示 10 天前的行为权重降到约 0.1330 天前降到约 0.002。这个特征比单纯的计数更能区分「最近活跃」和「曾经活跃」的用户。注意t_ref要用训练集的最大时间戳测试集的特征构造也要用同一个t_ref不能各算各的。还有一个容易被忽略的点是特征筛选。树模型虽然能处理冗余特征但太多噪声特征会拖累效果。我一般会看model.feature_importance(importance_typegain)把重要性为 0 或者极低的特征删掉再重训一次。通常能去掉 20% 到 30% 的特征AUC 不降反升。最后说一个验证方法不要只看 AUC还要看 KS 和提升度。AUC 衡量的是排序能力但业务上更关心 top 10% 的用户里有多少真的复购了。可以算一下top 10% 的命中率这个指标更贴近实际投放场景。如果 AUC 涨了但 top 命中率没涨说明模型只是把中间段排得更准了头部没改善需要针对性调整。从那以后我每次跑完模型都会强制走一遍「时间切分检查 → 特征重要性筛选 → top 命中率验证」这三步不再只看一个 AUC 数字。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
高效时间块管理法:28天提升学习效率的实践指南 1. 项目背景与核心价值这个看似简单的时间记录标题,实际上隐藏着高效学习者的核心方法论。作为一名经历过考研、考证和多个技能提升周期的老手,我深刻理解这种时间块记录法背后的精妙之处。0x3f这个ID背后代表的是一位典型的极客型学习者,而2… · 2026/9/25 2:12:12
OptiScaler 完整实战:超采样切换与排障指南 OptiScaler 完整实战:超采样切换与排障指南 【免费下载链接】OptiScaler OptiScaler bridges upscaling/frame gen across GPUs. Supports DLSS2/XeSS/FSR2 inputs, replaces native upscalers, enables FSR-FG/XeFG on non-FG titles. Supports Nukem mod for DLSS… · 2026/9/25 2:12:06
Conky 仓库开发指南:构建测试、代码规范与架构扩展实战 桌面应用系统监控 【免费下载链接】conky Light-weight system monitor for X, Wayland, and other things, too 项目地址: https://gitcode.com/gh_mirrors/co/conky 点击查看 免费下载 本篇指南以 Conky 仓库根目录的 AGENTS.md 为骨架,系统讲解贡献者… · 2026/9/25 2:35:18
Windows底层网络开发:Npcap SDK抓包与BPF过滤实战 简介:本资源是面向Windows平台网络开发与安全分析工程师的NPCap SDK 1.01开发套件,专为实现无线WiFi数据包捕获、协议解析与流量监控提供底层支持。适用于网络诊断工具开发、入侵检测系统(IDS)原型构建及网络安全教学实验等场景&a… · 2026/9/25 2:35:18
SSM 图书管理系统 🥂(❁◡❁)您的点赞👍➕评论📝➕收藏⭐是作者创作的最大动力🤞💖📕🎉🔥 支持我:点赞👍收藏⭐️留言📝欢迎留言讨论🔥🔥&am… · 2026/9/25 2:35:06
使用 PaddleSpeech 将 CC-CEDICT 中英词典解析为 JSON 格式的完整指南 人工智能语音音频NLP媒体生成 【免费下载链接】PaddleSpeech Easy-to-use Speech Toolkit including Self-Supervised Learning model, SOTA/Streaming ASR with punctuation, Streaming TTS with text frontend, Speaker Verification System, End-to-End Speech Translation … · 2026/9/25 2:34:53
华为AP4050DN FIT转FAT实战:从瘦AP到胖AP的完整刷机指南 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 2:34:47
创维E900V22D刷机全攻略:S905L3SB芯片兼容性解析与救砖实战 /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:31
MQTT协议原理与Broker服务器搭建实战:从Mosquitto到EMQX /* MD / 富文本中的 .toc(含博客园搬家等嵌套结构);.toc-box 在侧栏,不受影响 */#content_views .toc,/* 编辑器常在目录前后插入空 p(:empty 仍占 20px),一并去掉避免顶空隙 */#content_views.markdown_views > p:empty:has(+ .toc),#content_views.markdown_views … · 2026/9/25 1:00:37