写点什么

Instagram 推荐系统:每秒预测 9000 万个模型是怎么做到的?

  • 2019-12-09
  • 本文字数:4767 字

    阅读完需:约 16 分钟

Instagram推荐系统:每秒预测9000万个模型是怎么做到的?

Instagram 是 Facebook 公司旗下一款免费提供在线图片及视频分享的社交应用软件,于 2010 年 10 月发布。它可让用户用智能手机拍下照片后再将不同的滤镜效果添加到照片上,然后分享到 Facebook、Twitter、Tumblr 及 Flickr 等社交网络服务,或是 Instagram 的服务器上。Instagram Explore 页面其实是人工智能驱动的推荐系统,该系统基于一个高效的三阶段排名漏斗(3-part ranking funnel),能提取 650 亿个特征,每秒进行 9000 万个模型预测。



每个月,超过一半的 Instagram 社区成员都会访问 Instagram Explore 页面,寻找他们感兴趣的新照片、视频和故事。在数以亿计的选项中,如何大规模实时推荐与用户最相关的内容,给 Instagram 的工程师带来了许多挑战,这些挑战需要新的工程解决方案。


Instagram 通过创建一系列自定义查询语言、轻量级建模技术和支持高速实验的工具来解决这些挑战。这些系统支持 Explore 页面的规模,同时也提高了开发人员的效率。总的来说,这些解决方案描述了一种高效的人工智能系统,该系统基于一个高效的三阶段排名漏斗(3-part ranking funnel),它能提取 650 亿个特征,每秒进行 9000 万个模型预测。


本文,我们分享了让 Explore 页面起作用的关键要素的第一次详细概述,以及我们在 Instagram 上如何为人们提供个性化内容。


开发 Explore 页面的基础构件

在着手构建一个推荐引擎来处理每天上传到 Instagram 上的大量照片和视频之前,我们开发了一些基础工具来解决三个重要需求。我们需要进行大规模快速实验的能力,需要在人们兴趣范围内捕获更强的信号,需要一种计算效率高的方式来确保我们的建议既高质量又新鲜,这些定制技术是实现我们目标的关键。

使用 IGQL:一种新的特定领域语言

构建最佳推荐算法和技术是机器学习社区的研究领域之一,并且,根据任务的不同,选择合适的系统的过程也会有很大的不同。例如,虽然一种算法可以有效地识别长期兴趣,但另一种算法在识别基于最近内容的推荐方面可能表现得更好。我们的工程团队使用不同的方法进行迭代,我们需要一种方法,既能有效地尝试新的想法,又能将有前途的想法轻松地应用到大规模系统中,而不必太过担心计算资源的影响,如 CPU 和内存的使用。


为了解决这个问题,我们创建并发布了 IGQL,这是一种针对推荐系统中检索候选对象进行优化的特定领域语言。它的执行是在 C++ 中优化的,这有助于最小化延迟和计算资源。在测试新的研究想法时,还具有可扩展性和易用性。IGQL 既是静态验证,也是高级语言。工程师可以像 Python 那样编写推荐算法,并在 C++ 中快速高效地执行。


user.let(seed_id=user_id).liked(max_num_to_retrieve=30).account_nn(embedding_config=default).posted_media(max_media_per_account=10).filter(non_recommendable_model_threshold=0.2).rank(ranking_model=default).diversify_by(seed_id, method=round_robin)
复制代码


从上面的代码示例中可以看到,对于没有广泛使用这种语言的工程师,IGQL 提供了高可读性,有助于以原则性的方式组合多个推荐阶段和算法。例如,我们可以通过在查询中使用组合规则输出几个子查询结果的加权混合,对候选生成器的集合进行优化。通过调整权重,可以找到能够带来最佳用户体验的组合。


IGQL 使得执行复杂推荐系统中的常见任务变得简单,比如构建组合规则的嵌套树。IGQL 让工程师能够专注推荐背后的机器学习和业务逻辑,比如为每个查询获取适当数量的候选对象。提供高度代码可重用性。例如,应用排名器(ranker)就像在 IGQL 查询中添加一行规则一样简单。将它添加到多个位置是很简单的,比如对账户进行排名和对这些账户发布的内容进行排名。

用于个性化排名的账户嵌入

人们在 Instagram 上公开分享数十亿条高质量的媒体内容,这些内容都是有资格进入推荐页面的。在 Explore 页面上为各种兴趣社区维护一个清晰且不断发展的目录是存在挑战的:其话题从书法到火车模型都有。因此,基于内容的模型很难理解如此多样的基于兴趣的社区。


因为 Instagram 有大量基于特定主题的关注兴趣的账户(比如猫或者汽车),我们为此创建了一个检索管道,专注于账户级别的信息,而不是内容级别的信息。通过构建账户嵌入( Account Embeddings),我们能够更有效地识别哪些账户在主题上彼此相似。我们使用 ig2vec 来推断账户嵌入,ig2vec 是一种类似 word2vec 的嵌入框架。通常,word2vec 嵌入框架基于单词在训练语料库中跨句子的上下文来学习单词的表示。ig2vec 将用户与之交互的账户 ID(例如,用户喜欢来自某个账户的内容)视为句子中的单词序列。


通过应用 word2vec 的相同技术,我们可以预测一个人在 Instagram 应用中给定会话可能与之交互的账户。如果一个人在同一会话中与一系列账户进行交互,那么与来自不同 Instagram 账户的随机账户序列相比,它更有可能具有主题一致性,这有助于识别出与主题相似的账户。


我们定义了两个账户之间的距离度量:与嵌入训练中使用的距离度量相同,通常是余弦距离或点积。在这一基础上,我们做了一个 KNN (K 近邻算法)查找,以便为嵌入的账户找到与其主题相似的账户。我们的嵌入版本覆盖了数百万个账户,我们使用 Facebook 最先进的最近邻检索引擎 FAISS 作为支持检索的基础设施。



对于嵌入的每个版本,我们训练一个分类器,仅基于嵌入来预测一组账户的主题。通过将预测主题与人工标注的主题进行比较,我们就可以评估这些嵌入,是否能够很好地捕捉主题相似度。


检索与某个特定人先前表示感兴趣的账户类似的账户,可以帮助我们以一种简单而有效的方式缩小范围,为每个人制定更小的个性化排名清单。因此,我们能够用最先进的计算密集型机器学习模型为每个 Instagram 社区成员提供服务。

利用模型蒸馏对相关候选对象进行预选

在使用 ig2vec 根据个人兴趣确定最相关账户之后,我们就需要一种方法来对这些账户进行排名,这对每个人来说,经排名过的账户都是新鲜有趣的。这就需要在每次滚动 Explore 页面时,预测与每个人最相关的内容。


例如,通过深度神经网络为每个滚动动作进行评估,即使只有 500 个内容片段,也需要大量资源。然而,我们为每个用户评估的帖子越多,我们就越有可能从他们的清单中找到最好的、最个性化的内容。


为了能够最大化每个排名请求的内容数量,我们引入了排名蒸馏模型,帮助我们在使用更复杂的排名模型之前对候选对象进行预选。我们的方法是训练一个超轻量级的模型,该模型学习并尽可能接近主要排名模型。我们从更复杂的排名模型中记录具有特征和输出的输入候选对象。然后,使用有限特征集和更简单的神经网络模型结构的记录数据来训练模型以复制结果。其目标函数就是对 NDCG 排名(一种衡量排名质量的指标)的损失进行优化,使其超过主要排名模型的输出。我们使用蒸馏模型(distillation model)中排名最高的帖子作为后期模型的候选。


通过建立蒸馏模型的模拟行为,我们可以最大限度减少调整多个参数和在不同排名阶段维护多个模型的需要。利用这一技术,我们可以有效评估更大的内容集,在每个排名请求中找到最相关媒体内容的同时,保持计算资源仍在控制之下。

我们怎样构建 Explore 页面?

在创建了易于实验、有效识别用户兴趣并产生有效的相关预测所需的关键构件之后,我们就必须在生产中将这些系统结合在一起。利用 IGQL、账户嵌入和蒸馏技术,我们将 Explore 页面的推荐系统分为两个主要阶段:候选对象生成阶段(亦称为寻源阶段)和排名阶段。


生成候选对象

首先,我们利用人们之前在 Instagram 上交互过的账户(例如,在某个账户中点赞或保存其发布的媒体内容)来确定人们可能感兴趣的其他账户。我们称之为种子账户。种子账户通常只是 Instagram 上兴趣相似或相同的账户的一小部分。然后,我们使用账户嵌入技术来识别类似于种子账户的账户。最后,基于这些账户,我们就可以找到这些账户发布或参与的内容。



上图展示了 Instagram Explore 推荐的一个典型来源。人们可以通过许多不同的方式与 Instagram 上的账户和内容进行互动(例如关注、点赞、评论、保存和分享等)。还有不同的内容类型(如照片、视频、故事和直播),这意味着我们可以用类似的方案来构建多种来源。利用 IGQL,这个过程变得非常简单:不同的候选源只是表示为不同的 IGQL 子查询。


通过不同类型的来源,我们能够为普通人找到数以万计的合格候选对象。我们希望确保我们推荐的内容,对于包含许多年龄段的全球社区来说,既安全,又适合。使用各种信号,我们在为每个人建立合适的清单之前,过滤掉我们认为不符合推荐资格的内容。除了阻止可能违反政策的内容和错误信息之外,我们还利用机器学习系统来帮助检测和过滤垃圾邮件等内容。


然后,对于每个排名请求,我们为一个普通人确定数千个合格的内容源,从合格清单中抽取 500 个候选对象,然后将候选对象发送到排名阶段。

对候选对象进行排名

我们在有 500 个候选对象可供排名的情况下,使用一个三阶段的排名基础设施来帮助平衡排名相关性和计算效率之间的权衡。我们的三个排名阶段如下:


第一阶段:蒸馏模型模仿其他两个阶段的组合,具有最少的特征;从 500 个候选对象中挑选出 150 个质量最高、最相关的候选对象。


第二阶段:一种轻量级神经网络模型,具有完整的密集特征集;挑选 50 个最高质量和最相关的候选对象。


第三阶段:一种深度神经网络模型,具有完整的密集和稀疏特征集。挑选 25 个质量最高、最相关的候选对象(用于 Explore 页面的第一页)。



该动画描述了三部分组成的排名基础设施,我们使用它来平衡排名相关性和计算效率之间的权衡。


如果第一阶段中蒸馏模型模仿了其他两个阶段的排名,那么我们如何确定接下来两个阶段中最相关的内容呢?我们预测人们在每一条内容上采取的个人行为,无论是点赞和保存之类的积极行为,还是像“减少这样的帖子”之类的消息行为。我们使用一个多任务多标签(multi-task multi-label,MTML)神经网络来预测这些事件。共享的多层感知器(Multilayer Perceptron,MLP)允许我们捕获来自不同动作的常见信号。



模型架构


我们使用一个称为价值模型的算术公式来组合对不同事件的预测,以捕获不同信号的显著性,从而决定内容是否相关。我们使用预测的加权和,比如[w_like * P(Like) + w_save * P(Save) - w_negative_action * P(Negative Action)]。例如,如果我们认为一个人在 Explore 页面上保存帖子的重要性高于他们喜欢的帖子,那么保存行为的权重应该更高。


我们还希望 Explore 页面能够成为一个人们可以发现新兴趣和现有兴趣之间的平衡的地方。我们在价值模型中加入一个简单的启发式规则,以提高内容的多样性。我们通过添加惩罚因子来降低同一个作者或同一种子账户的帖子的排名,这样就不会在 Explore 页面看到同一个作者或同一个种子账户发出的多个帖子。这个惩罚会随着排名下降,并遇到更多来自同一作者的帖子而增加。


我们基于每个排名候选对象的最终价值模型得分,以子代的方式对最相关的内容进行排名。随着系统的发展,我们的离线重播工具,以及贝叶斯优化工具,可以帮助我们高效且频繁地调整价值模型。

一项正在进行的机器学习挑战

在构建 Instagram Explore 页面的过程中,最令人兴奋的地方之一就是不断寻找新的且有趣的方法,帮助社区发现 Instagram 上最有趣和相关的内容。我们正在不断发展 Instagram 的 Explore 页面,无论是通过添加像故事这样的媒体内容格式,还是通过新类型的内容入口点,如购物帖子和 IGTV 视频。


Instagram 社区和清单的规模都要求能够实现高速实验的文化和开发效率,才能可靠地推荐 Instagram ,以满足每个人的个人兴趣。我们的自定义工具和系统为持续学习和迭代奠定了坚实的基础,这对于构建和扩展 Instagram 的 Explore 页面是必不可少的。


作者介绍:


Ivan Medvedev,软件工程师;Haotian Wu,工程经理;Taylor Gordon,研究科学家。


原文链接:


https://ai.facebook.com/blog/powered-by-ai-instagrams-explore-recommender-system


2019-12-09 09:176498

评论

发布
暂无评论
发现更多内容

鸿蒙学习笔记之使用 XML 方式创建布局

宇宙之一粟

鸿蒙 java UI 2月月更

The Rust Programming Language

Joseph295

Go反射的三大法则

linlh

反射 元编程 Go 语言 2月月更

韵达基于云原生的业务中台建设 | 实战派

阿里巴巴云原生

阿里云 云原生 业务中台 合作案例

从冬奥看中国科技(五):漫天塞地物联网

脑极体

办公效率起飞了!Python终于解放了我的双手

Jackpop

Go语言图书管理RESTful API开发实战

Jackpop

Kubernetes集群仪表盘dashboard&Kuboard安装Demo

山河已无恙

Kubernetes 2月月更

设计消息队列存储消息数据的 MySQL 表格

swallowluo

架构实战营 #架构实战营 「架构实战营」

工作想法小计2/7 - 2/11

非晓为骁

个人成长 开发 工作方式 Go 语言

为什么需要单元测试?

蜜糖的代码注释

单元测试 后端开发 2月月更

电子书《大型组织深入推广零代码应用平台的行动指南》正式发布!

明道云

LabVIEW跳转访问网页

不脱发的程序猿

LabVIEW 跳转访问网页

RPA进阶(一):走近 RPA 世界

No Silver Bullet

RPA 机器人流程自动化 2月月更

如何利用区块链改进金融系统身份验证?

CECBC

DOM 节点的克隆和导入

编程三昧

JavaScript 前端 DOM 2月月更

kube-scheduler源码分析(1)-初始化与启动分析

良凯尔

源码 Kubernetes 容器 源码分析 #Kubernetes#

LabVIEW生成应用程序(exe)和安装程序(installer)

不脱发的程序猿

LabVIEW 生成应用程序(exe) 安装程序(installer)

技术盘点:2022年云原生架构趋势解读

阿里巴巴云原生

阿里云 架构 云原生 趋势

技术盘点:2022 年容器、Serverless、可观测、服务网格有哪些值得关注的趋势?

阿里巴巴云原生

阿里云 Serverless 云原生 趋势 可观测

Lyft微服务研发效能提升实践 | 2. 优化快速本地开发

俞凡

研发效能 大厂实践 2月月更 lyft

如何打造一款得心应手的VS Code?

Jackpop

总算彻底搞懂Python集合了

Jackpop

Kubernetes核心组件-ETCD详解

巨子嘉

容器 云原生 etcd

【C语言】一维数组

謓泽

C语言 2月月更 一维数组

基于51单片机室内灯光控制系统

DS小龙哥

2月月更

技术盘点:云原生中间件的技术演进与未来趋势展望

阿里巴巴云原生

阿里云 云原生 中间件 趋势

消息队列存储消息数据的表结构

皓月

「架构实战营」

gopher成长之路(四):GO开发工程师写QT

非晓为骁

个人成长

也许我们可以用另一种角度与观点看待世界所发生的事情,让你有所解答。

叶小鍵

显示器选购总结-戴尔2705QM-明基PD2700U

李印

总结 经验分享

Instagram推荐系统:每秒预测9000万个模型是怎么做到的?_语言 & 开发_Ivan Medvedev等_InfoQ精选文章