不久前,照片分享应用Instagram推出了搜索与浏览功能。浏览页面上的热门标签和地点是社区中一些最受欢迎的内容,而其背后是一个每天可以解析7000多万张新增图片的系统。近日,Instagram技术博客 介绍 了支撑该系统的热门趋势发现算法。
直观地讲,热门标签是一个比平时用得多的标签,而这种情况是由那个时刻发生的特定事件所导致。比如,在Instagram撰写那篇博文时,#equality就是一个热门标签,即当时有许多人用它分享图片:
通过标签热度变化可以识别趋势。Instagram认为,一个良好的趋势要具备三个要素:
识别趋势需要量化当前观察到的活动(分享照片和视频的数量)与预期活动的差异。如果前者高于后者,就可以确定某个趋势。比如上文提到的标签#equality,通常每个小时只有几张照片及视频用到它。但从太平洋时间上午7点开始,有数以千计的人用它分享内容。就是说,活动多于预期,标签#equality代表一种趋势。
对于每个标签和地点,他们会记录过去七天中每五分钟内有多少媒质在分享时用到了它,该数量表示为 C(h, t)
,即标签h在时间点t的计数(也就是,在t-5到t时段里以h作为标签的帖子数量)。由于该计数在不同的标签或不同的时点之间差别很大,所以将其规范化为在时点t观察到h的概率 P(h, t)
。此外,他们还构建了一个模型,用于计算预期数量 C’(h, t)
,并得出预期概率 P’(h, t)
。现在,就可以使用一种常见的概率差异度量方法“KL散度( KL divergence )”计算实际概率与预期概率的差异,公式如下:
S(h, t) = P(h, t) * ln(P(h, t)/P’(h, t))
其中, P(h, t)
可以体现 流行度 , P(h, t)/P’(h, t)
可以体现 新颖性 ,而t则体现出 时效性 。
预测是指根据过去的观察计算预期基准概率。在这个过程中,需要权衡准确性与计算的时空复杂度。通常,准确性会与时空复杂度呈一定的正比关系。他们测试了不同的可选方案,包括取上周同一时间的计数、回归模型、神经网络。最终,他们选择使用上周测量值中的最大概率,这有如下好处:
这里有两点需要说明一下。一是,由于大多数标签在五分钟内的计数都非常小,甚至为0,所以他们在计算旧的计数时以小时为单位,而且他们会查看几个小时的数据,以最小化随机使用高峰的干扰。二是,如果某个标签过去没有出现过,那么他们会将该标签在那个时间窗口内的计数置为3,依据是大多数标签在一个小时出现次数都不超过3。
这一步是根据KL散度值 S(h, t)
排列标签。他们发现,部分趋势消失地很快,但实际上仍然有人对其感兴趣。为了解决这个问题,他们引入了 指数衰减函数 ,用它定义趋势的生存期。 S(h, tmax)=SM(h)
表示标签h在时点tmax时取得最大KL散度值,则其指数衰减值为:
Sd(h, t) = SM(h) * (½)^((t - tmax)/half-life)
其中,衰减参数“半衰期(half-life)”为2小时,是指 SM(h)
每过两个小时就会减半。
通常,人们会用多个标签描述同一事件,当一个事件热门时,描述该事件的多个标签都会成为趋势。因此,需要将这些概念上相同的标签聚合成一个趋势。这有两个方面的工作:一是识别出谈论同一事件的标签,二是找出最能代表该事件的标签。对于第一项,他们通过以下维度计算标签相似度:
趋势聚合过程即是根据每一对趋势标签的相似度将它们分组。
他们将趋势发现后台设计成一个有四个节点的流处理应用程序,如下图所示:
每个节点都有特定的作用:
S(h, t)
。 该系统需要实时处理大量数据,并具有高效和容错特性。上述线性架构使他们可以将趋势划分,并启动每个节点的多个实例,实现并行处理。而且,某个划分或实例出现问题都不会影响整个系统。
上面讨论的是趋势发现过程,而发现的趋势通过下图所示的方式提供给应用请求:
可以看出,来自Instagram应用的趋势标签和地点请求不会增加趋势发现后台的负载,因为应用的请求是由 memcached 缓存和 Postgres 数据库提供,其中数据库中存储了 ranker 的计算结果。
后续,他们考虑将该项目分解成多个更小的问题,每个问题由具有特定功能的组件单独处理。这样,他们团队中的每个人就可以一次只关注一个问题。
感谢郭蕾对本文的审校。
给InfoQ中文站投稿或者参与内容翻译工作,请邮件至editors@cn.infoq.com。也欢迎大家通过新浪微博(@InfoQ,@丁晓昀),微信(微信号: InfoQChina )关注我们,并与我们的编辑和其他读者朋友交流(欢迎加入InfoQ读者交流群 )。