简介本资源为饿了么“骑士行为预估比赛”第一轮的完整参赛项目源码面向具备机器学习与深度学习基础的数据科学竞赛选手及智慧物流方向研究者用于解决骑手下一步行动预测这一序列建模问题。压缩包共66个文件约102MB以33个txt数据文件、18个ipynb实验笔记、5个py脚本及pickle模型文件为主涵盖数据整理、特征生成、训练集构造、GBDT配对与回归任务等完整流程模块。已有295人学习下载。读者可从中获取赛题数据组织方式、特征工程思路、LSTM等序列模型应用参考以及模型训练与评估脚本目录按feature、tools、model分层便于按阶段复现与二次开发适合作为智慧物流行为预测类竞赛的实战参考。1. 智慧物流赛题复盘饿了么骑手行为预估到底在预测什么外卖骑手在午高峰接到一单后下一秒是直奔取餐点、原地等餐还是顺路再捎一单这个看似简单的决策在 2020 年新冠疫情期间被饿了么搬上了算法赛场——「智慧物流新冠期间饿了么骑士行为预估比赛第一轮」要参赛者用骑手的历史轨迹、订单状态和时间戳预测骑手下一步动作。我拿到这份比赛项目源码包后第一反应不是急着跑模型而是先搞清楚它到底在预测什么是分类任务还是回归任务标签怎么定义特征里有没有泄漏这份资源适合三类人想入门时空行为预测的算法新手、需要一套完整比赛 baseline 的从业者、以及做即时配送调度想参考特征工程思路的工程师。它不是一个能直接上线的调度系统而是一份把「骑手行为」拆成可建模问题的实战样本价值在于流程完整、特征可解释、坑也真实。2. 拆开源码包数据字段、标签构造与 baseline 选型2.1 先看清数据长什么样再决定怎么建模这份源码包的核心是一份骑手行为日志常见字段包括骑手 ID、订单 ID、时间戳、经纬度、订单状态取餐/送达/空闲、配送区域等。不同版本字段名可能有差异但结构逻辑一致每一行是某个骑手在某个时刻的状态快照标签通常是「下一时刻的行为类别」。我一般会先做三件事看时间跨度、看骑手数量、看标签分布。时间跨度决定能不能做时序切分骑手数量决定要不要做分组统计标签分布决定用 accuracy 还是 F1。import pandas as pd df pd.read_csv(rider_behavior.csv) print(df.shape) print(df[action].value_counts(normalizeTrue)) # 标签分布判断是否类别不平衡 print(df[timestamp].min(), df[timestamp].max()) # 时间跨度 print(df[rider_id].nunique()) # 骑手数量这段代码不复杂但能避免后面白干。如果标签里某一类占比超过 80%直接上 accuracy 就是自欺欺人如果时间跨度只有几小时做滑动窗口就要小心样本重叠。参数上normalizeTrue看比例比看计数更直观nunique()比len(set())快。2.2 标签构造别把「未来信息」漏进特征骑手行为预估的标签一般有两种做法一是把下一时间窗口的行为作为类别二是把「是否在 N 分钟内接下一单」作为二分类。源码包里通常采用第一种按固定时间片如 5 分钟切分用当前片特征预测下一片行为。这里最大的坑是特征里混入了未来信息比如用了「订单完成时间」去预测「是否取餐」模型离线 AUC 很高上线就崩。# 按骑手分组后做时间偏移构造下一时刻标签 df df.sort_values([rider_id, timestamp]) df[next_action] df.groupby(rider_id)[action].shift(-1) df df.dropna(subset[next_action]) # 最后一条没有下一时刻丢掉shift(-1)是向上偏移取的是「下一行」的值配合groupby保证不跨骑手串行。dropna不能省否则最后一条的标签是 NaN训练时会报错或静默出错。常见做法是再用timestamp做一次窗口聚合把 5 分钟内的多条记录合并成一条减少噪声。2.3 baseline 选型LightGBM 比 LSTM 更适合第一轮很多新手一看到「时序预测」就想上 LSTM但这份比赛第一轮的数据量、特征维度、标签定义用 LightGBM 反而更稳。原因很直接特征以结构化字段为主时序依赖可以通过滑窗统计过去 10 分钟接单数、平均移动速度显式构造树模型对缺失值和异常值更鲁棒训练和调参成本也低。LSTM 不是不能用但需要更长的序列和更干净的输入第一轮容易翻车。import lightgbm as lgb from sklearn.model_selection import train_test_split features [hour, minute, lat, lng, speed, orders_last_10min] X_train, X_val, y_train, y_val train_test_split( df[features], df[next_action], test_size0.2, random_state42, stratifydf[next_action] ) model lgb.LGBMClassifier(n_estimators300, learning_rate0.05, num_leaves31) model.fit(X_train, y_train, eval_set[(X_val, y_val)], eval_metricmulti_logloss)stratify保证训练集和验证集标签比例一致避免某类样本全跑一边。num_leaves31是经验起点数据量大可以加到 63但别一上来就 255容易过拟合。eval_metric用多分类对数损失比 accuracy 更能反映概率质量。3. 特征工程实战从经纬度到骑手行为画像3.1 时空特征把经纬度变成「可学习的距离」原始经纬度直接丢给树模型效果通常一般因为模型很难从两个浮点数里自动学到「距离商圈多远」。我一般会构造三类派生特征距离最近取餐点的直线距离、距离最近送达点的距离、当前所在网格的订单密度。网格可以用 Geohash 或简单的经纬度分桶源码包里常见的是分桶法。import numpy as np # 经纬度分桶构造网格 ID df[lat_bin] (df[lat] * 100).astype(int) df[lng_bin] (df[lng] * 100).astype(int) df[grid] df[lat_bin].astype(str) _ df[lng_bin].astype(str) # 计算到取餐点的近似距离欧氏距离单位约 1 公里 df[dist_to_pickup] np.sqrt((df[lat] - df[pickup_lat])**2 (df[lng] - df[pickup_lng])**2) * 111乘 100 再取整相当于把约 1 公里精度作为网格边长太细会稀疏太粗会丢信息。乘 111 是把经纬度差转成公里数的粗略系数纬度方向准确经度方向在中纬度地区误差可接受。如果数据里没有取餐点坐标就用骑手历史接单点做聚类中心替代。3.2 时序滑窗过去 10 分钟比当前时刻更有信息量骑手行为有很强的惯性过去 10 分钟接了 3 单的人下一时刻继续接单的概率远高于空闲的人。滑窗统计是这类比赛最有效的特征之一常见做法是按骑手分组用rolling计算接单数、取消数、平均速度、移动距离。df df.sort_values([rider_id, timestamp]) df[orders_last_10min] df.groupby(rider_id)[order_id].transform( lambda x: x.rolling(10min, ondf.loc[x.index, timestamp]).count() )rolling(10min)是时间窗口不是行数窗口适合不规则采样的日志。transform保证返回长度和原表一致方便直接拼回特征矩阵。注意时间列必须是 datetime 类型否则窗口不生效。如果数据量大lambda会慢可以改用groupbyresample预聚合。3.3 类别特征处理骑手 ID 不能直接 one-hot骑手 ID、区域 ID 这类高基数类别特征直接 one-hot 会炸维度。LightGBM 支持直接传类别特征但需要先转成category类型如果要用逻辑回归或神经网络常见做法是目标编码或哈希编码。源码包里一般用 LightGBM 原生类别特征省事且效果不差。for col in [rider_id, grid, area_id]: df[col] df[col].astype(category) # LightGBM 训练时指定类别特征 model lgb.LGBMClassifier(n_estimators300, learning_rate0.05) model.fit(X_train, y_train, categorical_feature[rider_id, grid, area_id])astype(category)只是标记类型真正编码在 LightGBM 内部完成。如果换 XGBoost需要手动做目标编码且必须用交叉验证防止泄漏。类别特征不是越多越好骑手 ID 如果超过几千个建议先做频次过滤低频骑手归为「其他」。4. 避坑与排查离线高分上线崩的五个血泪经验4.1 现象验证集 F1 0.85测试集只有 0.5原因特征里混入了未来信息比如用了「订单完成时间」或「下一单接单时间」的统计量。解决把所有特征按时间戳排序逐列检查是否在预测时刻之后才产生。我一般会写一个时间边界检查函数任何特征的计算窗口右端点超过当前时刻就报警。4.2 现象模型训练报错「NaN label」原因shift(-1)后最后一条标签为空或者某些骑手只有一条记录。解决dropna(subset[next_action])之后再检查每个骑手的记录数少于 2 条的骑手直接过滤。别用fillna填标签那是自欺欺人。4.3 现象LightGBM 训练很慢内存爆掉原因类别特征基数太高或者滑窗特征用lambda逐组计算。解决先把骑手 ID 做频次过滤低频归并滑窗改用groupbyresample预聚合再 merge 回主表。数据量大时num_leaves从 31 降到 15n_estimators配合早停。4.4 现象验证集标签分布和训练集差很多原因train_test_split没加stratify或者按时间切分时没考虑类别随时间变化。解决分类任务优先用stratify如果要做时序验证用时间切分但检查两边分布差异大就做加权或重采样。4.5 现象预测结果全是多数类原因类别不平衡 模型没设class_weight。解决LightGBM 里设class_weightbalanced或者用scale_pos_weight二分类。多分类可以调objectivemulticlass配合class_weight但别过度加权否则少数类召回上去了精确率崩了。5. 进阶技巧用分组统计和早停把第一轮分数再抬一档第一轮比赛拼的不是模型多深而是特征多稳、验证多真。我后来养成一个习惯任何行为预测任务先跑一个「只用滑窗统计 LightGBM」的 baseline再逐步加特征每加一组就记录验证集 F1。这样能清楚知道哪组特征真正有用而不是一股脑全塞进去。# 分组统计按骑手和小时聚合构造行为画像 rider_hour_stat df.groupby([rider_id, hour]).agg( order_cnt(order_id, count), avg_speed(speed, mean), cancel_cnt(cancel_flag, sum) ).reset_index() df df.merge(rider_hour_stat, on[rider_id, hour], howleft)groupbyagg是构造画像特征的标准套路reset_index后 merge 回主表。注意hour要从时间戳里提取别用原始时间字符串。howleft保证主表不丢行缺失值留给 LightGBM 处理。早停是另一个容易被忽略的点。第一轮数据量不大n_estimators设 1000配合early_stopping_rounds50让模型自己决定什么时候停。model lgb.LGBMClassifier(n_estimators1000, learning_rate0.05, num_leaves31) model.fit( X_train, y_train, eval_set[(X_val, y_val)], eval_metricmulti_logloss, callbacks[lgb.early_stopping(50), lgb.log_evaluation(100)] )early_stopping(50)表示验证集指标 50 轮不提升就停log_evaluation(100)每 100 轮打印一次。这样既省时间又避免过拟合。我一般还会保存best_iteration_后面做特征重要性分析时用。验证方法上别只看一次train_test_split。我习惯跑 3 次不同random_state取 F1 均值和方差。方差大说明模型不稳优先检查特征泄漏和类别分布而不是继续调参。从那以后我每次做行为预测都强制先跑一遍「无滑窗特征」的 baseline再逐步加特征确认每一步都有正向收益才继续。希望帮到你。本文还有配套的精品资源点击获取
企业数字化 ERP 产品动态
相关推荐
PaddleSeg 全景分割工具包开发者指南:架构、数据编码与数据集定制全解析 人工智能计算机视觉预训练 【免费下载链接】PaddleSeg Easy-to-use image segmentation library with awesome pre-trained model zoo, supporting wide-range of practical tasks in Semantic Segmentation, Interactive Segmentation, Panoptic Segmentation, Image Matting,… · 2026/9/25 3:25:10
生产级知识库与Agent网关融合架构:混合检索与模型路由实战 1. 生产级知识库与 Agent 网关的整体设计思路1.1 为什么要把知识库和 Agent 网关放在一起做单独做一个 RAG 知识库,或者单独做一个 Agent 网关,这两件事在 Demo 阶段都不难。难的是把它们放到生产环境里,让它们协同工作,还要保证延… · 2026/9/25 3:25:10
aima-python 数据子模块更新指南:基于 git submodule 同步 aima-data 数据集仓库 人工智能机器学习深度学习 【免费下载链接】aima-python Python implementation of algorithms from Russell And Norvigs "Artificial Intelligence - A Modern Approach" 项目地址: https://gitcode.com/gh_mirrors/ai/aima-python 点击查看 免费下载 … · 2026/9/25 3:25:10
OpenShift Origin QuickStart 模板详解:应用骨架的构建原理、参数体系与自动同步机制 测试云原生质量保障 【免费下载链接】origin Conformance test suite for OpenShift 项目地址: https://gitcode.com/gh_mirrors/or/origin 点击查看 免费下载 本篇技术文章基于 examples/quickstarts/README.md 展开,系统讲解 OpenShift Origin 中 Qui… · 2026/9/25 3:57:03
React 360 资源缓存利器:深入解读 RefCountCache 引用计数缓存实现与应用 前端3D渲染 【免费下载链接】react-360 Create amazing 360 and VR content using React 项目地址: https://gitcode.com/gh_mirrors/re/react-360 点击查看 免费下载 导读
ref-count-cache 是 React 360 项目中的一个独立基础工具包,提供了一种以&quo… · 2026/9/25 3:56:57
免费给老 Mac 装上新版 macOS:OpenCore Legacy Patcher 三步完整走通 免费给老 Mac 装上新版 macOS:OpenCore Legacy Patcher 三步完整走通 【免费下载链接】OpenCore-Legacy-Patcher Experience macOS just like before 项目地址: https://gitcode.com/GitHub_Trending/op/OpenCore-Legacy-Patcher
OpenCore Legacy Patcher&am… · 2026/9/25 3:56:57
TEN Framework 中的 PIL 演示 Python 扩展:基于 VideoFrame 的图像处理实战 人工智能AI Agent多模态语音AI 应用 【免费下载链接】ten-framework Open-source framework for conversational voice AI agents 项目地址: https://gitcode.com/TEN-framework/ten-framework 点击查看 免费下载 导读
本文围绕 pil_demo_python 扩展,… · 2026/9/25 3:56:57
创维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