Pinterest是世界上最大的图片社交分享网站。网站允许用户创建和管理主题图片集合,例如事件、兴趣和爱好。以下为来自Pinterest工程师关于代码审查的一些思考。
作者:Shaji Chennan Kunnummel,Iaroslav Tymchenko
概览
Pinterest 的核心是一个视觉平台,因此理解图像并采取行动的需求至关重要。 几年前,内容质量团队设计并实施了我们自己的批处理管道来检测相似图像。 相似度信号在 Pinterest 被广泛用于各种用例,从改进基于相似图像的推荐到删除垃圾邮件和滥用内容。 然而,为新创建的图像计算信号需要几个小时,这是垃圾邮件发送者和滥用者损害平台的一个漫长的窗口。 所以最近,该团队实施了一个流管道来近乎实时地检测相似图像。
鉴于平台的规模,识别重复图像一直很困难,而实时识别则更具挑战性。 这篇博文重点介绍了内容质量团队最近所做的工作,即利用 Apache Flink (近乎)实时地检测重复图像。
该项目的目标是将延迟减少到亚秒级,而不是批处理流水线需要数小时的延迟,而不会影响准确性和覆盖范围。
具体来说,我们想解决以下两个问题:
- 给定一张图片,查找之前在 Pinterest 上是否使用过相同的图片(或轻微的变化,也就是 NearDup)
- 给定一张图片,找到 Pinterest 上使用的所有相似图片的列表
出于实际原因,Pinterest 使用的整个图像世界被分解为一组不重叠的集群。 请注意,相似关系不是传递的,因此使用近似关系来划分图像。 对于每个集群,都会(随机)选择一个代表成员并将其用作集群 ID。 更具体地说,我们使用图像之间的以下关系来表示不相交的集群:
- 图像(又名簇成员)到规范图像(又名簇头)
- 集群成员列表的规范图像
本文的其余部分重点介绍实时管道的设计和实现。 请注意,本文不是关于检测图像相似性,而是关于如何实时进行。
挑战
Pinterest 上的大量图像在可扩展性和稳健性方面提出了一系列挑战。 下面给出的数字可以让我们一窥我们正在处理的规模:
- 在 Pinterest 上保存的 Pin 图数:300B
- 每秒图像创建速率:~100(峰值为 200)
- 集群成员数量:平均 6 个,但少数集群高达 1.1M
鉴于信号的重要性以及如果信号延迟/损坏可能产生的影响,我们必须从一开始就将以下方面纳入系统:
- 易于调试
- 信号的可解释性
- 实时和长期监控信号的健康状况
- 在发生灾难性故障时重新处理图像子集的能力
- 能够尽可能无缝地从批处理管道切换到新管道
设计与实现
对于每个新创建的图像,我们运行以下步骤来检测相似图像:
- 从视觉嵌入中提取 LSH 项
- 查询自定义搜索引擎(使用 LSH 术语索引引导)以识别一组潜在候选人。 根据与相关图像匹配的词条数量对候选者进行排序。
- 使用基于 TensorFlow 的分类器评估候选集。 我们使用经验确定的阈值来过滤掉不匹配的图像
- 如果检测到类似的图像,则识别集群并更新存储。
整个系统构建为 Apache Flink 工作流。 在高层次上,一旦嵌入准备好,就会触发相似性计算。 Pinterest 的媒体团队已通过 Kafka 提供通知。
架构图
本节给出的图表显示了管道架构的本质。
流与流的连接
相似度计算使用不同的嵌入(部分用于历史目的)进行 LSH 和机器学习评估。 通常嵌入在几秒钟内可用,并且管道使用流-流连接来同步多个嵌入的可用性。
Manas:自定义搜索引擎
我们使用 Manas(Pinterest 的可配置搜索引擎)通过 LSH 词匹配来寻找潜在的候选图片。 上一篇博文中解释了如何使用 LSH 术语识别相似图像的详细信息。
由于我们需要根据重叠项的数量对候选者进行排序,因此搜索集群已针对延迟的正确性进行了优化。
与传统搜索引擎不同,我们的用例通常需要扫描整个语料库,并期望返回具有最高术语重叠的结果。 广泛的文档扫描确实对搜索基础设施造成了压力,并且需要严格的速率限制来规范搜索查询的速率。
一旦计算出相似度分数,搜索索引也会更新以使新创建的图像可搜索。
Tensorflow模型保存
我们利用 Pinterest 的名为 Scorpion 的 ML 服务基础设施来评估选定的候选图片。 考虑到问题的规模(峰值时,每秒评估近 50 万个实例),模型服务使用较好的优化,如 GPU 和微批处理以获得更好的性能。
存储与服务
如果检测到重复图像,则需要更新底层存储以提供映射服务。 如上所述,我们在存储中持久化了两种关系:
- 图像到簇头的映射
- 簇头到簇成员列表
图像到簇头的映射很简单,并且存储在 RocksDB 的本地变量中,它为我们提供了低延迟和线性可扩展性。
然而,簇头到成员列表的关系是一个更复杂的关系,因为簇大小严重倾斜(平均大小为 6,但少数簇达到一百万左右)。 簇头到成员列表的关系在 Pinterest 自己的名为 Zen 的图形存储系统中存储为图形(节点是图像,边缘表示簇头到图像的映射)。 使用图存储的主要原因是利用其分页支持来获取边(如果没有分页,K-V 对将具有非常大的 V,这将限制其在在线 K-V 系统中的使用)。
这些关系通过称为 Galaxy 的通用信号传递系统提供服务,该系统提供低延迟的信号获取。
引导现有关系
我们利用 Flink 的文件观察器功能来引导 RocksDB 和 Zen 图形存储。 历史数据被转换为 Flink 工作流程可以理解的模式,并保存在 AWS S3 上的目录中。 工作流中添加了一个文件观察器操作符,以观察 S3 位置并将数据批量上传到存储系统中。
管道的可操作性
该管道的设计和实施具有可操作性。
可调试性
由于管道很复杂,我们通过 Flink 算子实现了特殊的调试数据传播。 调试详细信息被推送到 Kafka 队列,并使用 Pinterest 自己的名为 Merced 的可扩展 Kafka 物化基础设施进行持久化。 系统还内置了功能,可以选择性地将图像 ID 提取到管道中,并实时检查中间结果,以便更好、更轻松地进行调试。
监控与告警
除了使用 Flink 提供的标准指标外,我们还有许多自定义指标来衡量管道的健康状况。 还有每小时运行在物化 Kafka 日志上的作业以测量覆盖率和其他标准指标以检测模型偏差等。
处理失败
我们构建了以下工具来处理故障和错误:
- 在管道中的任何主要组件发生故障时回滚到良好状态的工具
- 通过强制将图像更改为簇头映射来修复误报的工具
未来工作
最初以图像为中心的管道发现了从静态图像到动态 Pin 图(如视频和故事 Pin 图)的应用。 此外,它还可以推广到处理存在近重复关系的任何类型的数据,从而为未来提高效率创造机会。
本文为从大数据到人工智能博主「今天还想吃蛋糕」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://cloud.tencent.com/developer/article/1946401