概述
在 Uber,我们运用策略算法来连接司机和乘客。算法在全球上线之前,为了最优化用户体验,Uber 需要完全测试和评估算法效果。
使产品测试更安全、更容易,Uber 建立了一个仿真平台,用来仿真司机和骑手在真实世界中的场景。利用一个基于离散事件的模拟器,该平台允许工程师和数据科学家快速地构建原型,并且在无风险环境下,测试新的特征和猜想。
模拟器利用历史数据来执行两个重要的仿真组件:Marketplace 服务和用户行为模型。
- Marketplace 服务利用该平台来进行调度决策。
- 用户行为模型使用仿真内容来决定骑手和司机的决定,比如 撤单和导航选择。
为了让模型部署和训练更容易和准确,Uber 仿真平台团队构建了用于无缝集成模型训练、模型服务的机器学习框架。出于对准确性和真实性的要求,ML 在用户行为预测中扮演着关键先生的角色。实际上,大多数用户行为的仿真都是基于模型匿名化训练的历史聚合结果。仿真也回过头来反哺 ML 模型的开发和改进。这一切使得新模型在上线之前,能在仿真平台快速迭代。
我们团队设计了一个 ML 模型训练框架来帮助用户在仿真平台上快速构建和部署模型。
仿真平台机器学习框架
在仿真平台中,机器学习处于一系列重要功能迭代的核心地位。在介绍 ML 框架之前,模型开发、训练和部署通常面临临时、难以复用的问题。比如,ML 开发者在模拟器中直接实现 ML 模型并且在模拟器运行时训练模型。
一次性的快餐式方案随着多模型多版本的部署马上变得越来越复杂。模拟器很难为不同模型训练维护大量内存和 CPU 资源。在这些场景中,为每个模型从头到尾自定义训练和服务代码是不现实的。
仿真团队着手为 ML 训练和服务构建一个单一、高效、可复用框架。该框架提供一系列开源和自研组件。它分为四个层次:
- 包含 Python API 和模块的 ML 库
- 自动化训练的管道来训练模型并且以二进制形式存储
- 管理模型元数据的后端服务
- 在模拟器中可以加载模型的中心化模块
在仿真 ML 框架训练的工作流中,引入 Python ML 库,获取并处理原始数据,基于历史时间序列数据自动训练模型。一旦管道完成训练,它发送元数据到仿真数据库并且记录检查点,然后保存二进制文件到本地。之后,仿真后端服务启动模拟器,模拟器中的模型实例化过程会调用 Python ML 库和本地的检查点。
图一和图二 展示了一个机器学习框架的训练和服务工作流:
图一 自动化训练管道 (中) 使用 Spark(上)从 Hive 获取原始数据,同时仿真机器学习模型 (左) 保存数据到存储服务(右)和仿真数据库 (下) 中.
图二 创建一个仿真程序,首先要发起仿真服务请求 (左上). 然后,它会取到后端服务的模型元信息作为输入到数据库。数据库接着从存储服务中恢复检查点到本地磁盘。这些检查点包含了模拟器中的仿真机器学习模型(中上)。
在这个框架中,我们将训练和服务工作流解耦。这个改变为需要持续改进模型的模型开发者提供了灵活性。在这个系统中,如果开发者想要改变用户行为模式,唯一需要做的就是更新机器学习模型的实现。框架会自动触发训练的流程,然后在所有模拟器中分发最新的模型。
通过去掉在仿真中的模型训练工作任务,我们简化了复杂的仿真器,显著提升了内存和 CPU 的使用效率。这个改变也提升了模拟器的吞吐量。总之,一系列的简化节省了硬件资源,提升了系统效率。
仿真平台团队使用这个框架以一个标准化的方式来集成许多用户行为和其他机器学习模型到仿真平台。
供给活动模型如何改善市场模拟
正如最近关于共享出行仿真的研究表明,司机活动是仿真精度和真实度的主要因素。在 Uber 的市场模拟平台中,实验性算法带来与实际相左的匹配结果导致司机活动和真实的历史数据的表现不同。比如,司机在仿真中可能匹配到他们在现实中差异很大的乘客。在这个情况下,模拟器不能简单地用历史数据来模拟路径,距离以及下车地点。为了亡羊补牢,我们知道需要建立一个能够精确刻画司机活动行为的模型。在合适的活动模型下,可以改进乘客行为模型(比如乘客取消订单模型),减少匹配和定价算法中的噪声,为市场规则保驾护航。
准确仿真每一个司机活动是一个充满挑战的事情,因为仿真世界基于有限的历史数据,也缺乏影响用户行为的诸多因子,比如交通信息,天气,地理数据等。
幸运的是,对于市场仿真算法,单个司机活动不能显著影响算法结果。这些算法主要受到聚合后的司机分布而不是单个的司机动作的影响,尤其是在司乘匹配和定价算法上。处于这个原因,与其做到完美的个体仿真,不如关注模型如何能够精确仿真司机行为的分布。
为了在仿真世界中实现这一目标,我们将线上司机行为分为两阶段,如图三所示,在 Uber 市场中更好地预测了用户需求:
图三 司机活动混合模型由司机请求仿真行动开始到一系列打 ” 是 / 否 ” 的分支选择后到达终点,最后发送司机信息给路径规划引擎,预估行驶速度,模拟司机在路径上的移动行为。
我们实现了一个基于规则模型的在线司机。当一个仿真司机接单,模型开始规划路线并让司机沿着路线到预定地点。
仿真离线司机分布是更苦难的。像前面提到的,仿真世界很难精确复现历史司机行为。出于此,我们使用机器学习模型配合历史数据来预测聚合后的离线司机活动。使用线上算法,模型仿真的空闲司机分布与历史数据是尽可能的接近了。我们训练了一个基于树的随机模型来完成离线司机分布模拟。见图 4,5,6,如下展示了模型如何运转:
图四 我们的随机模型是一个决策树结构,以 “ 是否为高峰期司机 ” 作为第一个判断条件开始,经过一系列 ifelse 判断到达叶子节点。
如图四所示,当仿真想要预测离线司机分布,系统通过待服务司机的信息 (地点、时间等) 获取树模型的相关叶子节点。叶子节点包含了用于预测司机未来行为的转移矩阵。在仿真平台上,我们用自研开源的六边形分层空间索引 H3 将地球表面的空间划分为一致的地理单元。通过一致地理单元划分,我们定义了转移矩阵,如图五:
图五 概率表(三行三列,表示地球上不同网格之间的转移概率)
转移矩阵中的值描述了给定当前司机,从网格 Y 到网格 X 的转移概率。
通过此类转移矩阵,仿真可以预测司机最可能移动到哪一个网格。之后,仿真随机选择一个终点。图六,展示了这个过程:
图六 流程图从叶子节点开始,这里用一个地图来解释仿真平台如何通过转移概率矩阵获取精密地获取司机的移动行动。这就是用来预测司机终点的决策树随机模型。
一旦模拟器预测了司机的终点,它还会预估路线和速度,然后移动司机到终点。当司机去他们的目的地时,一个在在线和离线司机的关键区别就是司机是否改变他们的状态(打样或者被调配)。
使用司机行为混合模型,仿真平台精确地获取了司机在真实世界中的近似分布。我们对比了算法实际的效果差异。图七,显示高峰期的分布对比:
图七 左侧高亮区域是 Ground Truth, 右侧未仿真结果。由于精度很高,所以从地图上看非常一致。
参考资料
- https://eng.uber.com/simulate…
原文作者:Haoyang Chen, Wei Wang 译者:Harry Zhu 英文原文地址:
https://eng.uber.com/simulate…作为分享主义者 (sharism),本人所有互联网发布的图文均遵从 CC 版权,转载请保留作者信息并注明作者 Harry Zhu 的 FinanceR 专栏:https://segmentfault.com/blog…,如果涉及源代码请注明 GitHub 地址:https://github.com/harryprince。微信号: harryzhustudio
商业使用请联系作者。