时间-事件建模对于更好地理解用户体验的各个维度至关重要。通过利用经过审查的时间到事件数据(涉及时间间隔的数据,其中一些时间间隔可能超出了分析数据时的时间间隔),公司可以深入了解消费者生命周期中的痛点,以增强用户的整体体验。尽管经过审查的事件时间数据很普遍,但它经常被忽视,导致预测存在极大的偏差。
在优步,我们感兴趣的是调查乘客在平台上首次出行后再次出行所需的时间。我们的许多乘客是通过推荐或促销活动第一次接触优步的。他们的第二次骑行是一个关键指标,表明乘客发现了使用平台的价值,并愿意长期与我们合作。然而,建模到第二次骑行的时间是很棘手的。例如,有些骑手就是不经常骑车。当我们在这样的骑手第二次骑行之前分析这些时间到赛事的数据时,我们会考虑他们的数据审查.
类似的情况在其他公司和其他行业也存在。例如,假设一个电子商务网站对客户的重复购买模式感兴趣。然而,由于客户行为模式的多样性,公司可能无法观察到所有客户的所有重复购买行为,从而导致数据被删减。
在另一个例子中,假设一家广告公司对其用户的重复广告点击行为感兴趣。由于每个用户的兴趣不同,公司可能无法观察到客户的所有点击。用户可能直到研究结束后才会点击广告。这将导致下次点击数据的审查时间。
在对经过审查的时间到事件数据建模时,为每个感兴趣的个体索引
时,我们可以观察到如下形式的数据:
![]()
在这里,
是审查标签;
如果观察到感兴趣的事件;而且
如果感兴趣的事件被审查。当
,
表示感兴趣的事件的时间。当
,
表示审查发生之前的时间长度。
让我们继续优步的时间-秒乘的例子:如果一个乘客在第一次乘坐后12天第二次乘坐,这个观察结果会被记录为
.在另一个案例中,一名骑手第一次骑行,60天过去了,在规定的截止日期前,他们还没有返回应用程序进行第二次骑行。这一观察记录为
.情况如下图所示:

有大量的生存分析文献,在这个领域已经做了一个多世纪的统计研究;雷竞技是骗人的其中大部分可以使用概率编程的框架进行简化。在本文中,我们将介绍如何使用烟花概率编程语言建模审查时间到事件数据。
与流失建模的关系
在继续之前,值得一提的是,许多行业从业者通过设置人为定义的标签“搅乱”来规避这种经过审查的从时间到事件的数据挑战。例如,一家电子商务公司可能会将一位客户定义为“流失”,如果他们在过去40天内还没有回到该网站进行另一次购买。
流失量建模使从业人员能够将观察结果调整为经典的二元分类模式。因此,使用现成的工具(如scikit-learn和XGBoost),客户流失建模变得非常简单。例如,上面两个骑手将分别被标记为“未搅拌”和“搅拌”。
虽然流失模型在某些情况下确实有效,但它并不一定适用于优步。例如,一些乘客可能只在出差时使用优步。如果这个假设的乘客每6个月要出差一次,我们可能会错误地把这个商务乘客贴上“颠簸”的标签。因此,我们从流失模型中得出的结论可能具有误导性。
我们也有兴趣从这些模型中做出解释,以阐明不同因素对所观察到的用户行为的贡献。因此,模型不应该是一个黑盒。我们希望能够开放模型,并使用它做出更明智的业务决策。
为了实现这一点,我们可以利用Pyro,这是一种用于概率编程的灵活且富有表现力的开源工具。
用于统计建模的Pyro
创立于Uber,烟花是一种用Python编写的通用概率编程语言,构建在PyTorch库上,用于张量计算。
如果你有统计学背景,拥有最少的贝叶斯建模知识,或者你一直在使用TensorFlow或PyTorch等深度学习工具,那么你很幸运。
下表总结了一些最流行的概率编程项目:
| 软件 | bug / jags [1] | 斯坦 | PyMC | TensorFlow概率[4] | 烟花 |
| 编程语言 | 领域特定语言[2] | 领域特定语言 | Python | Python | Python |
| 底层计算引擎 | 自我 | STAN数学图书馆 | Theano [3] | TensorFlow [5] | PyTorch [6] |
下面,我们将重点介绍这些不同软件项目的一些关键特性:
- BUGS / JAGS是后来被称为概率编程的早期例子。它们在统计领域已经积极发展和使用了二十多年。
- 然而,BUGS / JAGS主要是从头开始设计和开发的。因此,模型规范是使用它们的领域特定语言完成的。此外,概率程序员从R和MATLAB中的包装器中调用BUGS / JAGS。用户必须在编码语言和文件之间来回切换,这有点不方便。
- PyMC依赖于Theano后端。然而,Theano项目最近被终止了。
- TensorFlow Probability (TFP)最初是一个名为Edward的项目。Edward项目被滚动到TFP项目中。
- TFP使用TensorFlow作为它的计算引擎。因此,它只支持静态计算图。
- Pyro使用PyTorch作为计算引擎。因此,它支持动态计算图。这使用户能够指定数据流方面不同的模型,并且非常灵活。
简而言之,Pyro位于最强大的深度学习工具链(PyTorch)的非常有益的交汇点,同时站在数十年统计研究的肩膀上。雷竞技是骗人的其结果是一个非常简洁和强大,但灵活的概率建模语言。
建模经过审查的时间到事件数据
现在,让我们开始讨论如何对经过审查的时间到事件数据建模。感谢谷歌Colab,用户可以结账大量的例子代码和在不安装Pyro和PyTorch的情况下开始建模数据。您甚至可以复制和摆弄工作簿。
模型定义
出于本文的目的,我们将时间到事件数据定义为
,
作为时间到事件和
作为二进制审查标签。我们将实际的事件时间定义为
,这可能不会被观察到。我们将审查时间定义为
,为简单起见,我们假设它是一个已知的固定数字。总之,我们可以将这种关系建模为:
![]()
![]()
我们假设
服从指数分布与尺度参数
,一个变量依赖于以下线性关系与感兴趣的预测
:
![]()
![]()
在这里,
是软加函数,从而保证
保持积极。最后,我们假设
而且
遵循正态分布作为先验分布。对于本文的目的,我们感兴趣的是评估的后验分布
而且
.
生成人工数据
我们首先导入Python中所有必要的包:
为了生成实验数据,我们运行以下几行代码:
恭喜你!您刚刚在Note[1]中运行了第一个Pyro函数。这里我们从正态分布中抽取样本。细心的用户可能已经注意到这个直观的操作与我们在Numpy中的工作流程非常相似。
在上述代码块的末尾(注2),我们生成了的回归图
(绿色),
(蓝色)
,分别。如果我们不考虑数据审查,我们就低估了模型的斜率。
构建模型
有了这些新鲜但经过删减的数据,我们可以开始构建更准确的模型。让我们从下面的模型函数开始:
在上面的代码片段中,我们突出了以下注释,以更好地阐明我们的示例:
- 注1:总的来说,模型函数是描述数据如何生成的过程。这个例子模型函数告诉我们如何生成y或truncation_label从输入向量x.
- 注2:我们指定的先验分布
而且
这里和样本从他们使用pyro.sample函数。Pyro在PyTorch项目和Pyro项目本身中都有一个庞大的随机分布家族。 - 注3:我们连接输入
,
,
成
用变量表示的向量链接在这里。 - 注4:我们指定了真实时间到事件的分布
利用指数分布与尺度参数向量链接。 - 注5:供观察
,如果我们观察时间到事件的数据,那么我们将其与真实的观察结果进行对比y[我]。 - 注6:如果为了观察而删减数据
,截断标记(这里等于1)遵循伯努利分布。的CDF表示看到截断数据的概率
点
.我们从伯努利分布中取样,并将其与实际观测结果进行对比truncation_label[我].
有关贝叶斯建模和使用Pyro的更多信息,请查看我们的入门教程.
用哈密顿蒙特卡罗计算推理
在计算贝叶斯推理时,哈密顿蒙特卡罗(HMC)是一种流行的技术。我们估计
而且
使用HMC,如下:
上面的过程可能需要很长时间才能运行。这种缓慢在很大程度上是由于我们是通过每个观测来评估模型的。为了加快模型的速度,我们可以使用向量化pyro.plate而且pyro.mask,如下图所示:
在上面的代码片段中,我们首先使用指定的模型指定HMC内核。然后,我们执行MCMCx,y,以及truncation_label.MCMC采样结果对象接下来转换为EmpiricalMarginal对象,帮助我们进行推理a_model参数。最后,我们从后验分布中抽取样本,并用我们的数据创建一个图,如下图所示:
我们可以看到样本是围绕的真实值聚集的为2.0。
使用变分推理加速估计
随机变分推理(SVI)是一种加速贝叶斯推理的好方法有大量的数据。现在,只要知道导函数是理想后验分布的近似值就足够了。导函数的规范可以极大地加快参数估计的速度。为了实现随机变分推理,我们将引导函数定义为:
指南=自动多变量正常(模型)
通过使用导函数,我们可以近似参数的后验分布
而且
为正态分布,其中它们的位置和尺度参数分别由内部参数指定。
模型训练和结果推断
使用Pyro的模型训练过程类似于深度学习中的标准迭代优化。下面,我们指定SVI训练器并通过优化步骤进行迭代:
如果一切按计划进行,我们可以看到上述执行的结果。在这个例子中,我们得到了如下的结果,其均值非常接近于和指定的真值:
a_model =0.009999999776482582, b_model =0.009999999776482582
a_model =0.8184720873832703, b_model =2.8127853870391846
a_model =1.3366154432296753, b_model =3.5597035884857178
a_model =1.7028049230575562, b_model =3.860581874847412
a_model =1.9031578302383423, b_model =3.9552347660064697
最终结果:
中位数a_model =1.9155923128128052
中位数b_model =3.9299516677856445
我们还可以通过下面的代码检查模型是否收敛,并达到图3:
sns.plt.plot(损失)
我们可以用guide.quantiles ()功能:
我们可以看到,导函数以的实际值为中心
而且
,分别如下:
前进
我们希望您可以利用Pyro进行自己的经过审查的时间到事件数据建模。要开始使用开源软件,请查看Pyro官方网站额外的例子包括一个入门教程而且沙箱库.
在以后的文章中,我们将讨论如何利用Pyro的附加功能加速SVI计算,包括使用板API用于对相似形状的样品进行批量处理。
有兴趣参与Pyro和Uber AI的其他项目吗?考虑申请一个职位我们的团队!







