前言:本文转载自InfoQ,原链接如下。本人为作者之一。
InfoQ官网文章
InfoQ微信公众号文章

腾讯信息流亿级别相似视频识别技术架构优化实践

作者:邹建勋,袁易之,常郅博

1.信息流业务背景介绍

信息流是一种可以滚动浏览,持续给用户提供内容的数据形式。信息流源于内容信息平台,兴起于社交媒体、新闻资讯类平台。 信息流内容会出现在外观相似、一个接连一个显示的版块中。近年来,信息流内容市场发展迅速,通常内嵌在各类App中,由平台主动推送,用户的抵达率高。而通过对用户的行为偏好进行跟踪分析建立算法推荐模型,当内容足够丰富时,可以为用户主动推荐无限多感兴趣的内容。
随着各类视频App火爆,目前短视频已经成为信息流中最重要的流量窗口。短视频碎片化的内容突破了空间、时间、人群的限制,广受用户欢迎。同时, 其个性化、平民化的传播形式和语言表达,也契合了用户的情绪价值。
视频内容理解主要负责视频的理解分析和加工处理,是视频信息流生态中重要的组成部分,也是其核心财富。而相似视频识别是内容理解中非常重要的一环。

图1 短视频信息流形态

2.为什么需要相似视频识别能力?

随着短视频业务不断发展,吸引了越来越多的优秀内容创作者前来发布,同时也出现了一些搬运号搬运内容的情况。这些内容或完全相同,或只是添加了水印、花边、裁剪、旋转、滤镜等干扰因素。

图2 搬运内容的形态

这些重复或相似的内容,可能会带来以下影响:
● 对用户来说,它们都是相同的内容,若重复消费,则会给用户带来不好的体验。
● 对业务来说,这些重复内容的处理,会浪费大量的机器资源和审核的人力资源,显著增加内容处理成本,限制业务规模。

因此我们需要构建相似视频识别的能力,用来对重复的视频进行去重。此外,相似视频识别的能力在推荐打散、搬运号识别、低质识别、品牌采买等场景也能得到有效收益。

本文将围绕相似视频识别技术展开详细介绍,包括架构演进、工程优化、组件沉淀等部分,希望能为有相同诉求的读者带来一些启发。

3.亿级别相似视频识别的挑战

不同人群对于相似视频识别能力的需求各不相同。对用户来说,推荐池中一旦存在重复视频,就很容易被推荐系统基于画像反复推荐,因此从用户体验考虑,需要更重召回;对号主来说,一旦判断错误,视频被误打击,号主这条视频就不可能再被启用,因此从号主体验考虑,又需要重准确。

综上,我们的相似视频识别能力既要保证足够高的召回率,还必须足够准确,这就需要对多个环节进行全面优化。

3.1原有架构存在不足

早期的相似视频识别架构相对简单,整个去重的流程基本在一个服务中就完成了。比如很早就支持标题去重服务,整个流程包括:对标题提取特征向量,向量写入样本池;然后用此向量检索样本池,召回相似标题;再对召回的相似标题进行校准,是否真正重复;最后做出决策,是否进行去重拦截。

但后来我们发现仅标题去重无法满足产品发展需要,于是仿照标题去重又新增了视频的画面去重、封面图去重等等。系统架构变成了如下图3所示:

图3 早期去重架构

这种架构存在多种问题:

1. 单机存在性能上限

最初每一种召回服务的样本池都是自己在内存中管理。服务都使用大内存机器,进行单机部署,同时部署1台冷备机器。主机读写时,与备机进行强一致性数据同步。这样的架构很明显存在性能上限,无法利用分布式的优势。

2. 各去重模块相互耦合,无法利用多种判断结果,重复开发工作量大

对于仅标题重复、画面不重复的视频,如果想要做到不拦截、只打标记,在原有架构下是无法完成的。因为标题去重服务在决策的时候没有画面信息和封面信息。

以一个非常简单的需求为例:调整去重优先级,对不同层级的账号调整对应的优先级。要满足这个需求,上面三个服务每一个都需要调整,相当于三倍开发量。碰到复杂的需求,必定会浪费大量开发人力,同时这种重复代码也不利于维护。

3. 不利于扩展

如果以后需要新增召回策略,只能再次新增一个类似的服务,进一步加剧系统的维护难度。

3.2算法模型服务消耗大量成本

在我们的业务场景下,系统每天需要处理百万级的新增视频,我们需要对视频进行各个维度的特征提取、生成向量,用于召回和校准。而特征提取依赖的算法模型会消耗大量的机器资源,包括CPU、GPU和内存存储,存在极大的成本挑战。

3.3检索架构高可用问题

在我们的检索架构中会存储若干天历史视频向量,总体视频数量达千万到亿级,对应的抽帧图数量则达几十亿到百亿级。每新增一个视频,我们都需要在秒级的时间内,从几千万到亿级的视频库中,召回重复视频。

这些业务特点对于我们的相似视频识别架构、算法模型处理效率和检索架构高可用等层面,都提出了非常大的挑战。下面分别从这三个角度出发,介绍我们所做的一些优化。

4.相似视频识别架构设计

我们重新设计了整个相似视频识别的架构,采用分层设计,把特征提取、召回、校准以及决策分离开。新架构如下图4所示:

图4 新的去重架构

整个新架构共分为6层,自顶向下分别是:

● 预处理层:

预处理层负责对视频介质进行预处理,抽取1秒1帧的平均帧,以及场景切换的关键帧,同时提取视频中的音频,以及智能提取封面图。

这里为什么存在2种抽帧呢?因为我们发现它们在去重的效果上各有优势,无法相互替代。例如:有些场景切换比较频繁的视频,如果抽取平均帧时,时间轴刚好错开了,就会导致抽取的帧之间关联性很小,影响召回。反之,对于场景切换少,甚至静止类的视频,显然只用关键帧是不适用的。

● 特征提取层:

特征提取层主要负责对视频介质进行相应的特征提取。对于关键帧,提取为二值向量(值为0/1);平均帧提取为Embedding向量;音频提取为mfcc和chromaprint向量;标题提取为bert向量;封面图提取sift特征。特征向量存储至MySQL。在第3层中建立Faiss索引时,会读取MySQL中的向量。

为何需要多种特征和多种召回路径呢?因为业务对重复视频的定义是:只有画面+音频+语义,这三者都重复才算是视频重复。因此,任何单一的一种特征向量,都不足以判断视频是否重复。此外,即使2个视频的画面和音频都不重复,但标题或者封面图重复,如果这2个视频出现在用户的同1刷的展示列表中,也会带来不好的体验。因此,对这种仅标题或封面图重复的,也会进行召回,在推荐后台进行打散处理。

● 召回层:

召回层负责基于特征提取层中生成的各种向量,建立向量检索库,进行召回。我们使用的是内部基于Faiss之上开发的分布式向量检索引擎。对于每种向量,会建立一个相应的索引库,用于召回。

● 校准层:

校准层会对召回的疑似重复的视频pair进行校准。因为在召回层,我们更注重高召回率,会适当降低对准确率的要求,准确率交给校准层来保证。例如:视频A,召回了和B、C、D重复,则校准层会分别对A&B、A&C、A&D 这3个pair进行校准。校准的内容包括标题、画面、音频等维度,进一步识别这些pair的标题、画面、音频看是否真正重复。

● 决策层:

决策层主要用于处理业务逻辑,包含了大量业务规则。主要做的工作包括:识别到重复视频后,计算优先级,应该启用哪些、拦截掉哪些;同时,对视频A,生成类似的关系链形式:B|C|D,给到推荐端,进行去重或者打散;也会记录标题、封面、画面、音频等哪些维度是重复的。

● 监控层:

监控层用于监控整个系统的运行情况,统计每天去重识别的量级等多个指标数据。人工定期抽检去重掉的视频是否合理。同时,我们也建立了benchmark机制,用于准确评估整个系统的准召率。当算法模型或者工程服务有版本更新时,先在benchmark系统上进行评估,达标后再发布上线,减少系统风险。

通过架构优化,我们对整个框架做了更合理的划分,每一层各司其职,同时每一层都可平行扩展,使得开发成本和维护成本都大大降低,也得以更好地支持业务的快速发展。

5.算法模型服务性能优化

如前文所述,特征提取层和校准层主要负责提取视频的各个特征,会消耗大量的机器资源。本节重点介绍如何提高算法模型服务的处理效率,进而降低机器资源成本。

5.1PyTorch模型服务性能提升7倍

相似视频识别系统其中一路召回的特征模型,输出的是二值向量结果(0/1)。该模块基于PyTorch框架开发,采用的ResNet50模型,整体过程是将视频的每张抽帧图转换为N维的0/1向量。最初上线部署至Kubernetes pod容器(8核)上时,单帧向量化需3.4秒,但在同等配置的8核实体机上,只需0.46秒。

工程同学不断深挖,最终发现是环境配置导致的差异。PyTorch中默认使用了OpenMP并行计算来加速模型。如果不配置OMP_NUM_THREADS环境变量,默认会使用pod容器所在母机node的所有CPU核。母机node是64核,则模型在pod容器中会开启64个线程,每个线程试图去抢占CPU核。然而Kubernets只分配给pod容器8核算力,64个线程跑到一定时候会被内核强制调度让出CPU,此时中间的一些CPU Cache数据会失效,程序会被迫进行上下文切换。而频繁的上下文切换非常影响性能,导致64核比8核运行的性能更差。通过设置正确的OMP_NUM_THREADS,pod容器计算性能可以恢复至实体机的95%。

下图5是优化前后的耗时对比,最终性能提升了7倍。

图5 优化前后的性能对比

同理,使用golang开发的服务,如果没有正确配置GOMAXPROCS变量,在Kubernetes容器(整体核数>所需核数)上部署时也会遭遇类似问题。

5.2SKLearn模型服务性能提升9倍

在相似视频识别系统中,对召回的疑似重复视频pair,会提取其音频并转换为chromaprint向量,计算两个音频向量之间的海明距离,以此判定pair的音频是否重复。

该模型服务基于sklearn框架开发,使用了RANSAC回归模型。初期部署至Kubernetes容器时,一对2分钟左右的音频处理耗时需4.7秒左右,pod基本满负载运行。工程同学通过分析sklearn模型代码,找出了计算复杂度较高的top N步骤,发现其中之一是海明距离计算。通过对其进行优化,使用gmpy2代替自己计算海明距离,耗时降低到2.3秒。然后,在同等配置实体机上进行测试,发现处理相同的音频pair只需0.5秒。在代码和调用栈分析协助下,发现原来sklearn也使用了OpenMP进行并行计算。和上一节情况类似,如果没有正确设置OMP_NUM_THREADS值,pod使用的CPU核数会超过分配限制,被迫切换上下文,从而导致性能低下。

我们修改了适当的OMP_NUM_THREADS值,却发现在sklearn模型中并没有生效,翻阅sklearn文档也并没有找到相关的设置API。我们推测是模型本身对于线程做了控制,就尝试将sklearn模型转换为ONNX模型,通过使用ONNX提供的API设置适当的OMP_NUM_THREADS,最终把耗时降低到0.5秒。

图6 优化前后的性能对比

5.3ONNX Runtime加速模型推理性能提升8倍

如前文所述,我们通过正确配置Kubernetes pod环境参数,大幅降低了模型处理耗时。然而因为每天要处理海量图片,该模型仍然消耗了非常可观的机器资源。于是,我们尝试对模型本身进行推理加速,提高整体图片处理的吞吐量。

我们调研了ONNX Runtime、OpenVINO、TensorRT等模型推理框架,发现这些框架通过对算法模型进行层间的融合,如卷积+BatchNorm是CNN中常见的结构,而BatchNorm本身是线性操作,在推理时可以融合至卷积操作中,使计算量可以显著降低。同时这些框架也为卷积、矩阵乘法等耗时运算提供了一套性能较好的实现,使得推理速度相比于原生PyTorch有非常大的提升。

我们选取了ResNet50作为基准模型测试了ONNX Runtime和OpenVINO上的推理性能,其中ResNet50模型原生PyTorch推理速度为93ms,ONNX Runtime推理速度为38ms,OpenVINO推理速度为43ms,ONNX Runtime有2.45倍的加速比。

同时在重构推理服务的过程中,工程同学发现服务代码中遗留了算法同学的部分训练代码,存在PyTorch训练时的DataLoader逻辑,使得处理每个请求时都需要创建DataLoader和背后的进程池,在请求结束时再全部销毁。通过将此类冗余逻辑重构,处理耗时降低至35ms。相比加速前的耗时,性能提升了近8倍。

综上,我们通过优化模型服务的性能,不仅有效提升了服务的处理速度,亦可以大大降低服务成本。

6.相似内容检索架构优化

我们需要用新入库的内容去检索所有目前已经在库中的内容,根据某种度量方式,来判断内容是否相似。目前业界常见都是将视频整体或者视频帧转为Embedding向量进行检索。我们库中现在有几十亿的向量,如果暴力计算出最相近的K个向量(K-Nearest Neighbor,KNN),会导致服务计算量过大、耗时太长,在生产环境不可接受。所以我们一般都采用似近邻(Approximate Nearest Neighbor,ANN)算法,从而平衡线上召回效果以及检索性能。

6.1分布式向量检索

Facebook开源了一个ANN向量相似度检索算法库Faiss,但是Faiss只支持单机,在我们十亿量级下,单机根本无法满足需求。业界一般都会基于Faiss搭建一套自己的分布式特征向量检索系统。

我们的检索架构早期是一个单机服务,而视频量的快速增长,我们也逐步演进到集群化。目前我们使用的是公司基于Faiss库之上实现的一个高可用、高吞吐的通用分布式相似性搜索组件。

也正是因为这套组件是基于Faiss开发的,不仅继承了Faiss的众多优点,但同时也继承了Faiss的一些固有限制:

● 实时写入性能低

在我们的业务场景中,每天会有百万量级的新视频需要加入到索引库中。同时,每个新视频还需要实时检索,召回重复的视频。
前文提到过,索引库会保存历史N天的所有视频,量级在几千万到上亿级。如果我们只建单个Faiss索引,对这种量级的索引进行实时的混合读写操作性能很低,无法使用。

● 数据淘汰困难
索引库最多保存历史N天的所有视频,意味着每天需要从库中淘汰掉第N+1天的视频。众所周知,直接从Faiss索引中删除大量向量是一种非常糟糕的方案。

● 模型定期更新
Faiss索引的模型需要定期训练更新,不然会影响检索的准确度。但更新时不能中断服务,否则会影响线上检索请求。

6.2分布式向量检索管理系统

为了解决上述几个问题,我们设计了一套分布式向量检索管理系统。整体架构如下图7所示,主要分为两层:统一管理向量读写接入的Proxy 和索引管理系统Manager。

图7 向量索引管理系统

● 读写分离机制

我们采用大小两个索引读写分离的方式,来解决实时写入性能低的问题。其中大索引保存前1天至前N天的海量数据,只提供检索(读)功能,小索引保存当天的实时新增数据,提供实时写入和检索(读写)功能。因为小索引最多只保存1天的数据,量级相对小很多,足以支持实时的读写,性能满足要求。

如下图8所示:通过proxy写入向量的时候,会实时写入小索引以及存储db。而读的时候会并发读大索引以及小索引,然后proxy合并两者的检索结果。

图8 大小索引的读写分离

● 双buffer切换机制
Manager从逻辑上把索引数据抽象为两种类型。一个是工作索引,称为buffer0,提供线上的写入和检索服务,包含大索引(保存历史N-1天的海量数据)和小索引(保存当天数据)。另一个是备用索引,称为buffer1。

图9 双buffer索引

Manager每天会对Faiss索引进行重建,重建过程中,会淘汰掉N+1这天的旧数据,同时会重新训练Faiss模型。Manager分别重建好新的大索引和小索引后,即完成了buffer1备用索引的创建。此时,会触发索引切换,buffer1备用索引提升为工作索引。Proxy会把线上请求引入至buffer1中。buffer1变为新的工作索引,buffer0变为备用索引,其中的索引数据会被清空释放。

以此循环,再到新的一天,Manager会在buffer0中重建新的大索引和小索引,然后再把线上流量从buffer1切换至buffer0。buffer0变为新的工作索引,buffer1变为备用索引,其中的索引数据会被清空释放。

依靠双buffer每天不断切换,就可以解决旧数据淘汰和模型定期训练的问题。具体的索引重建流程可参考图7。

重建大索引时,Manager从MySQL中导出前1天至前N天的向量数据,按照约定格式,落地为N-1个文件。每个文件即代表某一天的全量向量数据,而文件的一行即代表某个视频或者某个抽帧的X维向量。由此可知,导出db数据时,自然就把第N+1这天的旧数据淘汰掉了,最终重建好的大索引,就不再包括第N+1天的数据了。

向量原始数据准备完毕后,即可按照图中step1至step6的步骤,进行索引重建。包括采样数据,训练Faiss模型,然后load数据至Faiss,进行索引重建。小索引的重建只需从MySQL中导出当天的向量数据,后面步骤同大索引。

● 多set索引机制

如上所述,采用读写分离能够解决索引的实时写入性能问题。但随着业务快速发展,视频量级不断增长,又出现了新的挑战:

1) 每天新增视频越来越多,小索引即使只保存当天视频向量数据,量级也不再小了,在可预见的将来,混合读写的模式会遇到瓶颈。

2) 大索引重建耗时太长。因为大索引保存的是N-1天的海量数据,数量在几十亿级以上,每天重建需花费数小时以上。

3) 空闲资源浪费。双buffer机制,意味着需要预留1倍的资源给备用索引使用。而这些预留的资源只在每天重建的那段时间才会用到,大部分时间处于闲置状态。

为了解决以上问题,我们引入了分set索引的机制。即,把大小索引数据拆分成多份(每一份称之为set),建多个set,每次只是将增量数据加入需要淘汰数据的那一个set,那么只需把那一份对应的数据重建索引即可。假设大索引分成m个set,那每天重建大索引时,只要将需要淘汰数据所在的那一个set重建即可,预留的资源只需m分之一。

这样既加快了重建的速度,也减少了空闲资源。

当然,proxy也会对分set进行适配。向量写入时,hash写入某一个小索引set中;检索时,会并发检索所有的大索引set和小索引set,合并检索结果。

图10 分set后的索引重建

通过分布式向量检索以及分布式向量检索管理系统,大大节约了我们的存储成本,也使得我们的内容管理和检索变得更高效,平行扩展也更方便了。

7.小结

在业务规模快速增长的情况下,我们重新设计相似视频识别的架构与分层,各司其职,使得各层可以快速水平扩展。对算法模型服务的性能优化,在内容量快速增长的同时,更好的控制了业务成本。

通过对相似内容检索架构优化,有效地支撑了在海量内容的相似内容检索。至此,亿级别的相似视频识别问题基本得到解决。后续我们也会持续优化,提升整套框架的易用性,可配置化,同时也会支持更多的底层的向量检索库,以适配各种不同业务场景的需求。

腾讯信息流亿级相似视频识别技术架构优化实践相关推荐

  1. 影视级跨平台视频制作技术的落地实践

    编者按: 近年来,视频形式的多元展现形式被更多行业所认可,视频技术在跨行业中的应用,被赋予了更多可能性与趣味性.不同行业间生产内容的多样性与差异化让视频内容升级的需求进一步提升,视杏科技作为专业的音视 ...

  2. 亿级短视频社交美拍架构实践

    https://www.jianshu.com/p/b73dcd2c03e7 本文系麦俊生在BOSS直聘主办的直聘学院「对话架构师」活动上的精彩分享. 一.短视频市场的发展 近几年来,短视频应用在国内 ...

  3. 亿级短视频社交美拍架构实战

    "在美拍的服务化过程中,主要基于 etcd 来实现我们的动态服务发现和配置服务,在 client 层面扩展实现了包含负载均衡.心跳.节点健康状态探测.etcd 节点挂掉的灾备等基础功能,同时 ...

  4. 架构 对话架构师:亿级短视频社交美拍架构实战

    麦俊生,美图架构平台深圳技术总监,曾担任新浪微博.奇虎 360 技术专家,从事高性能高可用架构设计开发工作,参与建设微博的 feed 和私信 IM 系统.负责 RPC 框架 motan.cache s ...

  5. 对话架构师:亿级短视频社交「美拍」架构实战

    本文系美图架构师麦俊生,在Boss直聘主办的直聘学院「对话架构师」活动上的分享整理,介绍短视频社交"美拍"架构实践的总结. 麦俊生,Boss直聘「直聘学院」特邀分享嘉宾.美图架构平 ...

  6. 腾讯云十亿级 Node.js 网关的架构设计与工程实践

    作者|王伟嘉 编辑|孙瑞瑞 本文由 InfoQ 整理自腾讯云 CloudBase 前端负责人王伟嘉在 GMTC 全球大前端技术大会(深圳站)2021 上的演讲<十亿级 Node.js 网关的架构 ...

  7. 腾讯万亿级 Elasticsearch 技术解密

    点击上方"方志朋",选择"设为星标" 回复"666"获取新整理的面试资料 作者: johngqjiang,腾讯 TEG 云架构平台部研发工程 ...

  8. 听腾讯 TEG 大佬谈腾讯万亿级 Elasticsearch 技术解密

    作者:johngqjiang,腾讯 TEG 云架构平台部研发工程师 Elasticsearch(ES)作为开源首选的分布式搜索分析引擎,通过一套系统轻松满足用户的日志实时分析.全文检索.结构化数据分析 ...

  9. 腾讯万亿级Elasticsearch应用及优化解密

    Elasticsearch(ES)作为开源首选的分布式搜索分析引擎,通过一套系统轻松满足用户的日志实时分析.全文检索.结构化数据分析等多种需求,大幅降低大数据时代挖掘数据价值的成本. 腾讯在公司内部丰 ...

最新文章

  1. 手机端html5展示pdf,pdf.js移动端展示预览打开pdf-pdfh5.js
  2. Linux学习---Day02
  3. 使用自定义的按钮替换默认的input type='file'
  4. nginx 实用配置问题总结
  5. android 电池高温关机,Android 关机问题分析指南
  6. MySQL 无符号和有符号的区别
  7. 关于Python的一些学习笔记(小白式笔记,持续更新)
  8. hsi i均衡化 java_基于HSI-mod的直方图均衡化
  9. 代理猎手(Proxy Hunter)教程(详细图文)
  10. document.getElementById/Name/TagName
  11. 什么是区块链----概念
  12. 测试报告应该包括哪些内容?
  13. 使用jqury的心得
  14. Vue中的视频播放插件( vue-video-player )
  15. J2EE基础教程(4):struts框架(视频笔记)
  16. UserWarning: Possibly corrupt EXIF data.
  17. matlab里面的sul,MATLAB语言在电机控制系统仿真研究中的应用
  18. 数据分析入门必知--数据分析流程
  19. 北邮网络安全-防火墙
  20. 富田刹车马达特点和用途

热门文章

  1. hitfilm 导出视频 the sample Rate (XXX Hz) is not supported by encoder
  2. 【JavaScript】实现简单的图片处理
  3. dataframe常用笔记
  4. iOS8开发之 PHAsset 保存图片到相册(相机胶卷) 详解三
  5. Jenkins + fastlane
  6. mas_makeConstraints与mas_updateConstraints与mas_remakeConstraints的区别
  7. 齐岳磷光金属铱配合物Ir(ppy-CH2-R)2(bpy-(CONH-C4H9)2)(PF6)
  8. 一年级新生家长php,一年级新生家长寄语【五篇】
  9. 直播源码开发,Android 屏蔽返回键(后退键)
  10. 周金瑞12.16黄金还会涨吗?黄金原油行情分析操作建议