news 2026/8/30 0:20:29

天猫复购预测实战:特征工程与LightGBM全流程解析

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
天猫复购预测实战:特征工程与LightGBM全流程解析

简介:用户复购预测是电商用户行为分析中的经典问题,其核心在于从海量行为日志中挖掘用户的真实购买意图。特征工程作为数据挖掘的关键环节,直接决定了模型性能的上限,而梯度提升树(如LightGBM)则是逼近这一上限的高效工具。在业务实践中,浏览、收藏、加购、购买等行为序列蕴含丰富的意图信号,通过构造用户-商家交叉特征、时间窗口特征等方式,可显著提升复购模型的判别能力。围绕天池学习赛“天猫复购预测”赛题,详细拆解从数据探索、特征构建、模型训练到时序验证的完整流程,并分享类别不平衡处理、AUC评价指标及常见踩坑经验,为电商大促场景下的复购预估提供可复用的工程参考。 整理代码仓库的时候,翻到了去年打阿里天池学习赛“天猫复购预测”的完整项目,从数据探索脚本到最终提交的模型权重都还在。这个赛题我一直觉得是入门电商用户行为分析最好的练习之一:数据规模不算夸张,业务含义很清晰,特征工程能玩的花样很多,而且只要特征做得扎实,单靠LightGBM就能拿到高分段。后来我把整套源代码和文档说明整理成了规范的项目结构,每次带新人入门复购预测,都直接拿这套代码当模板。这篇文章就把我从头到尾的思路、代码组织方式和踩坑记录全部摊开讲,适合正在打比赛、或者想在业务里落地用户复购模型的朋友参考。

1. 赛题拆解:天猫复购预测到底在预测什么

1.1 业务背景与数据形态

“天猫复购预测”本质上是一个用户-商家二元组的二分类问题。天池给出的背景是:有用户在某个商家买过东西,你手里有这些用户之前6个月的行为日志,包括浏览、收藏、加购、购买这四类行为,同时给了用户画像信息,最后要预测这些用户在双11当天是否会再次购买给定商家的商品。

这句话信息量很大,很多人一上来就把它当成“用户复购预测”,结果特征工程全围绕用户维度做,忽略了赛题里最关键的约束:训练样本本身是(user_id, merchant_id)的pair对。也就是说,模型要判断的不是“这个用户会不会买东西”,而是“这个用户会不会在这个商家买东西”。这个差别决定了特征工程的重心必须放在用户和商家的交互关系上。

先看数据文件。天池学习赛的官方数据通常包含四类文件,字段大致如下:

文件主要字段用途
user_log_format1.csvuser_id, item_id, cat_id, seller_id, brand_id, time_stamp, action_type6个月的行为日志,一张表包含所有交互行为
train_format1.csvuser_id, age_range, gender, merchant_id, label训练样本,label表示双11当天是否购买
test_format1.csvuser_id, age_range, gender, merchant_id测试样本,需要输出购买概率
user_info_format1.csvuser_id, age_range, gender用户画像补充信息

这里有个容易忽略的点:行为日志里的seller_id和训练样本里的merchant_id并不总是一一对应关系,需要仔细核对数据字典。我整理代码时专门写了一个字段核对脚本,把seller_id和merchant_id的映射关系先跑清楚,避免后面做特征聚合时张冠李戴。

1.2 评价指标AUC与它的意义

复购预测场景下,正负样本比例严重失衡,准确率没有参考价值。天池官方选用AUC作为评价指标。AUC的含义是:随机给一个正样本和一个负样本,模型给正样本打分高于负样本的概率。它不依赖阈值选择,反映的是模型整体的排序能力。

业务上对应的是:在需要触达的潜在复购用户列表里,模型能不能把真正会复购的人排到前面。同一个模型阈值定0.5还是0.3,只影响最终筛选人数,不影响排序质量。竞赛里大家都追求AUC,本质上是在比谁的用户-商家排序更贴近真实购买概率。

1.3 完整项目结构概览

这份源码不是随手写的实验notebook,而是按可复现、可迁移的思路组织成了规范项目:

天猫复购预测/ ├── code/ │ ├── config.py # 路径和参数配置 │ ├── 01_data_exploration.ipynb # 数据探索 │ ├── 02_feature_engineering.py # 特征工程 │ ├── 03_model_train.py # 模型训练与时序验证 │ └── 04_predict.py # 生成提交文件 ├── data/ # 数据目录 ├── docs/ │ ├── 数据说明.md │ └── 特征字典.md └── README.md

这样设计的原因很简单:把探索、特征、训练、预测拆开,方便单独复现。文档说明里把每个文件的输入输出都写清楚了,刚接触的人按README顺序跑一遍也能复现结果。这也是我认为“高分项目”应该具备的样子——代码能跑只是底线,别人能顺着你的思路复现,才说明你真的把问题吃透了。

2. 数据探索阶段:那些值得关注的分布特征

2.1 行为日志中的动作类型分布

行为日志里的action_type有4个取值:0浏览、1收藏、2加购、3购买。我第一件事就是统计四个动作的总量。

通常浏览行为占绝对大头,购买行为占比很小。收藏和加购虽然量不大,但这两个动作代表用户主动表达的购买意向,对复购预测的权重非常高。一个用户在某个商家加购过5次但一次都没买,和另一个用户浏览过5次但没加购,行为意图完全不同。

我还做了用户维度的转化漏斗统计:浏览到收藏的转化率、收藏到购买的转化率、加购到购买的转化率。这些漏斗特征最后进了模型,重要性排名非常靠前。原因也好理解:一个用户从浏览到加购的转化率越高,说明他使用购物车做决策的习惯越强,双11这种大促场景下,购物车里的东西更容易变成实付订单。

2.2 负样本占比与类别不平衡问题

我观察到训练样本中正样本占比大约只有不到10%。这意味着如果模型全部预测为0,准确率也能有90%以上,但AUC会非常难看。类别不平衡是复购预测必须处理的第一个实际问题。

处理不平衡有一个前置动作:先确认正负样本在特征上的可分性。我画了正负样本在“用户-商家交互次数”这个特征上的分布,发现正样本的交互次数明显更高、最近一次交互时间更近。这说明特征本身就有区分度,模型要学的是排序关系,而不是硬性的分类边界。这一点很重要,它决定了后面建模时的策略选择:与其在采样技巧上花大力气,不如把特征做得更有区分度。

2.3 线下行为与线上行为的分布差异

训练集里用户行为来自前6个月,预测目标是双11当天的购买。6个月的日常行为习惯和双11当天的购物心态差别很大。很多人平时在某个商家只是逛逛,双11当天因为优惠、凑单、囤货等原因就买了。

这个差异提醒我:不能只在全量行为上做统计特征,还要把时间切成“近期”和“远期”。距离双11越近的行为,对预测双11当天是否购买应该越重要。我在特征工程里加了30天、14天、7天的时间窗统计,就是为了捕捉用户在临近大促时的行为变化。这些时间窗特征在后来的重要性排序里表现非常好,也验证了这个业务直觉。

3. 特征工程:把6个月行为压缩成每个样本的画像

3.1 用户维度特征

用户维度特征描述的是用户整体购物习惯。一类是行为量特征:总行为数、总购买数、总浏览次数、总收藏数、总加购数;另一类是多样性特征:交互过多少商家、多少商品、多少类目、多少品牌。

多样性特征比很多人想象的重要。交互类目特别多的用户,通常是大促型的囤货党,他们双11购买的意愿更强;只盯着某几个类目看的用户,往往是目标明确的比价型用户。我在代码里用groupby统计了每个用户覆盖的类目数、商家数、商品数,这些特征的构建成本很低,但信息量很大。

还有一类时间特征:用户活跃天数、平均每天行为数、最近一次行为距离双11的天数、第一次行为到最近一次行为的跨度。最近一次行为时间离双11越近,说明用户在大促前仍然活跃,这类用户在双11下单的概率通常更高。

3.2 商家维度特征

商家特征描述商家本身的吸引力和运营质量。我用行为日志聚合出:商家总销量、商家被购买人数、商家被收藏人数、商家被加购人数、商家在售商品数、商家涉及类目数。

这里比较关键的是商家的“复购潜力”:统计每个商家中有多少比例的用户发生过二次以上购买。如果一个商家的回头客比例高,说明这个商家的商品或服务有粘性,对新用户来说也更可能在双11产生首次复购。我称之为商家维度的“留客率”,后来看特征重要性,它排在商家特征里比较靠前的位置。

但要注意,商家特征不能脱离用户单独使用。同一个商家对老用户和新用户的意义完全不同。新用户可能因为活动力度大被吸引,老用户则可能因为回购习惯或者品牌忠诚度再次购买。所以更重要的还是用户和商家之间的交叉特征。

3.3 用户-商家交叉特征(本赛题的核心)

复购预测的样本是(user_id, merchant_id),所以每一个样本其实代表了一段潜在的用户-商家关系。要预测这段关系在双11是否会变成购买,最直接的方法就是看这段关系在过去6个月里发展到什么程度。

我从行为日志里聚合出用户和商家之间的交互统计,代码大致长这样:

interaction = user_log.groupby(['user_id', 'seller_id'])['action_type'].agg([ ('total_actions', 'count'), ('browse_actions', lambda x: (x == 0).sum()), ('fav_actions', lambda x: (x == 1).sum()), ('cart_actions', lambda x: (x == 2).sum()), ('buy_actions', lambda x: (x == 3).sum()), ]).reset_index()

然后基于这些统计继续加工更深一层的特征。

首先是交互天数:这个用户有多少天在该商家产生过行为。交互天数比交互次数更稳健,因为一天内反复点开同一家店说明不了太多,但连续多天来店里看,说明用户和商家之间的联系更紧密。

其次是最近一次交互距离双11的天数。这是用户-商家关系“新鲜度”的信号。我强烈建议所有做复购预测的人都重视这个特征:如果一个用户11月8号刚在某个商家加购过东西,和另一个用户9月20号之后没再来过的用户相比,前者在双11下单的概率大得多。我在最终模型里看到这个特征对AUC的贡献排在所有特征的前两位。

然后是购买转化率:购买次数除以总交互次数,反映用户在该商家的消费意愿饱和度。转化率太低的用户可能只是随便看看,转化率很高的用户反而可能是已经买够了,最近不太会再买。这个特征不是单调的,树模型能自动捕获这种非线性关系。

最后是行为类型组合特征:是否加购过、加购后是否购买、收藏后是否购买。加购是强意向信号,很多用户会提前把想买的东西放进购物车等双11。我把加购后是否购买单独提出来,发现这个布尔特征对正样本的命中率非常高。

一句话总结:把每个用户-商家对之间的关系用数字“画像”出来,画像越清晰,模型越容易判断双11是否会成交。这也是这个赛题最核心的技术点。

3.4 时间切分与特征有效性验证

时间特征是复购预测的大杀器,但也是最容易做错的地方。我用了一个简单的思路:把行为日志按月份切开,分别统计每个月的行为量,然后看不同月份特征与标签的相关性。

典型的现象:越靠近双11的月份特征和标签的相关性越高。7月的行为量和复购标签的相关性很弱,9月的行为量相关性明显更强。这符合常识:用户在临近期购买决策时留下的行为信号更有价值。

我构造特征时没有简单地把6个月数据全部累加,而是用了滑动窗口。比如:近7天加购数、近14天交互次数、近30天购买次数、近60天交互天数。每类特征在时间粒度上有区分,模型可以自己学习应该更看重哪个窗口。这个设计在模型融合阶段特别有用,因为不同窗口特征往往会在不同的树模型中有不同的优势。

4. 建模与验证:LightGBM下的训练策略

4.1 为什么选LightGBM而不是深度学习

很多人看到用户行为数据就想到embedding、序列模型,但在我当时的实验里,LightGBM在AUC上完全不输给简单的神经网络,而且训练速度快得多、调参成本低。原因很简单:这个赛题的特征经过工程处理之后是典型的结构化表格数据,GBDT这类模型对表格数据有天然优势,对缺失值、异常值和多类别特征都很友好。

深度学习要做的话,一般走的是行为序列方向:把用户行为按时间排序,用GRU或Transformer编码。这类模型有潜力,但需要更大的数据量、更长的调参周期。在竞赛时间有限、目标是拿高分的场景下,把特征工程做扎实之后再上LightGBM,是投入产出比最高的路径。

4.2 类别不平衡的处理:不采样or下采样

我试过几种处理不平衡的方法:随机下采样、SMOTE过采样、调整scale_pos_weight。

试下来的结论是:随机下采样会让训练集变小,导致线下AUC虚高但线上成绩不稳定;SMOTE在表格数据上表现一般,还容易制造噪声样本;最稳妥的是保持原始训练集不变,在LightGBM里设置scale_pos_weight为负样本数除以正样本数的比值。

这个参数的本质是给正样本的损失加权,让模型更关注数量少的那一类。复购预测场景里正负样本比例大概在1:10左右,我把scale_pos_weight设置在8到15之间,用验证集AUC来选。最终线下验证时,这个参数从默认值1调到10左右,AUC提升大约0.005到0.008,虽然幅度不大,但在高分阶段每一点提升都很宝贵。

4.3 时序交叉验证的切分方式

这个赛题里有一个很多人容易犯的错误:直接对训练样本做随机K折交叉验证。随机切分会让同一时间段的用户信息同时出现在训练集和验证集,线下指标会虚高,线上却会打折扣。

我的做法是按时序切分:比如用7月到8月的数据训练,用9月的数据做验证,模拟“预测未来”的真实场景。这样选出来的参数线上更稳。

当然,严格做时序验证也有代价:样本利用率降低。所以我的最终方案是:调参和特征选择用时序验证,确定最终模型后,再在全量数据上重新训练一次,用更少的轮数防止过拟合。这样既保证了参数选择的稳健性,又能让模型充分学习全部历史行为信息。

4.4 参数调优与特征重要性

我给LightGBM设置的基础参数如下:

params = { 'objective': 'binary', 'metric': 'auc', 'learning_rate': 0.05, 'num_leaves': 63, 'max_depth': 7, 'feature_fraction': 0.8, 'bagging_fraction': 0.8, 'bagging_freq': 1, 'scale_pos_weight': 10, 'verbose': -1 }

调参的经验是:先固定learning_rate,在0.05到0.1之间;然后调num_leaves和max_depth,控制模型复杂度;接着调feature_fraction和bagging_fraction,让模型更稳定;最后再回头降低learning_rate并增加n_estimators,配合早停。

训练结束后一定要看特征重要性。我用的衡量方式是gain,即特征被用于分裂时带来的信息增益总和。排名靠前的特征基本都是“最近一次交互距离双11的天数”“用户-商家交互天数”“近30天加购数”这类强业务相关特征。如果发现某个构造复杂的特征排名很低,一般会直接丢掉,减少过拟合风险。

5. 高分经验沉淀与踩坑实录

5.1 最容易掉进去的三个坑

先说第一个坑:样本重复。train和test文件里同一对(user_id, merchant_id)不应该出现两次,但我在做特征合并时发现,如果不先去重,groupby聚合出来的特征值会在不同行之间互相干扰。处理方式很简单:在特征工程之前先按user_id和merchant_id去重,确保每个样本只对应一行特征。

第二个坑:时间戳特征直接当数值用。time_stamp比如“2016-09-30”,如果直接转成数值喂给模型,模型很难学到周期性。应该把它转成距离双11的天数,或者拆成年月日、星期几、是否周末这样的可解释特征。

第三个坑:数据泄露。如果不小心把双11当天的行为日志也纳入了特征统计,线下AUC会异常高,线上直接崩。我在源码里专门做了一个检查函数,统计特征时强制只使用指定截止日期之前的行为日志。这个问题在很多开源代码里都存在,尤其是特征统计脚本写在notebook里的时候,很容易把全量数据都算进去。

5.2 几个“看似有效但最终无效”的操作

我在迭代过程中试过不少方法,效果不好但很常见的操作有以下几类。

把user_id、seller_id、item_id直接做标签编码后当数值特征喂模型。这种做法在树模型里几乎不会带来正向收益,高基数ID还会导致过拟合。我最后是彻底删掉了这些原始ID特征。相比之下,把用户偏好类目标签化会好一些,因为类目数量有限,而且浓缩了用户意图。

尝试加用户行为序列的LSTM模型,AUC和LightGBM差不多,但训练时间多了几十倍。如果只是想要高分,这个方向性价比很低;如果不是为了学习序列建模,不建议在竞赛阶段盲目尝试。

对年龄和性别做粗暴的one-hot编码,提升很小。年龄范围本来就有序,直接用数值编码加缺失值填充反而更稳。我在一个版本里把age_range做成了one-hot,验证集AUC几乎没有变化,后来就放弃了这个方向。

5.3 从0.70到0.75+的提分路径回顾

我的提分过程大致分四个阶段,写在这里给后来的人一个参照。

第一阶段:只做用户和商家的基础统计特征,也就是行为量、交互量这类简单聚合,AUC大概在0.70左右。这个分数已经能保证不垫底,但距离高分很远。

第二阶段:加入用户-商家交叉特征,特别是交互天数、购买转化率、最近交互时间,AUC会往上走一大截,到0.72到0.73之间。这一步是真正的分水岭,做好交叉特征的人和不做交叉特征的人,在这里拉开差距。

第三阶段:加入时间窗口特征和近期行为特征,比如近7天、近30天、近60天的行为统计,AUC再往上走,到0.74以上。这个阶段考验的是对业务节奏的理解,知道用户什么时候的行为信号最有价值。

第四阶段:调整scale_pos_weight和模型参数,再加上LightGBM和XGBoost的简单融合,最终稳定在高分区间。到这一步,基本上能到达这个赛题的头部水平。

这条路径说明了一个核心规律:对于复购预测这类业务,特征决定上限,模型只是逼近上限的工具。如果特征工程做得足够深,哪怕只用LightGBM也能拿到很好的结果。

6. 项目源码与文档说明组成:可复现指南

6.1 代码结构怎么组织

为了让别人能顺畅地复现,我把代码拆成了几个独立模块。config.py负责路径和参数,01_data_exploration.ipynb做探索性分析,02_feature_engineering.py生成所有特征并缓存为parquet文件,03_model_train.py做时序验证和训练,04_predict.py生成提交文件。

每个模块都保持“输入-处理-输出”清晰的结构。这样做的好处是,改特征或者换模型时,只需要动对应的模块,不会把整个流程带崩。比如我想加一个用户-商家交互天数的特征,只需要改02_feature_engineering.py,后面训练和预测脚本完全不用动。

6.2 环境依赖与运行流程

环境依赖主要集中在pandas、numpy、lightgbm、scikit-learn、tqdm这几个库。建议用Python 3.8以上版本,安装方式就是常规的requirements.txt:

pandas>=1.0 numpy>=1.18 lightgbm>=3.0 scikit-learn>=0.22 tqdm>=4.0

运行流程很简单:先跑数据探索脚本确认数据没问题,然后跑特征工程生成特征文件,接着跑训练脚本查看验证集AUC和特征重要性,最后跑预测脚本生成提交文件。文档说明里我写清楚了每一步的输入输出文件名,以及预计的运行时间。这样不管是自己复盘还是别人跑代码,都不会卡在“不知道下一步该做什么”。

6.3 如何迁移到自己的业务场景

很多朋友拿到这份源码后问得最多的问题是:我只想预测自己业务里的复购,能不能直接用?答案是能,但需要做几个替换。

把user_log行为日志换成你自己的用户行为表,把seller

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

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/8/30 0:16:01

LSP与LLM:搭建AI代码补全与编辑器交互的标准桥梁

LSPs for LLMs,直译是“给大语言模型用的 LSP”,更准确地说,是把 Language Server Protocol(语言服务器协议,简称 LSP)当作大语言模型(LLM)和编辑器之间的标准通道。这个方向解决的实…

作者头像 李华
网站建设 2026/8/29 23:57:32

AI本硕博必看:云程奖申报与作品化实战指南

2026年,AI领域的竞争已经从“拼模型参数”进入“拼工程落地”阶段。但一个尴尬的现实是:很多在校AI本硕博手里握着不错的论文、项目甚至开源作品,却始终缺少一个能被行业直接认可的展示窗口。简历上写了三页项目经历,面试官真正想…

作者头像 李华
网站建设 2026/8/29 23:55:00

用飞行手册结构打造Anti-Slop Skill:让AI输出不再废话

你有没有遇到过这种情况:让 AI 写一段技术说明,它交回来一篇“在当今信息化时代……具有重要意义”的官样文章。你把“不要说废话”打在提示词里,它删掉了第一段套话,又补了两段同义反复。问题出在哪? 问题不在于模型…

作者头像 李华
网站建设 2026/8/29 23:53:46

降aigc免费工具哪种适合论文?按AI率、重复率和导出方式选

降aigc免费工具哪种适合论文?按AI率、重复率和导出方式选 降aigc免费工具是否适合论文,要看它能不能完成你当前缺的那一步。AI率检测负责定位,文字处理负责修改,论文查重负责找重复来源,导出功能负责留下可复检文件。…

作者头像 李华
网站建设 2026/8/29 23:52:04

2026前端面试真题:原理深度与工程落地全解析

前端行业这几年变化快,面试的要求也跟着水涨船高。尤其到了2026年这个节点,单纯背八股文已经很难过面试了,考察的重点越来越偏向“原理深度 工程落地 场景应变”这三样东西。我平时也帮团队筛简历、做技术面,见过太多候选人简历…

作者头像 李华