我们如何提高推荐选择的质量和速度

我叫 Pavel Parkhomenko,是一名机器学习开发人员。 在本文中,我想谈谈 Yandex.Zen 服务的结构并分享技术改进,这些改进的实施使得推荐质量的提高成为可能。 从这篇文章中,您将学习如何在短短几毫秒内从数百万个文档中找到与用户最相关的文档; 如何对一个大矩阵(由数百万列和数千万行组成)进行连续分解,以便新文档在数十分钟内收到其向量; 如何重用用户-文章矩阵分解以获得良好的视频向量表示。

我们如何提高推荐选择的质量和速度

我们的推荐数据库包含数以百万计的各种格式的文档:在我们的平台上创建并取自外部网站的文本文章、视频、叙述和短文。 这种服务的开发伴随着大量的技术挑战。 这里是其中的一些:

  • 划分计算任务:离线完成所有繁重操作,实时只执行模型的快速应用,以便负责100-200ms。
  • 快速考虑用户操作。 为此,有必要将所有事件立即传递给推荐器并影响模型的结果。
  • 制作提要,以便新用户能够快速适应他们的行为。 刚加入系统的人应该感觉到他们的反馈会影响推荐。
  • 快速了解向谁推荐新文章。
  • 对不断出现的新内容做出快速响应。 每天都会发表数以万计的文章,其中许多文章的寿命有限(例如新闻)。 这就是它们与电影、音乐和其他长期且昂贵的创作内容的区别。
  • 将知识从一个领域转移到另一个领域。 如果推荐系统已经训练了文本文章模型,并且我们向其中添加视频,则可以重用现有模型,以便新型内容排名更好。

我会告诉你我们是如何解决这些问题的。

选择候选人

如何在几毫秒内将正在考虑的文档数量减少数千倍,同时几乎不影响排名质量?

假设我们训练了许多 ML 模型,根据它们生成特征,并训练了另一个为用户对文档进行排名的模型。 一切都会好起来的,但如果有数百万个文档,你就不能实时获取和计算所有文档的所有符号,并且需要在 100-200 毫秒内构建推荐。 任务是从数百万个子集中选择某个子集,为用户进行排名。 这个阶段通常称为候选人选择。 它有几个要求。 首先,选择必须非常快地进行,以便为排名本身留出尽可能多的时间。 其次,在大大减少了用于排名的文档数量后,我们必须尽可能完整地保留与用户相关的文档。

我们的候选人选择原则已经演变,目前我们已经制定了一个多阶段计划:

我们如何提高推荐选择的质量和速度

首先,将所有文档分为几组,并从每组中取出最流行的文档。 组可以是站点、主题、集群。 对于每个用户,根据他的历史记录,选择最接近他的组,并从中获取最佳文档。 我们还使用 kNN 索引来实时选择最接近用户的文档。 构建 kNN 索引的方法有多种;我们的效果最好 新南威尔士州 (分层可导航小世界图)。 这是一个分层模型,允许您在几毫秒内从数百万的数据库中找到用户的 N 个最接近的向量。 我们首先离线索引整个文档数据库。 由于在索引中搜索的速度非常快,因此如果有多个强嵌入,您可以创建多个索引(每个嵌入一个索引)并实时访问每个索引。

我们仍然为每个用​​户保留了数以万计的文档。 计算所有特征仍然很多,因此现阶段我们使用轻量级排序——特征较少的轻量级重排序模型。 任务是预测重型模型的顶部将包含哪些文档。 具有最高预测变量的文档将用于重模型,即排序的最后阶段。 这种方法允许您在数十毫秒内将用户考虑的文档数据库从数百万减少到数千。

运行时的 ALS 步骤

如何在点击后立即考虑用户反馈?

推荐的一个重要因素是对用户反馈的响应时间。 这对于新用户来说尤其重要:当一个人刚刚开始使用推荐系统时,他会收到各种主题的非个性化文档提要。 一旦他第一次点击,你就需要立即考虑到这一点并适应他的兴趣。 如果离线计算所有因素,系统将因延迟而无法快速响应。 所以需要实时处理用户的操作。 出于这些目的,我们在运行时使用 ALS 步骤来构建用户的向量表示。

假设我们有所有文档的向量表示。 例如,我们可以使用 ELMo、BERT 或其他机器学习模型基于文章文本离线构建嵌入。 我们如何根据用户在系统中的交互来获得同一空间中用户的向量表示?

用户文档矩阵的形成和分解的一般原理让我们有 m 个用户和 n 个文档。 对于某些用户来说,他们与某些文档的关系是已知的。 那么这些信息可以表示为一个 mxn 矩阵:行对应于用户,列对应于文档。 由于该人没有看过大部分文档,因此大多数矩阵单元格将保持为空,而其他单元格将被填充。 对于每个事件(喜欢、不喜欢、点击),矩阵中都会提供一些值 - 但让我们考虑一个简化的模型,其中喜欢对应于 1,不喜欢对应于 -1。

让我们将矩阵分解为两个:P (mxd) 和 Q (dxn),其中 d 是向量表示的维度(通常是一个很小的数字)。 那么每个对象将对应一个 d 维向量(对于用户来说 - 矩阵 P 中的一行,对于文档 - 矩阵 Q 中的一列)。 这些向量将是相应对象的嵌入。 要预测用户是否会喜欢某个文档,您只需将其嵌入相乘即可。

我们如何提高推荐选择的质量和速度
分解矩阵的可能方法之一是ALS(交替最小二乘法)。 我们将优化以下损失函数:

我们如何提高推荐选择的质量和速度

这里rui是用户u与文档i的交互,qi是文档i的向量,pu是用户u的向量。

然后,通过求解相应的线性回归,从均方误差(对于固定文档向量)的角度来看,找到最佳用户向量。

这称为“ALS 步骤”。 而ALS算法本身就是我们交替固定一个矩阵(用户和文章)并更新另一个,找到最优解。

幸运的是,找到用户的向量表示是一个相当快的操作,可以在运行时使用向量指令完成。 这个技巧可以让你在排名时立即考虑用户反馈。 可以在 kNN 索引中使用相同的嵌入来改进候选选择。

分布式协同过滤

如何进行增量分布式矩阵分解并快速找到新文章的向量表示?

内容并不是推荐信号的唯一来源。 另一个重要来源是协作信息。 传统上可以从用户文档矩阵的分解中获得良好的排名特征。 但当尝试进行这样的分解时,我们遇到了问题:

1.我们拥有数百万的文档和数千万的用户。 该矩阵并不完全适合一台机器,分解将需要很长时间。
2. 系统中的大部分内容的生命周期都很短:文档的相关性只能维持几个小时。 因此,有必要尽快构建它们的向量表示。
3. 如果在文档发布后立即构建分解,则足够数量的用户将没有时间对其进行评估。 因此,它的向量表示很可能不是很好。
4. 如果用户喜欢或不喜欢,我们将无法立即在分解中考虑到这一点。

为了解决这些问题,我们实现了用户文档矩阵的分布式分解,并进行频繁的增量更新。 它到底是如何运作的?

假设我们有一个由 N 台机器组成的集群(N 为数百台),并且我们想要对它们进行分布式分解,而该矩阵不适用于一台机器。 问题是如何进行这种分解,一方面使每台机器上有足够的数据,另一方面使计算是独立的?

我们如何提高推荐选择的质量和速度

我们将使用上面描述的 ALS 分解算法。 让我们看看如何以分布式方式执行一个 ALS 步骤 - 其余步骤将类似。 假设我们有一个固定的文档矩阵,并且我们想要构建一个用户矩阵。 为此,我们将其按行分为 N 个部分,每个部分将包含大约相同数量的行。 我们将向每台机器发送相应行的非空单元格以及文档嵌入矩阵(全部)。 由于它的大小不是很大,并且用户文档矩阵通常非常稀疏,因此该数据适合常规机器。

这个技巧可以重复几个时期,直到模型收敛,一一交替固定矩阵。 但即便如此,矩阵分解也可能需要几个小时。 这并不能解决您需要快速接收新文档的嵌入并更新构建模型时信息很少的嵌入的问题。

快速增量模型更新的引入帮助了我们。 假设我们有一个当前经过训练的模型。 自她的培训以来,出现了与我们的用户互动的新文章,以及在培训期间几乎没有互动的文章。 为了快速获得此类文章的嵌入,我们使用在模型的第一次大型训练期间获得的用户嵌入,并执行一个 ALS 步骤来计算给定固定用户矩阵的文档矩阵。 这使您可以非常快速地接收嵌入(在文档发布后几分钟内),并且经常更新最近文档的嵌入。

为了立即考虑人类行为来提出建议,在运行时我们不使用离线获得的用户嵌入。 相反,我们执行 ALS 步骤并获取实际的用户向量。

转移到另一个域区域

如何使用文本文章的用户反馈来构建视频的矢量表示?

最初,我们只推荐文本文章,因此我们的许多算法都是针对此类内容量身定制的。 但当添加其他类型的内容时,我们面临着调整模型的需要。 我们如何使用视频示例解决这个问题? 一种选择是从头开始重新训练所有模型。 但这需要很长时间,而且一些算法对训练样本的大小要求很高,对于新类型的内容在服务上的最初时刻来说,还无法提供所需的数量。

我们反其道而行之,重新使用了视频的文本模型。 同样的 ALS 技巧帮助我们创建视频的矢量表示。 我们根据文本文章对用户进行矢量表示,并使用视频视图信息执行 ALS 步骤。 所以我们很容易得到视频的矢量表示。 在运行时,我们只需计算从文本文章获得的用户向量与视频向量之间的接近度。

结论

开发实时推荐系统的核心涉及许多挑战。 您需要快速处理数据并应用机器学习方法来有效地使用这些数据; 构建能够在最短时间内处理用户信号和新内容单元的复杂分布式系统; 以及许多其他任务。

在我所描述的当前系统的设计中,用户推荐的质量随着他的活动和服务停留时间的增长而提高。 当然,主要的困难在于:系统很难立即了解与内容互动很少的人的兴趣。 改进对新用户的推荐是我们的主要目标。 我们将继续优化算法,以便与人相关的内容更快地进入他的提要,并且不相关的内容不会显示。

来源: habr.com

添加评论