ARTICLE · INTELLIGENCE

战地情报 · 详情页

来自尧图项目组的一线实战观察与深度解析

TTDM模型解析:用旅行时间差异驱动下一位置预测

TTDM模型解析:用旅行时间差异驱动下一位置预测

1. 这个模型到底在解决什么问题

1.1 下一位置预测的行业现状与痛点

做位置数据相关工作的朋友应该都有同感,下一位置预测(Next Location Prediction)这个方向看起来简单,实际做起来水很深。它要回答的问题很直白:给定一个人过去一段时间的位置轨迹,预测他接下来最可能出现在哪里。

这个任务在行业里的应用面其实比大多数人想象中广得多。个性化推荐系统需要预判用户下一步会去哪个商圈,智能配送平台要提前把运力调度到需求即将爆发的位置,城市管理部门想根据人群流动趋势做公共资源投放,甚至移动广告投放都想抢在用户到达某地之前把推送送到他屏幕上。十年前做这个方向的主流思路是马尔可夫链和频繁序列挖掘,最近几年基本被循环神经网络、注意力机制、图神经网络等深度模型主导,各路论文刷精度刷得飞起。

但落地的时候你会发现一个尴尬的事实:很多模型在公开数据集上报的准确率很漂亮,换到真实业务数据上就崩。为什么崩?一个核心原因是,绝大多数模型把位置预测当成纯序列建模问题,只看“用户上一次去了哪、上上次去了哪”,却忽略了一个极其关键的信息——用户在两个位置之间到底花了多长时间。而TTDM这个模型,全称Travel Time Difference Model,旅行时间差异模型,恰恰把“时间差”这个维度提到了核心位置,用一套不同的思路重新解构了下一位置预测问题。

我最初看到这个标题的时候,第一反应是它可能只是在RNN输入里多拼了一个时间间隔特征。真把方法读进去之后发现完全不是这样,它是在特征构造、候选集生成、模型结构三个层面上都围绕“时间差”做文章。这篇博文就围绕这个模型的核心设计思路、特征体系、实操细节和踩坑记录展开。

1.2 TTDM的切入点:时间差背后藏着行为语义

先想想一个很常见的场景。某位用户的轨迹数据大致是:写字楼(9:00-12:00)、附近餐厅(12:00-13:00)、写字楼(13:00-18:00)、健身房(19:00-21:00)、住宅小区(21:30-次日8:30)。

如果用传统的序列模型看,这条轨迹就是一个地点标签序列,模型学到的是“写字楼后面常跟餐厅、餐厅后面常跟写字楼”这类转移规律。但仅看序列顺序,信息损失非常严重。从写字楼到餐厅的转移耗时可能只有几百秒,从餐厅回到写字楼也是几十米的路程,但从健身房回家这个转移却可能跨越半个城区,耗时四五十分钟。这两类转移在序列层面都只是“上一个地点到下一个地点”的一次跳转,数学模型上几乎无法区分。

TTDM的思路是,把转移时间差异当作一个强语义特征来用。说白了就是:不同地点之间的旅行时间本身蕴含了地点的功能属性、空间关系、用户活动模式,把这些差异建模进去,模型才能真正理解“一次转移”背后是午休就近吃饭,还是下班后专程去健身。

更关键的是“差异”这个词。模型不是简单地使用绝对旅行时间,而是对比实际旅行时间和某种参考值之间的差。比如从某个地点的平均停留时长、从一个区域到另一个区域的期望通勤时间,实际值偏离期望值越多,说明这次转移背后可能伴随特殊的意图或异常情况,这些信号对预测下一步位置往往比单纯的顺序信号更有判别力。

这个视角在行业里并不新鲜,位置数据挖掘的老手都会在特征工程里加入时间相关的字段,但把它系统化地建模成一个完整预测框架的,确实不多见。TTDM的价值在于把零散的经验整合成了可复用的方法论。

2. 为什么“时间差”比“纯顺序”更值钱

2.1 传统序列建模的三个盲区

要理解TTDM的设计取舍,得先看看现有方法到底漏掉了什么。我拿自己做过的实验数据来说明。

第一个盲区是停留时长被完全忽略。一个人的行为节奏是有强周期性的,工作日午后在办公室附近餐厅出现的概率极高,深夜出现在公司附近的概率趋近于零。但纯序列模型如果不注入时间戳信息,就完全意识不到“现在是几点”。它只能看到地点标签组成的链条,而链条本身不携带任何钟表信息。

第二个盲区是转移耗时与空间距离的关系被丢弃。用户从家到公司可能跨越很远的物理距离,而从办公室到同楼层的会议室几乎只隔几米。序列模型处理这两种转移时一视同仁,这等于主动扔掉了一大批高质量的空间约束。真实场景里,一个用户不可能在五分钟之内从城市A端跑到B端,这种物理约束本身就是天然的候选集过滤器。

第三个盲区是用户之间、不同时段之间的行为差异无法体现。工作日中午白领们的轨迹高度相似,但到了周末每个人就散落到完全不同的活动空间。平均转移时间、停留时长分布都随上下文剧烈变化,静态的模型很难捕捉这种动态性。

TTDM通过构造旅行时间差异特征,把上述三个盲区一次性补上了。它不是完全抛弃序列信息,而是在序列之上叠加了一个物理世界的时间约束层。

2.2 时间差背后的行为学解释

为什么时间差特征有判别力?从行为学角度看,人的活动安排通常由一系列“锚点”驱动。上下班打卡是硬锚点,赶高铁飞机是硬锚点,和朋友约饭是软锚点。硬锚点对时间的约束极强,用户会精确规划出发时间;软锚点则比较灵活,前后会有一两个小时的漂移区间。

这些锚点直接反映在旅行时间差异上。举个例子,同一个用户,工作日早上从家出发到公司,记录到的转移时间通常稳定在30分钟左右波动很小。周末从家出发去商场,可能上午十点出门也可能下午三点出门,但转移时间同样稳定在20分钟左右,因为用户对自己熟悉的路线有稳定的时间预期。

更有意思的是跨地点的时间差。假设用户上午十点从会展中心出来,下一步有两个候选:回公司、去机场。从会展中心到公司的历史平均转移时间是40分钟,到机场是60分钟。如果此刻用户的实际可用时间只有50分钟,那么他下一步去公司的概率就显著高于去机场。这种物理时间约束带来的概率差异,是纯序列模型完全无法表达的。

TTDM做的事情就是把这类约束显式化为数值特征,让模型在打分的时候能直接利用上。它在数学上等价于给位置转移的概率估计增加了一个时间上下文条件,但实现方式比贝叶斯网络之类的复杂方法简洁得多。

2.3 和主流方案放一起看

我拿几种典型方法和TTDM做了个横向对比,感受会更直观:

方法类型代表思路对时间信息的利用程度主要短板
一阶/高阶马尔可夫链直接统计转移频次仅通过分段划分隐式使用状态空间爆炸,泛化能力弱
循环神经网络/LSTM对位置序列编码可拼接时间戳但无专门建模长序列遗忘,时间语义弱
注意力机制方法对历史位置加权聚合仅捕捉相对位置关系难以建模绝对时间约束
图神经网络方法地点作为图节点建模几乎没有时间概念时间动态性严重缺失
TTDM时间差特征+序列编码联合建模时间差贯穿特征、候选、打分全流程对冷启动用户表现依赖历史数据量

从表格能看出来,大部分深度模型本质上还是在玩空间模式,TTDM更像是把时间维度从“附带字段”提升到了“一等公民”的位置。它不跟你拼网络结构有多深多奇,而是换了一个角度重新审视这个问题。

3. 核心细节解析:特征构造与模型结构

3.1 特征体系:三个层次的时间差信号

TTDM的特征体系是整个模型的精髓所在,它的特征并不复杂,但每一条都围绕时间差展开。我拆成三个层次来看。

第一层是点级特征,也就是单个停留点的内在属性。一个停留点包含到达时间、离开时间、停留时长。从这三个原始值能衍生出大量特征:停留时长是否偏离该用户在该类地点上的历史平均驻留时间,到达时间是否落在该地点类型的典型到访时段内,当前时刻是工作日还是周末、是早高峰还是午休。这一层特征解决的是“这个地点对当前用户来说是不是一个符合常规的访问”。

第二层是转移级特征,也就是两个相邻停留点之间那条边的属性。核心就是旅行时间差异:实际转移时间减去同一起点终点对的历史平均转移时间,得到一个差值。这个差值越接近零,说明这次转移越常规,越偏离则意味着用户在赶时间、绕路或者碰上了异常交通。这一层特征解决的是“这次转移是不是一次常规移动”。

第三层是对比级特征,也是TTDM名字中Difference的直接体现。给定当前停留点和候选下一个地点,模型会计算从当前点到候选点的期望转移时间,再对比用户历史轨迹中所有从当前点出发的转移时间统计量,获得候选点之间的相对时间优势。举例来说,用户当前在体育馆,候选点有家和餐厅,家方向的历史平均转移时间是25分钟,餐厅方向是15分钟。这个10分钟的时间差就是一个强有力的排序特征。

我自己的实操经验是,第三层特征对最终精度的提升幅度最大,前两个层次更偏向“数据清洗和补全”的性质,对比级特征才是真正的杀手锏,它直接刻画了多个候选之间的相对竞争力。

3.2 模型主干:序列编码加候选集打分

特征工程做扎实之后,模型结构其实不需要太花哨。TTDM的典型实现是一个双塔结构加序列编码器,我拆开来说。

序列编码器负责处理历史轨迹。每个停留点经过嵌入层映射成向量,然后在向量上拼接该点的点级特征向量。这里有个关键设计,位置嵌入和时间特征不直接相加,而是分别过两个全连接层后在通道维度拼接,目的是避免数值尺度差异大导致的时间特征被位置嵌入淹没。

编码器主体可以用Transformer层也可以用双向LSTM,实际效果差异不大,但Transformer的并行训练速度优势明显。编码器输出一个固定维度的上下文向量,代表用户当前的行为状态。

候选集打分塔负责给候选位置打分。对于每个候选地点,模型会提取三类特征:候选点和当前点的空间距离及时长估算、候选点的对比级时间差特征、候选点自身的功能属性特征。这些特征经过一个多层感知机后,和序列编码器的输出向量做点积或拼接,最终输出一个标量分数。

训练的时候用负采样构造负样本,正样本是真实的下一个位置,负样本是在候选集里随机抽出来的非真实位置。每抽搐若干负样本与一个正样本配对,使用Pairwise排序损失进行优化。这里要注意的是,负样本的采样不能完全随机,否则模型学到的只是“正样本概率高于随机概率”而已,应该优先选择那些时间差特征上与正样本接近的迷惑性地点做负样本,这样训练出来的模型区分能力会更强。

3.3 训练目标和损失设计

我特别想聊一下损失函数的设计细节。原始论文里用的是带Margin的Hinge Loss,公式看起来并不复杂,但如果把Margin设成固定值,训练初期模型输出分数普遍偏低的时候会导致收敛极慢。实际工程里更推荐用它和交叉熵损失的加权组合。

具体操作是,每个训练批次里的正样本和负样本放在一起,先计算Softmax交叉熵损失,再把正样本分数与负样本分数的差值纳入Hinge Loss,两个损失按权重相加。交叉熵负责让模型“大致分清正负”,Hinge Loss负责细化排序边界。实测下来,这个组合比单一损失稳定,尤其适合候选集规模较大的场景。

还有一个非常容易踩的坑是样本权重的设置。下一位置预测的数据天然存在严重的头部聚集现象,高频地点占了大多数样本。如果不做任何处理,模型会倾向于输出那些高频热门地点,这会让评估指标虚高,但实际业务价值很有限。建议在损失函数里按样本逆频加权,也就是给低频转移更高的权重,或者对高频地点做欠采样,两者结合效果更理想。

4. 实操过程:从数据到评估的全流程

4.1 数据预处理:轨迹切分和停留点识别

TTDM这类模型对数据质量的要求比传统序列模型高得多,因为时间差特征完全依赖精确的到达和离开时间。我处理过的很多原始GPS数据其实噪声很大,定位点每隔几秒采样一次,信号漂移、设备关机、室内丢星的情况无处不在。如果不做清洗,算出来的旅行时间差异特征基本是垃圾进垃圾出。

第一步要做的就是把原始GPS轨迹切分成停留点序列。常用的思路是:如果一个定位点与上一个有效点的距离小于设定阈值(比如200米),并且持续时长超过最短停留阈值(比如5分钟),就认为用户在这个区域发生了停留。把连续满足条件的点聚成一个停留点,取中心坐标作为位置代表,取首尾时间戳作为到达和离开时间。

这里要特别小心短时抖动问题。用户在同一个商场里从一楼走到三楼,GPS坐标可能在200米范围内缓慢漂移,如果只按距离阈值判断,可能被错误地切成多个停留点。比较有效的做法是用速度特征辅助判断,当瞬时速度持续低于某个阈值且坐标漂移呈现随机游走特征时,才判定为停留状态。

停靠点聚类的时候,我建议用基于密度的聚类算法对停留坐标做二次聚合,避免同一地点被切分到多个停留簇。聚类半径要根据业务场景调整,在城市中心区域建议50到100米,郊区或园区可以放到150米甚至更大。

4.2 特征工程的关键实现

按我之前说的三级特征体系,具体落地时会有很多细节。停留时长偏离度的计算要按用户分桶归一化,比如把每个用户的所有停留时长按对数变换后做z-score标准化。之所以用对数变换,是因为停留时长的分布极度右偏,有大量一两分钟的短暂停留,也有一整晚七八个小时的长时间停留,直接用原始数值会导致模型被极端值带偏。

转移时间差异特征的计算是最核心也是实现最复杂的部分。要得到“从A点到B点的历史平均转移时间”,必须预先建立一个地点对之间的时间统计表。这个表的数据来源有两个:一个是当前数据集里所有用户的历史轨迹,另一个可以借助地图导航API补充估算。前者有真实行为数据但覆盖度有限,后者覆盖全量地点对但有估算偏差,我实践下来两者融合效果最好,覆盖度不够的地点对用导航估算值兜底。

权重上有个小技巧,估算值拼进模型的时候乘一个0到1之间的置信度系数,这个系数可以简单取为该地点对在历史数据中出现的频次经过Sigmoid映射之后的数值。这个置信度系数作为额外特征输入模型,既能缓解数据稀疏问题,又能让模型学会在数据不可靠时自动降低时间差特征的权重,效果非常显著。

对比级时间差特征则需要逐候选点计算。每次生成候选集后,对每个候选点计算当前点到候选点的期望转移时间,再减参考时间,得到相对差值。预测阶段的计算开销主要也集中在这里,所以工程上要对候选集做两阶段筛选:先用规则快速过滤掉明显不合理的候选点(物理距离过远、当前时段不可能前往等),再用精细特征做排序。

4.3 候选集生成策略

候选集质量基本决定了一个模型的上限,TTDM也不例外。我见过有人直接在全部地点上做打分预测,既慢又不准,因为绝大多数地点在特定时刻的概率趋近于零,硬算只是在增加噪声。

合理的第一层候选集生成策略是时间衰减加空间约束。以当前点为圆心,画一个半径1到5公里不等的候选圈,圈内所有历史出现过的地点作为候选。圈径大小可以根据用户的移动速度动态调整,步行状态候选圈半径可以小到800米,驾车状态则放大到整个城区的尺度。然后把当前时间是否匹配候选地点类型考虑进去,比如深夜时段几乎所有商场和办公类地点都可以从候选集中剔除。

第二层再用个性化偏好校准,对每个用户维护一个历史访问频率表,把用户从未或者极少访问的地点类型降权。比如某用户过去三个月从没在晚上去过电影院,那电影院类候选点即使空间上很近,也应该排在比较靠后的位置。

如果数据集里有用户的常驻地和常用通勤路径,还可以把这些信息作为先验加入候选集,对预测经常往返于固定几点的用户收益特别大。

4.4 训练配置与超参数设置

我在复现TTDM类模型时用过的比较稳定的配置向大家公开一下:

参数推荐值说明
嵌入维度64或128地点数超过10万时建议128,否则64足够
Transformer层数2到3更深的层在位置预测任务上没有显著收益
注意力头数4或8按嵌入维度取适当比例
Dropout0.2防止时间特征层过拟合,尤其是数据量小时
负样本数20到50真实业务数据20够用,公开数据集建议50
学习率1e-3配合预热预热步数建议占总步数的5%
批次大小256到512过小会导致时间差特征的batch内统计不稳定
序列长度20到50个停留点超过50步的历史对预测当前一步贡献极小

训练过程需要特别注意一个问题是训练集和测试集的用户隔离。同一用户的轨迹片段如果同时出现在训练集和测试集里,模型相当于见过了用户的全局行为模式,评估结果会严重虚高。正确做法是按用户划分数据集,保证一个用户的所有数据都只在训练集或测试集中出现一次,绝不做跨集合的数据混合。

4.5 评估指标怎么选才不会骗自己

下一位置预测领域最常用的评估指标是Top-1准确率和Top-K命中率。Top-1就是预测概率最高的那个位置是否等于真实位置,Top-5命中率则是看真实位置是否落在概率最高的前五个候选里。

光看这两个指标是不够的。如果候选集本身很小(比如只有二十个候选),随机猜测的基线就已经有百分之五的Top-1准确率了,模型做到百分之十看起来不痛不痒。所以评估时一定要设置一个合理的随机基线,我习惯用按历史频率加权随机预测作为下限参考,模型好坏的判断应该看它比这个基线高了多少个百分点。

另一个值得关注的指标是平均倒数排名MRR,它衡量的是真实位置在所有候选中的平均排名倒数。MRR对排序的中间区域更敏感,能反映模型距离“正确答案排第二”和“正确答案排第二十”之间的差距,比只看Top-1更能体现模型对候选集的整体排序能力。

时间一致性验证是我个人比较强调的一个额外检查项。预测结果的评估还要按时间段拆分来看,工作日和周末分别测试,模型在工作日频繁到访点上的表现通常远好于周末的随机活动场景,如果发现某个时段表现格外差,往往意味着该时段的时间差特征统计不充分。

5. 常见问题与排查技巧实录

5.1 时间差特征稀疏,统计量覆盖不足

实操中最先撞见的问题就是地点对之间的历史平均转移时间缺失。一个新用户可能只产生了几十条轨迹,覆盖到的地点对非常有限,大量候选点之间根本找不到历史统计量。

应对办法就是导航估算兜底加置信度加权,这一套我前面提过。再补充一个可选的优化方向:对缺失严重的地点对,用区域级别的平均转移时间做中间层。比如具体地点之间的时间差查不到,就退一步用“用户当前所在商圈到候选点所在商圈”的平均通勤时间差来替代,粒度粗一些但至少比完全空缺强得多。这个多粒度回退方案在工程中极易实现,我用下来能有效降低冷启动场景下的预测崩溃率。

5.2 冷启动用户怎么办

冷启动是位置预测的老大难问题。新用户没有任何历史数据,点级特征和转移级特征全部算不出来。

纯靠TTDM在冷启动场景下确实乏力,所以我的建议是这个阶段不要和深度模型死磕。冷启动用户直接用热门地点优先加简单规则处理,比如预测其所在地附近的商圈、车站、大型公共设施。等用户积累了一定量的轨迹数据(通常一个星期左右)再切到TTDM完整模型,效果会顺滑得多。

如果在业务上必须从第一秒就开始用模型预测,可以在训练时对特征缺失值做特殊的掩码处理。具体做法是,把时间差特征的缺失标志作为一个布尔特征喂进模型,让模型自己学会在缺失时依赖其他特征,而不是在数据入口直接丢弃样本。这个技巧拯救了大量早期数据不足的线上请求。

5.3 数据泄漏的常见隐患

我见过不止一次因为数据泄漏导致模型在测试集上刷出奇迹般高分,上线之后算法效果折半的事故。在时间序列相关的特征里,泄漏点通常藏在特征计算和样本划分这两个环节。

特征计算阶段的泄漏典型情况是:用测试时间段内的数据去计算地点对的历史平均转移时间,再把这个统计量当作训练特征喂给模型。解决方法是为每一条样本只使用其时间戳之前的历史数据计算统计特征,工程上需要用滑动窗口异步计算。

样本划分阶段的泄漏典型情况是连续时间的轨迹被切到不同集合。例如用户某天中午十二点在商场附近,下午两点在办公室,由于轨迹点密集采样,相同半小时内切出的样本可能同时落在训练集和测试集里。正确的做法是按用户的连续轨迹片段切分,把同一用户同一天的数据尽量放在同一个集合内。

5.4 工程化部署上的注意事项

离线实验效果不错不等于上线就能用。TTDM在在线推理阶段最大的开销是逐候选点计算时间差特征,候选集一放大,特征计算就变成延迟瓶颈。

常用的工程优化手段有三个方向。一是特征预计算,地点对之间的统计时间表可以离线全部算好并加载进内存,在线只做查表,不做实时计算。二是候选集两阶段筛选,先用纯规则的轻量过滤器把候选点从几万缩到几百,再进入模型做排序打分。三是特征计算结果的缓存,同一用户同一个当前点下的候选点特征,在一段时间内可以复用,不需要每次请求都重新计算。

模型存储量的问题也不可忽视。如果地点数量很大,嵌入矩阵可能占据几十GB内存,这时候要用乘积量化等向量压缩方案来降低内存占用,换来的精度损失通常很小。

5.5 高频场景下的预测倾向

还有一个坑很隐蔽,就是高频地点主导预测结果。写字楼和白领用户之间天然有强关联,但一个人不可能一天到晚都待在写字楼。模型一旦把预测倾向过分集中到用户历史上去得最多的地方,短期指标会表现良好,但长期看用户会感到推荐越来越无趣。

应对方式是在损失函数中加入正则项,让预测概率分布在候选集上不要过于集中,或者对高频地点的预测分数乘以一个轻微衰减系数。衰减系数的取值需要反复调优,压太狠会导致Top-1准确率明显下降,压太轻又拉不开差异化推荐的距离。

6. 一些实操后的真实体会

TTDM这套方法真正让我佩服的地方,不是模型结构本身有多惊艳,而是把物理世界的常识重新放回到了预测算法里。人们常说深度学习模型就是黑盒,但我个人实践下来的感受是,如果你能在特征入口把人类对世界的理解注入进去,模型输出的稳定性和可解释性会同时上一个台阶。旅行时间差异就是一个绝佳的例子,它既不需要复杂模型结构,又天然带有行为语义,普通从业者完全有能力复现并改进。

如果你正准备入手这个方向,我的建议是从小数据集起步,先把停留点识别和统计特征计算做到位,再去调模型结构。有过一次完整流程的落地经验后,再看业内其他新颖模型会顺畅很多。后续如果想把TTDM继续向前推进,可以考虑引入实时路况信息来修正转移时间差,或者把用户当前的交通方式作为条件变量加入特征体系,这两处改动都值得一试。

RELATED READING

延伸阅读

更多一线实战笔记与深度复盘,助您持续精进