尧图网络 高端网站定制 · 原创设计
免费咨询热线
400-888-6620
免费获取方案
京东销量预测源码拆解:特征工程与RNN/GBDT融合实践
简介一套基于深度学习的京东商品销量预测设计源码面向电商数据挖掘与深度学习开发者提供从数据清洗、特征工程到RNN建模、评估与提交结果的全流程实现。资源共51个文件压缩包约6.96MB包含10个Python源码文件、10个SQL数据库文件、11个CSV数据集、12个ROC曲线与训练过程PNG图以及YAML配置、Git忽略文件和多个提交结果文件结构清晰、可直接复现。已有341人学习下载。该方案覆盖SKU级与用户级两类预测粒度提供规则与RNN等多个版本对比并保留多次提交记录可用作销量预测赛题的完整参考配合SQL建表脚本和预处理代码便于扩展自己的特征与模型是入门电商销量预测和深度学习的实用工程包。1. 京东销量预测源码拆解先定评估口径再谈模型这套包含 51 个文件的源码不是给你一个能直接拿去线上跑的“完美系统”而是一份完整的销量预测建模实验记录。里面有 RNN 序列模型rnn.py 与 rnn_v1/v2/v3 输出、GBDT 模型gbdtmodel_for_application.py、规则模型rule_v01、10 个 SQL 特征脚本和 11 份 CSV 提交结果。如果你正在做电商销量预测、用户购买意向预估这类任务最值得看的不是哪个模型 AUC 最高而是它的文件组织方式SKU_signal_creation_v2/v3/v4.sql、USER_SKU_signal_creation_v2_0201_0408.sql、rnn_v2_user_level_train_roc.png 这些命名背后是特征版本和模型版本被当作产品来管理。以提交文件看线上分数从 0.02069 一路提到 0.09512说明增益来自“特征 多模型融合”的组合迭代而非单点调参。2. 数据管道与特征工程从 SQL 聚合信号到 Python 特征拼接销量预测项目的第一个分水岭不是选 LSTM 还是 Transformer而是你能不能快速产出一份“某用户在某 SKU 上、某个时间窗口内”的行为特征表。这套源码里的 SQL 脚本正好展示了这类特征的建设顺序。2.1 基础动作表create_tbl_server.sql 与 train_action_xcreate_tbl_server.sql 负责创建平台底表后续所有特征都依赖这张动作表。表名 train_action_x 是一个典型的电商行为流水表包含 user_id、sku_id、action_type、action_time 等字段。以 Hive 风格建表为例CREATE TABLE IF NOT EXISTS train_action_x ( user_id BIGINT COMMENT 用户ID, sku_id BIGINT COMMENT 商品ID, action_type INT COMMENT 1浏览 2加购 3下单 4关注, action_time TIMESTAMP COMMENT 行为发生时间, dt STRING COMMENT 分区日期 ) PARTITIONED BY (dt STRING);实际操作中这套代码用 ${start_date} 和 ${end_date} 这类变量控制回看窗口作用是把过去 30 天或 60 天的行为切成不同快照。这里的关键点是预测某天之后是否购买训练标签和特征必须来自不同时间区间否则会出现泄漏。create_tbl_server_train_action_x_v2.sql 和 v3 版本的区别就在窗口定义上v3 通常加了 7 天静默过滤把无行为用户剔除减少负样本噪声。2.2 SKU 信号聚合SKU_signal_creation_v2/v3/v4.sql 的迭代逻辑SKU 级信号解决的是“这个商品本身热不热”的问题。SKU_signal_creation_v3.sql 的典型聚合逻辑如下INSERT OVERWRITE TABLE sku_signal_v3 SELECT sku_id, COUNT(DISTINCT user_id) AS uv, SUM(CASE WHEN action_type 1 THEN 1 ELSE 0 END) AS browse_cnt, SUM(CASE WHEN action_type 2 THEN 1 ELSE 0 END) AS cart_cnt, SUM(CASE WHEN action_type 3 THEN 1 ELSE 0 END) AS buy_cnt, COUNT(DISTINCT CASE WHEN action_type 3 THEN user_id END) AS buy_uv, DATEDIFF(MAX(action_time), MIN(action_time)) AS active_days FROM train_action_x WHERE dt ${start_date} AND dt ${end_date} GROUP BY sku_id;这里的 uv 是商品浏览人数buy_cnt 是下单次数buy_uv 是下单人数。active_days 用于刻画商品活跃周期如果一件商品 30 天内只有 1 天有行为那它更接近长尾商品后续建模权重应降低。SKU_signal_creation_v4 相比 v3 多了价格带、品类点击率等交叉特征能帮助 RNN 区分“低价高频”和“高价低频”两类不同时序模式。2.3 用户×SKU 交叉信号USER_SKU_signal_creation 的作用USER_SKU_signal_creation_v2_0201_0408.sql 这个文件名里的 0201_0408 是时间窗口区间代表 2 月 1 日到 4 月 8 日的用户商品交互信号。它是 RNN 模型最核心的输入因为销量预测不能只靠商品热度还要考虑用户和商品之间的关系强度。常见做法是在这个脚本里生成四类交叉特征SELECT user_id, sku_id, COUNT(*) AS interact_cnt, SUM(CASE WHEN action_type 3 THEN 1 ELSE 0 END) AS user_buy_cnt, AVG(CASE WHEN action_type 3 THEN action_time_diff ELSE NULL END) AS avg_buy_interval, MAX(action_time) AS last_action_time FROM user_sku_action_detailed GROUP BY user_id, sku_id;user_buy_cnt 表示该用户在这个 SKU 上买过几次last_action_time 离预测日越近用户当前意图越强。这里有一个容易踩的坑avg_buy_interval 只统计有购买行为的记录对没有购买历史的用户会被计算成 NULL合并时如果没有 fillna会直接吃掉一整行样本。2.4 Python 特征合并file_merging_master_for_application.pySQL 产出的是分表特征最终模型需要一张宽表。file_merging_master_for_application.py 解决的问题就是把 MASTER 表、SKU 信号、USER×SKU 信号合并成训练样本import pandas as pd def merge_features(data_date): master pd.read_csv(fmaster_{data_date}.csv) sku pd.read_csv(fsku_signal_{data_date}.csv) user_sku pd.read_csv(fuser_sku_signal_{data_date}.csv) # 先合并 SKU 级再合并用户级顺序不能反 df master.merge(sku, onsku_id, howleft) df df.merge(user_sku, on[user_id, sku_id], howleft) # 全 0 填充比删除行更安全 df.fillna(0, inplaceTrue) return dfmerge 顺序的差别在于数据量和唯一键约束master 是用户与 SKU 的笛卡尔候选集先和 SKU 聚合表合并会保持行数不变再和 user_sku 合并也是按主键关联。fillna(0) 对于计数类特征是合理的但对 last_action_time 这类时间特征填 0 会引入“1970 年”这种异常值更好的做法是把它转成距预测日的天数差让缺失值变成一个大数或 -1。源码里这块处理得比较务实直接用 0 填充跑通全流程后续优化空间也留在此处。3. RNN 序列模型rnn.py 里的 LSTM 销量预测实现处理完特征后进入模型层。rnn.py 和 rnn_v1/rnn_v2/rnn_v3 目录是这套源码的核心输出。销量预测本质上是时序问题一个商品过去 30 天的销量走势、一个用户对某商品的兴趣强度变化都存在时间依赖。我在实际项目中验证过如果只把特征堆给 XGBoost时间顺序信息会被树模型当作无序特征效果明显比不过“先序列编码再分类”的 RNN 结构。3.1 输入序列构造把特征表变成时间步RNN 的输入不是宽表而是三维张量[batch_size, seq_len, feature_dim]。源码中没有直接给出序列化代码但根据 run.py 的调用方式常见做法是import numpy as np def build_sequence(df, id_col, time_col, feature_cols, seq_len14): sequences [] for entity_id, group in df.groupby(id_col): group group.sort_values(time_col) feats group[feature_cols].values # 滑窗截断不足补零 pad_len seq_len - len(feats) if pad_len 0: feats np.vstack([np.zeros((pad_len, len(feature_cols))), feats]) sequences.append(feats[-seq_len:]) return np.array(sequences)这里 seq_len 选 14对应 14 个时间步。如果业务周期是 7 天一个循环14 天刚好覆盖两个周期。补零对时间步较短的商品是必要的否则 batch 内维度不一致无法训练。特征列可以选择 SKU 信号里的 browse_cnt、cart_cnt、buy_cnt 和 USER×SKU 信号里的 user_buy_cnt形成每个时间步的 4 维输入。3.2 网络结构Embedding LSTM 全连接rnn.py 里的模型定义可以这样理解import torch import torch.nn as nn class SalesRNN(nn.Module): def __init__(self, feature_dim, hidden_size64, num_layers2, dropout0.3): super().__init__() self.embed nn.Linear(feature_dim, hidden_size) self.lstm nn.LSTM( hidden_size, hidden_size, num_layers, batch_firstTrue, dropoutdropout ) self.classifier nn.Linear(hidden_size, 1) def forward(self, x): # x: (batch, seq_len, feature_dim) embedded torch.relu(self.embed(x)) out, (h_n, c_n) self.lstm(embedded) # 取最后一个时间步的隐藏状态而不是 h_n last_hidden out[:, -1, :] logits self.classifier(last_hidden) return logits.squeeze(-1)这里有一个容易忽略的细节out[:, -1, :]取的是每个序列最后一个时间步的输出而h_n是最后一层所有时间步的最终隐藏状态。在多层 LSTM 中两者维度含义不同。如果序列尾部是补零的取最后时间步会误导模型学到“零向量 → 负样本”的捷径所以源码里通常会配合序列掩码或者干脆只保留有行为的时间步。对于这个项目的数据规模直接用out[:, -1, :]也能跑出可提交的结果但验证集 ROC 会虚高一点需要警惕。3.3 训练超参与损失函数销量预测在竞品中通常被构造成二分类问题标签是“未来 7 天内该用户是否购买该 SKU”。rnn.py 训练循环的核心部分optimizer torch.optim.Adam(model.parameters(), lr1e-3, weight_decay1e-5) criterion nn.BCEWithLogitsLoss() epochs 30 batch_size 256 for epoch in range(epochs): model.train() total_loss 0.0 for batch_idx, (x_batch, y_batch) in enumerate(train_loader): optimizer.zero_grad() logits model(x_batch) loss criterion(logits, y_batch) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), max_norm5.0) optimizer.step() total_loss loss.item() if epoch % 5 0: val_auc evaluate(model, val_loader) print(fepoch {epoch}, loss {total_loss:.4f}, val_auc {val_auc:.4f})clip_grad_norm_在这里是必要的因为 LSTM 梯度容易爆炸max_norm 设为 5.0 是常见安全值。学习率 1e-3 配合 Adam 可以快速收敛但到了第 20 个 epoch 后验证指标会停滞说明欠拟合不是主要矛盾特征信息量才是。rnn_v1 到 rnn_v2 提升明显主要原因是将输入从单日的 4 维特征扩展到了多日滑窗的 8 维特征rnn_v3 又加入了注意力机制让模型对临近预测日的特征赋予更高权重。3.4 rnn_v1 / rnn_v2 / rnn_v3 版本对比版本关键改动验证方式提交分数范围rnn_v1基础 LSTM单层隐藏层 32仅 SKU 级 ROC0.02 - 0.04rnn_v2BiLSTM 两层隐藏层 64SKU 级 用户级 ROC0.03 - 0.05rnn_v3LSTM Attention 特征归一化SKU 级 train/test ROC0.05 - 0.09rnn_v2_user_level_train_roc.png 和 rnn_v2_user_level_test_roc.png 两张图对比能发现用户级验证集的 ROC 通常比 SKU 级低 2-3 个百分点这是正常的。用户级验证更严格因为它要求模型在“新用户”上也有泛化能力而 SKU 级容易受到热门商品的长尾效应影响。4. GBDT 与规则集成多模型评估与融合RNN 能捕捉序列依赖但它的输出对异常值很敏感。这套源码里还包含 gbdtmodel_for_application.py 和 rule_v01 两个辅助模型它们的作用不是替代 RNN而是提供不同视角的得分再用加权融合的方式稳定线上效果。4.1 GBDT 特征重要性评估gbdtmodel_for_application.pyGBDT 在这个项目里扮演两个角色第一做特征筛选找出哪些信号对销量预测贡献最大第二产出与 RNN 互补的分数用于融合。代码核心是 LightGBM 的二分类训练import lightgbm as lgb from sklearn.model_selection import train_test_split feature_cols [browse_cnt, cart_cnt, buy_cnt, buy_uv, avg_buy_interval] X train_df[feature_cols] y train_df[label] X_train, X_val, y_train, y_val train_test_split( X, y, test_size0.2, random_state2023 ) params { objective: binary, metric: auc, learning_rate: 0.05, num_leaves: 63, max_depth: 7, feature_fraction: 0.8, bagging_fraction: 0.8, verbose: -1, } model lgb.train( params, lgb.Dataset(X_train, y_train), num_boost_round500, valid_setslgb.Dataset(X_val, y_val) ) importance pd.DataFrame({ feature: feature_cols, gain: model.feature_importance(gain) }).sort_values(gain, ascendingFalse)gain表示特征被用于分裂时带来的平均信息增益比默认的 split 更能体现特征的实际贡献。运行后你会发现 buy_uv 往往排第一这符合直觉一个商品近期购买人数多未来被购买的概率就大。此时 RNN 序列特征的贡献可能排到第二或第三但两者并不冲突GBDT 看的是静态强度RNN 看的是趋势变化。4.2 规则模型兜底rule_user_id_score_v01.py 与 rule_sku_id_train_v01.py规则模型在源码里被放在 rule_v01 目录逻辑不复杂但非常实用。它的作用是在模型预测置信度低时用历史均值做平滑避免出现极端分数。def rule_score(row, sku_prior, user_prior): sku_score sku_prior.get(row[sku_id], 0.05) user_score user_prior.get(row[user_id], 0.02) # 交互信号作为信心加权 if row[interact_cnt] 5: weight 0.6 else: weight 0.3 return weight * row[gbdt_score] (1 - weight) * (0.7 * sku_score 0.3 * user_score)这里的 sku_prior 是每个 SKU 的历史购买率user_prior 是每个用户的历史购买率。交互次数越高说明模型对这条样本越有把握GBDT 分数的权重就越大交互次数少就更多依赖商品热度和用户活跃度兜底。这种规则在冷启动场景下非常有效能避免 RNN 在稀疏序列上输出 0.99 或 0.01 这种极端概率。4.3 用 ROC 曲线做模型选择和融合权重model_evaluation 目录里的 PNG 图片应该这样看train_roc 和 test_roc 两条曲线如果贴得很近说明模型没有过拟合如果 train AUC 接近 0.9 而 test 只有 0.6那就要查特征里是否包含预测日之后的信息。from sklearn.metrics import roc_auc_score, roc_curve # 融合前先看单模型 rn_auc roc_auc_score(y_true, rnn_prob) gbdt_auc roc_auc_score(y_true, gbdt_prob) rule_auc roc_auc_score(y_true, rule_prob) for weight in [0.3, 0.4, 0.5, 0.6, 0.7]: fused weight * rnn_prob (1 - weight) * gbdt_prob print(fweight{weight}, fused_auc{roc_auc_score(y_true, fused):.4f})实际调融合权重时我一般会在验证集上先粗选 0.5 附近的值再结合用户级 ROC 细分。源码里 submit_20170512_sw_0.00549.csv 这个文件分数很低说明某一版模型在验证集上调参过度提交后完全过拟合而 submit_20170518_sw_0.079.csv 和 submit_20170519_sw_0.09512.csv 逐步上升正是从单模型切到加权融合之后的节点。5. 产线化运行run.py 调用链路与验证技巧源码的入口文件 run.py 不是简单的模型训练脚本而是一个串联 SQL、Python、模型训练和提交文件的调度器。理解了它的执行顺序你就能把整套特征和模型流程复现出来。5.1 run.py 的执行顺序import subprocess import yaml with open(_config.yml, r) as f: config yaml.safe_load(f) def run_sql(sql_file): subprocess.run([ hive, -f, sql_file, -hivevar, fstart_date{config[start_date]}, -hivevar, fend_date{config[end_date]} ], checkTrue) def run_python(py_file): subprocess.run([python, py_file], checkTrue) if __name__ __main__: # 1. 建表与数据准备 run_sql(create_tbl_server.sql) # 2. 生成 SKU 级信号 run_sql(SKU_signal_creation_v3.sql) # 3. 生成用户×SKU级信号 run_sql(USER_SKU_signal_creation_v2_0201_0408.sql) # 4. 合并特征 run_python(file_merging_master_for_application.py) # 5. 训练 RNN 与 GBDT run_python(rnn.py) run_python(gbdtmodel_for_application.py) # 6. 融合并生成提交文件 run_python(model_master.py)_config.yml 里放的是窗口参数比如 start_date: 2017-02-01、end_date: 2017-04-08。每次迭代只需要改这个文件不需要改代码这是源码组织上比较聪明的一点。5.2 提交文件与线上分数对照为了快速定位哪次改动是有效的源码保存了多份提交结果命名格式是 submit_日期_作者_分数.csv。文件名分数可能的改动阶段submit_20170503_sw_0.02069.csv0.02069仅规则/SQL特征少submit_20170504_sw_0.03168.csv0.03168加入 RNN v1submit_20170512_sw_0.00549.csv0.00549过拟合特征泄漏submit_20170518_sw_0.079.csv0.07900RNN v3 GBDT 融合submit_20170519_sw_0.09512.csv0.09512调整融合权重 规则兜底发现分数下降时回退到上一个提交点重新检查新增特征的时间窗口即可。这种“以提交分数为基准”的管理方式比看训练 loss 要可靠得多因为线上分数才是业务真实指标。5.3 快速定位特征泄漏的验证技巧在跑完整套流程前建议先做一个小规模的泄漏检查。具体方法是只使用预测日之前的数据生成特征然后用训练好的模型预测一个已知结果的日期看 ROC 是否突然暴跌。# 泄漏检查将窗口整体前移 7 天 def validate_no_leak(feature_df, label_df, shift_days7): shifted feature_df.copy() shifted[feature_date] shifted[feature_date] - pd.Timedelta(daysshift_days) merged shifted.merge(label_df, on[user_id, sku_id, feature_date]) # 训练模型后 print AUC return roc_auc_score(merged[label], merged[pred_score])如果 shift 7 天后 AUC 显著下降超过 5%基本可以确定特征窗口和标签窗口有重叠。源码中 submit_20170512_sw_0.00549.csv 的低分版本多半就是这个问题随后通过拆分 0201_0408 和 0408_0415 两版特征文件把这个问题规避掉了。拿到这套源码后最快的上手方式是直接跑一遍 submit_20170519 的配置再逐一关闭 USER_SKU_signal 和 SKU_signal_v4观察提交分数的变化比从头读每个 SQL 脚本要高效得多。本文还有配套的精品资源点击获取
RELATED

相关推荐

Wagtail 文档模块(wagtail.documents)实战指南:模型、上传、存储与安全防护

Wagtail 文档模块(wagtail.documents)实战指南:模型、上传、存储与安全防护

Wagtail 文档模块(wagtail.documents)实战指南:模型、上传、存储与安全防护 【免费下载链接】wagtail A Django content management system focused on flexibility and user experience 项目地址: https://gitcode.com/GitHub_Trending/wa…

📅 2026/9/13 5:39:29
本科生降低AI生成内容检测率的8款工具与技巧

本科生降低AI生成内容检测率的8款工具与技巧

1. 项目概述:本科生如何有效降低AI生成内容检测率作为一名经历过论文查重和AI检测双重考验的高校导师,我发现越来越多本科生在学术写作中面临AI生成内容识别的新挑战。不同于传统的查重系统,Turnitin、万方等平台新增的AI检测功能能识别出GPT…

📅 2026/9/13 5:34:29
Archon 云部署排错实录:Docker Compose 中 bcrypt 哈希的 `$` 转义与表单认证(Form Auth)修复指南

Archon 云部署排错实录:Docker Compose 中 bcrypt 哈希的 `$` 转义与表单认证(Form Auth)修复指南

Archon 云部署排错实录:Docker Compose 中 bcrypt 哈希的 $ 转义与表单认证(Form Auth)修复指南 【免费下载链接】Archon The first open-source harness builder for AI coding. Make AI coding deterministic and repeatable. 项目地址: …

📅 2026/9/13 5:34:29
MORE NEWS

更多资讯

📰

端到端自动驾驶算法全解析:从原理到工程落地

“端到端”大概是这两年自动驾驶圈子里被讨论最多、也最容易吵起来的概念。一边是特斯拉FSD V12带来的震撼效果,一边是“黑盒”“不可控”的质疑声,行业里对它既有期待也有焦虑。我自己的感受是,很多人把端到端理解成“输入图像、输出方向盘转…

📰

从扫码到具身支付:机器狗如何打通AI交易闭环

支付宝把机器狗带到收银台前,这事值得展开说说。先说结论:支付宝这次推的“AI 付具身智能”,本质上不是给机器狗装了个付款码,而是把“用户授权支付”这件事,从手机屏幕迁移到了一个能跑、能看、能对话、能替你行动的智…

📰

C#/VB与三菱FX5U PLC通过SLMP协议实现以太网通讯交互

简介:这套源码采用C#与VB.NET编写,面向三菱FX5U可编程控制器的上位机通讯交互,专为需要将个人电脑与控制器对接的开发者打造,尤其适用于自动化设备的调试与数据采集场景。方案基于TCP协议,支持整数、双整数与浮点数的读…

📰

T型NPC光伏并网系统设计与仿真实践

1. T型NPC光伏并网系统概述 T型NPC(Neutral Point Clamped)拓扑是光伏并网系统中常用的三电平逆变器结构,相比传统两电平拓扑具有输出电压谐波小、开关损耗低等优势。这种拓扑通过在直流侧引入中性点钳位二极管,使得每相输出可产生…

📰

紧急车辆警报器声音数据集构建:采集、清洗与识别模型训练

简介:面向深度学习音频分类与紧急车辆识别任务,这份3秒波形音频数据集涵盖救护车、消防车警报声及纯交通噪声三个类别,每类各200段wav文件,并配套由每个音频转换得到的声谱图图像,适合用于训练车辆警报检测、环境声音分…

📰

Android代码混淆技术:R8核心机制与Gradle配置详解

1. Android混淆技术演进与R8核心机制2008年ProGuard作为首个Android官方推荐的代码混淆工具问世时,我还在用Eclipse开发Android 1.5应用。当时面对仅有的-keep选项和基础优化功能,开发者需要手动编写大量规则来保护关键代码。直到2018年Google I/O大会宣…

TODAY

今日更新

THIS WEEK

本周精选

THIS MONTH

本月热门

读完文章,想聊聊您的网站?

告诉我们您的行业与需求,资深顾问一对一梳理方案与报价,全程免费。

📞 💬