🧠 第十章 交通与智驾:构建安全高效出行解决方案
📄 一句话概括

13.1 公里、8 段路,P50 是 18.3 分钟。 报中位数就等于一半人会迟到(50%);改报 P80(22.8 分钟)只剩 20%。更麻烦的是相关性: 段间正相关时区间宽 12.5 分钟,独立假设只算 6.2 分钟——拿这个区间去套, 名义 80% 实际只覆盖 46%。

📝 本节和前面几节的关系

上一节管的是「车怎么走」,这一节管的是「人怎么知道」。 ETA 是导航里最被低估的指标:它决定用户什么时候出门、走哪条路、信不信你。

一、ETA 从来不是一个数

「预计 18 分钟到达」这句话背后其实是一个分布:路况好 15 分钟,堵一下 28 分钟, 你报的那个数只是从这个分布里挑了一个点。 挑哪个点,决定了两件事:多少人会迟到,和这个 App 显得有多靠谱。 常见的三个选择:均值、中位数、某个高分位。 均值和中位数差不多(本例 18.6 对 18.3),因为路程由多段叠加,分布已经接近对称。 所以「报得准不准」这个问题,看均值是看不出来的。 真正的问题是:你要让多少人迟到?这个问法听着奇怪,但它就是 ETA 产品的核心取舍。

二、报中位数等于一半人迟到

中位数的定义就是「一半的概率超过它」。Demo 算出来:报 P50,超过它的人正好 50%。 这个 50% 不是模型不准,是定义出来的。哪怕你估得完美无偏,报中位数也还是一半人迟到。 而迟到的代价远大于早到——早到五分钟没人感谢你,迟到五分钟就是一次差评。所以从产品角度, ETA 应该报偏保守的分位数。 Demo 里的数:报 P80(22.8 分钟),迟到率降到 20%,代价是数字大了 4.5 分钟。 这就是 ETA 的全部取舍:报得越保守,越不容易失信,也越容易被嫌慢。 行业里常见的做法是报 P75 到 P85, 具体选哪个,取决于这个产品更怕「迟到」还是更怕「用户觉得慢」。

三、独立性假设把区间算窄了

要报分位数,就得知道整个分布,而分布的形状取决于「各段路之间是否相关」。 Demo 对比两种假设:段间独立(每段速度各自随机)和段间相关 0.5(有一半波动来自共同因子, 比如同一场雨)。 结果很扎眼:相关时 P10~P90 宽 12.5 分钟,独立时只有 6.2 分钟,差一倍。 更狠的是交叉检验:拿「独立假设」算出的区间去套「相关」的分布,名义覆盖 80%,实际只覆盖 46%。 原因很直白:8 段路的拥堵是同一场雨、同一个早高峰造成的,不会互相抵消。 独立假设把「一起慢」当成了「有的快有的慢」,于是把总时间的波动算小了。 这一条在实践里非常常见: 很多 ETA 系统的误差在晴天很小、一到下雨就整体偏晚——因为模型是按独立路段建的, 没有「全局拥堵因子」这一项。

四、落地的三个层次

① 报分位数,不报均值。接口上直接给 P50 和 P80 两个数,前端按场景选:赶飞机用 P80, 随便逛逛用 P50。 ② 相关性要进模型。最省事的做法是加一个全局因子:先估「今天全城偏慢多少」,再逐段修正。 这一项就能覆盖掉大部分相关性。 ③ 不能只报「准不准」,要报「区间覆盖」。评估指标应该是「P80 区间实际覆盖了多少比例」, 目标 80%,低于 70% 说明区间太窄,高于 90% 说明太保守。 最后提醒:ETA 的误差会随预测时长放大。5 分钟后的预测可以很准, 60 分钟后的预测基本只能给个区间。所以「越远越不准」要在 UI 上体现出来,而不是假装一样准。

五、动手 Demo:ETA:报中位数 50% 的人迟到,改报 P80 只剩 20%

8 段路合计 13.1 公里,每段速度服从对数正态(中位 20~70 公里/时、σ=0.35)。 跑 20000 次蒙特卡洛,分别按「段间独立」和「段间相关 0.5」两种假设生成速度,算出总耗时分布, 再统计 P50、P80、P10~P90 区间宽度和覆盖率。最后拿独立假设的区间去套相关分布,看覆盖掉多少。

z = rg.normal(0, 1, (M, 1))                # 全局因子
e = rg.normal(0, 1, (M, len(L)))           # 各段独立抖动
v_cor = med * np.exp(sig * (np.sqrt(rho) * z
                             + np.sqrt(1 - rho) * e))
t_cor = (L / v_cor * 3600.0).sum(axis=1) / 60.0

late50 = 100.0 * np.mean(t_cor > np.percentile(t_cor, 50))
late80 = 100.0 * np.mean(t_cor > np.percentile(t_cor, 80))

lo_i = np.percentile(t_ind, 10)            # 独立假设的区间
hi_i = np.percentile(t_ind, 90)
cross = 100.0 * np.mean((t_cor >= lo_i) & (t_cor <= hi_i))

实跑输出:

--------------------------------------------------------------------
ETA:报中位数 50% 的人迟到,改报 P80 只剩 20%
--------------------------------------------------------------------
  路径                     8 段,合计 13.1 公里
  速度模型                 对数正态,中位 20~70 公里/时,σ=0.35
  蒙特卡洛                 20000 次

  假设           P50(分)   P80(分)    P10~P90   区间覆盖   区间宽
  --------------------------------------------------------------
  段间独立          18.6      20.8   [16, 22]        80%      6.2
  段间相关 0.5      18.3      22.8   [13, 26]        80%     12.5

  看前两列:**P50 段间独立 18.6 分钟、相关 18.3 分钟,几乎一样。**
  **所以「平均要多久」这个数,对出行决策几乎没有用。**
  **报中位数等于承认「一半人会迟到」**——50%,这个数是定义出来的,
  不是模型不好。**你要让谁不迟到,就得报比他高的分位。**
  报 P80(22.8 分钟),迟到率降到 **20%**,代价是数字大了 4.5 分钟。
  **这就是 ETA 产品的全部取舍:报得越保守,越不容易失信,也越容易被嫌慢。**
  再看第三、四列。**相关时区间宽 12.5 分钟,独立时只有 6.2 分钟,差一倍。**
  最狠的是交叉检验:**拿独立假设的 [15, 22] 去套相关分布**,
  **名义覆盖 80%,实际只覆盖 46%。**
  **这就是忽略相关性的代价:区间看起来还在,其实根本不够宽。**
  原因很直白:**8 段路的拥堵是同一场雨、同一个早高峰造成的**,不会互相抵消。
  **独立假设把「一起慢」当成了「有的快有的慢」,于是把总时间的波动算小了。**
  实务上要做的:**ETA 必须按分位报,而且相关性要进模型。**只报均值的导航,遇到下雨天一定翻车。

done -> _out_39p.txt

报 P50,迟到率 50%——这是定义,不是误差。 很多人看到这个数会以为模型有问题,其实模型没问题,是选错了报什么。 报 P80,迟到率 20%,数字从 18.3 变 22.8,大了 4.5 分钟。 这 4.5 分钟就是「可信度」的价钱。 区间宽度那一列:12.5 对 6.2。 相关假设下区间宽一倍,因为 8 段路的波动会叠加而不是抵消。 交叉检验 46% 是最值得记住的数。名义上「80% 区间」, 实际只包住 46% 的情况——这个系统会在下雨天系统性失信。 要说明:速度分布、相关强度、路段长度都是我设的,不是真实路网数据。 但蒙特卡洛、分位数、覆盖率的算法是真的,换成真实 GPS 速度数据,流程不变。

30 秒实验

  1. 把相关系数从 0.5 加到 0.9(整城一起堵),看区间宽度和覆盖率。 宽度会接近 20 分钟,覆盖率更低——相关性越强,独立假设错得越远。
  2. 把 σ 从 0.35 改成 0.15(路况很稳),看 P80 和 P50 的差距。 会缩到 1 分钟左右——路况越稳,保守报价的代价越小。
  3. 把路段数从 8 段改成 3 段,重跑交叉检验。 覆盖率会回升到 60% 以上——段数越少,独立假设的偏差越小。

常见误区

  1. 「ETA 报准了就行」。报中位数必然一半人迟到,要报分位数,是有意报得偏保守。
  2. 「各路段独立建模最简单」。独立假设会把区间算窄一半,下雨天覆盖率掉到 46%。
  3. 「用平均速度算时间就行」。平均值丢掉了波动,而用户感受到的恰恰是波动。
自测三问(点开对答案) 1. 为什么报中位数会有 50% 的人迟到? —— 中位数按定义就是「一半概率超过它」。这不是模型误差,是选择了这个分位数必然的结果。 2. 为什么各路段不能假设独立? —— 同一场雨、同一个早高峰会同时影响所有路段,波动叠加而不是抵消。 独立假设会把总时间的方差算小,区间算窄。 3. 评估 ETA 该用什么指标? —— 看「P80 区间的实际覆盖率」,目标是 80%。低于 70% 说明区间太窄,高于 90% 说明报得太保守。

通行效率解决了,还有一个更硬的需求:别撞上。下一节看 AEB 的阈值到底该定在几秒。

相关笔记