CV CUDA在微博多媒体内容理解的应用

20230725182007e54ee9545bdbb385b1488526cc883c07f867f6276

一、微博多媒体内容理解的背景介绍 

2023072518200845e56cd95d74d7c2ed978730f042f6d7766b1a774

首先和大家分享多媒体内容理解的背景,多媒体内容主要包含视频,音频,图像和文本的理解。在视频的理解里边,有很多非常重要也非常基础的一些工作,比如视频的 embedding 标签,视频的质量,视频的摘要、封面等等。图片的理解同样,图片的理解也是非常重要的,因为在微博的场景里面,图片是占比较大的一类数据。主要的工作包含 embedding 标签,图片 OCR 了,人脸识别。在这一系列的算法层上面,支持了公司非常多的业务。最基本的,比如个性化推荐内容的审核,物料标签版权,视频的指纹,视频拆条等等一系列的业务。

以上就是微博多媒体内容理解的总体的一个结构。

下面会分 4 块的技术的内容做详细说明。

二、视频摘要(Video Summarization) 

20230725182008a89f19402345da786091084f6b44154219af03763

1、技术背景

视频摘要的主要目的是对于一段相对比较长的视频,采用算法抽取一部分帧,或者一部分连续的帧,也可以是单独的一帧去表达视频。使观看者在看完摘要后能够大致理解视频所要表达的主要内容,一般有两种摘要的方式。

第一种是静态的摘要。这项技术很早之前就有了,最常见的一个应用就是视频的静态封面怎么去抽取,其实就只抽取一帧,这一帧可能会包含了比较丰富的信息。使用户看了这一帧就能大体知道这个视频的内容。比如讲的打篮球还是踢足球。第二种摘要是动态摘要,从视频里边选取一段或者多段连续时间的视频帧作为摘要,这种可以作为物料的审核或者物料的打标。还有个应用是视频的动态封面,比如有一些 APP,它的视频是有这种动态封面的。物料审核主要针对某些涉及政治或者色情的视频,以及版权侵犯的场景等,可能是需要人工去审核。这种场景人工在审核的时候,如果对于原始的视频去简单看一遍,是非常耗时的。先对视频进行一定程度的浓缩,是可以极大的节省人力的。

2、业界做法

2023072518200873a8887200b37b0c72866967f8c03cc1f1348e378

(1)dppLSTM(ECCV 2016)

业界之前比较普遍地做法,第一个是 ECCV 2016 的一个方法,这个方法其实它比较早,但是它特别有代表性。这是一个有监督的方式。首先人工去标注这一帧,是不是比较关键的一个帧,以及这一段是不是比较关键的一段。

这个模型的输入是从一个预训练的模型去抽取每一帧的特征向量,然后供两个 LSTM 模型在时间维度上建模,它会算一下当前帧与其他帧的关系。再接一层 MLP,这一层主要会预测当前这一帧它的重要程度,当前这一帧它跟其它帧的相似度。最后再有个模块,基于这两个分数值,去判断当前视频帧的集合里边哪一些是比较重要,哪一些是适合的。

这个方法比较常规的一种做法,需要人工标注,但人工标注其实非常的难,不同的人去标,可能标准很难去统一。第二就是非常耗人力了,对于视频,需要一帧一帧的标注。

(2)SUM-GAN(CVPR’ 2017)

右边这个图是 2017 年的一个方法,它是一种无监督的方式,非常类似于现在比较火的对比学习的技术。

首先这个模型它分成了四大块,sLSTM 模块会给输入的帧打一个重要性分数。这样相当于有了每一帧的向量和重要程度。然后,这个模块会根据重用性的程度把向量去做加权,重新去算向量。生成模块会根据重用性程度加权之后的向量,再去恢复视频的原始向量,然后把恢复的向量跟原始的向量做对比,看恢复得好不好,如果恢复得好,就可以说明帧的重要性算对了。反之就没算对。所以整个过程是一个无监督的过程,因为它是个已知的原始向量去对比的过程。

(3)CSNet(AAAI’ 2018)

2023072518204887b6f52572b3e9c167c5930d14e943db14726a560

视频处理的时候,对于长视频这种以远程的关系建立时间建模,是比较难的一个问题。上面左图是 AAAI’18 年的论文,它的一个侧重点是解决当时间跨度比较长的情况下,怎么去建立帧与帧之间的关系。

首先每一帧向量进来通过 CNN 以后会分成两块,第一块按照它原有的时间顺序切成一个一个的段。第二块在时间维度上,会跳着挑一些帧,比如挑第一帧,第四帧,第八帧,它把 148 放在一块,相当于把不同时间跨度的帧放在一块,这有利于对远程帧的向量的一个感知特性的感知。另外,是类似于 attention 的一个方式。比如这一帧跟第四帧去比一下,跟第八帧去比一下,根据差异性来判断这一帧的重要性,差异大说明重要,类似的话说明不重要。最后就根据 tension 和原始上传的向量去做一个融合,最后再去预测分数。这种方法它主要是解决了长视频的一种建模的方式。

(4)DR-DSN(AAAI’ 2018)

右边这个图也是 2018 年的一篇论文,首先它在原来的基础上能做到无监督。第二个,当时来讲,它的效果是比较好的。

跟前面的方法一样。首先把每一帧都向量化,再做双向的 LSTM 网络。它的不同点在于,把整个训练建模的目标变成了两个。这样做有两个目的,第一个是去度量多样性,最后摘要出来的这一段必须是比较丰富的内容。第二个是选出来这些关键的片段和尾帧是具有代表性的,能够代表原始的视频。这样从比较长的视频,选出来的片段会具有多样性,相互之间重复度是比较低的。其次还能代表原来整个长视频的内容。整个过程不需要任何的监督的信号,所以它是一个无监督方式。

3、微博的工作

20230725182103770f44264b449da0cc335981f17b348141d9ee745

前沿的这些做法其实各有各的优点,也各有各的缺点。微博结合我们自己的业务场景,做了我们自己的模型。当然有监督的这种方式我们基本上就不用考虑了,因为太费人力了。无监督的这种方式相对来讲,相对于有监督来讲,它在效果上会有一些差异,会有所降低。但我们在探索怎么样可以在不需要人工标注的情况下,还能做到一个比较好的效果。

下面是微博特定场景里面做模型的一些动机。

在微博多媒体的场景里,事先有视频分类这么一个模型,这个模型它其实抽出的特征是有一定的语义信息的,训练视频分类的时候,标签是一致的。因为微博场景里面有大量的这种数据,所以这个模型是比较容易得到的。当时基于这一点想去虚拟一个弱监督或者无监督的模型。弱监督是因为用视频分类模型去做监督,所以称它为弱监督。这个图就是整个的算法结构。当然这个方法的论文是在 2021 发表的,如果大家感兴趣,可以去仔细地去阅读一下论文。

20230725182009185dd3d364253ad352b851e2933b1a955cec42806

首先视频会抽成帧,然后每一帧都会去抽到一个向量。之后会使用一个比较常规的算法。比如用一个镜头切割的算法,把视频切割成 5 个镜头或者是 5 个片段,每一段把这一段里的向量做一个平均,得到的向量就代表了这一个片段的特征,这一个代表片段的特征会被放到视频分类的模型里面去,这个模型的作用就是,输入是一串向量,输出是一个向量,并且因为后接一个分类。可以拿分类层的前面特征作为最后的视频的一个表达向量,这样多个镜头通过上面的分类网络,就可以得到唯一的向量。

然后 Summary Generation Sub-network 的部分会根据输入的镜头的向量去做选择,选择一些镜头作为最后的摘要的片段。当然也是采用了潜量的一些做法,用 LSTM 去建立镜头与镜头之间的关系,同时每一个镜头会预测到一个分数,再根据分数去选择一些片段。

那么最后这个片段选得好不好,用一种什么样的方式去衡量呢?这里设计了四种的监督方式。

第一种就是选出来这个片段,仍然送到视频分类网络里面去,这个时候多个镜头向量,最后可以得到一个向量。如果选了这个片段是比较好得到的向量,那么就和所有的片段进去之后,视频分类网络得到的向量是一样的了,或者至少是高度相同的。所以可以把它作为一个基因多信号,在语义层次上,选出的这些片段,能够跟原来整体视频的语义层次是相同的。那么选出来的这些片段,它本身需要一些什么样的约束呢?

第一个,选出来的片段必须有多样性,这一段与另外一段肯定是不同的。如果是相同的,就不需要去重复地选。第二个,它是具有代表性的,原来视频的某一段,可以在选出的片段里面找到一段在语义层次上比较相似的。最后一点就是选出的这些片段在时间上应该是有个约束,不应该让模型在极端的情况下,比如把原来所有的片段都选上,不就是涵盖了所有的语义吗?这样肯定是不需要的,所以加个时间长度的一个约束。最后所有的约束项一共有 4 项,4 项里面后面的三项都是无监督的。第一项是根据视频分类网络的监督信号算出来的,所以总体上不需要去额外的标注一些信息。当然视频分类网络是有监督的,所以这个方法称为一个弱监督的方式。

20230725182010d19254045157f684085273a16ad5e176feab3a148

这种方法在做前向推理的时候,上面视频的分类网络就可以扔掉了,因为那个只是作为训练时候的一个监督信号的来源。来了新的视频之后,就走下面流程,每一帧去抽向量,做镜头的切割,再算镜头向量,再过我们的摘要网络。最后可以得到每一个片段的分数,这一个片段里边我们认为每一帧的分数都是一样的。

20230725182010c46699a2185f49e3cc351560b2e7994754a463291

上图展示了我们跟有监督和无监督的一些方法去做对比,我们作为一个弱监督的方式,但是跟有监督对比也还是有优势的。跟现有的一些无监督的方式,我们的这种方式性能相对来讲会更好一些。图上下面部分展示了我们当时的方法,跟业界最好的方法做了一个具体的,在视频上做了一个对比。我们看了抽出来的摘要信息,其实更符合,至少更符合我们微博场景对于摘要的一些需求。同时在开源的数据里面,摘出来的片段其实哪怕跟当时最好的方法相比,也是很有优势的。图片最下面是我们论文的地址。

4、具体应用

2023072518201146deebc36b90fa8fdee810a9cba30c89c66420422

下面介绍视频摘要在微博的应用,以及在什么样的场景下面去使用。第一个是静态的封面,对于一个长视频,一般会选择比较重要的一帧去作为视频,在没有播放的时候作为一个封面展示在前面。第二个是动态的方面,作为封面,可能在时间的长度上面是有一个约束,比如不能超过 3 秒或者 5 秒,所以动态方面会从整个视频里边去抽,连续一段持续 3 秒的得分数最高的一段去作为动态的封面。第三个应用场景是物料的打标,打一些标签和物料的审核,这样人只要一看摘要,就基本上能够知道这个物料怎么去打标,或者审核过不过。如果有疑虑,再去看原始视频,这样能够大大的提升人工的效率。

三、视频质量 

202307251820111503dba7860e97257b505244b8a8101f7bd883217

1、技术背景

视频质量的主要目的是通过使用深度学习产生统一量化的质量指标,从而可以根据质量对视频进行推荐或者打压限流。

几个图展示的是一些具体的例子。什么样的是质量不好的,比如拍得比较模糊,或者是拍摄的时候焦距不够好,或者是这种运动模糊。

2、业界做法

20230725182012f70d3d210cfb8e3e2f16630a2038d25bd56782689

首先看看业界以前是怎么去解决视频质量这个问题的。这个大致架构比较常规,大部分论文都采用的这么一种结构,可能有些在这个结构上会做一些小小变动。

每一帧进来之后,首先过一个 CNN 网络拿到 feature map,然后在 feature map 做 global pulling 得到向量。向量再通过一个 GRU 从而建立时序的关系,然后可以得到每一帧的质量分。再根据每一帧的分数通过 pulling 或者其他一些方式计算视频的总体质量得分。

3、微博的做法

在微博的场景怎么去解决这个问题?能否用现有模型呢?经过实验,发现现有模型不是特别适合微博的场景。因为像视频质量,一般没有一个唯一的标准,是一个相对比较主观的评价。开发的视频质量评价模型需要符合微博的业务场景。那么从微博为什么需要视频质量评估这个问题本源出发,之前其实一直有人工持续的在标注数据,通过与标注人员的沟通,了解他们是怎么理解视频质量标准的,我们再从中总结一些经验,设计出符合我们视频质量评价的算法架构。

20230725182012981963972ae5748f6e021111dea06fff8b525f991

我们采用的是递进式的处理方式,也可以说是层次的一种结构。我们先从帧级别去判断,从帧级别再上升到镜头或者片段的级别,再从片段级别上升到整体视频的级别。

上图是这个算法模型的整体的架构。首先输入的是视频帧,每一帧都一个位置编码和一个事先算好的能够代表这一帧质量的 embedding。那么这个 embedding 怎么算呢?先分析完这个总体结构之后再详细介绍。视频帧输入之后过 Transformer 结构。就 Transformer 我们针对视频质量场景做了特殊的设计。过 Transformer 之后,就可以把第 0 个第 1 个位置作为最后预测视频质量分数的输出。上图左边就是设计的 Transformer 结构的,输出有两块,一块是帧的向量,第二块是代表初始的视频的质量。这是一个需要学习的量。我们会把视频帧切断,每一段在内部去过一个 Transformer 结构,这里的两段 Transformer 结构也是有两个输出,每一帧会输出一个 embedding。这个 embedding 的含义会描述这一帧的质量,同时还有一部分是代表了这一个片段的质量。这样的话,多个片段,每一段它都会有 embedding 代表这一段的质量。最后再把段的质量做一个融合,通过 Transformer 结构做一个融合,把它 pulling 起来,然后因为是从段级别进行融合,就能够代表视频整体的质量的情况。这里帧的向量也会作为输出。因为下一个还是一个完整的 Transformer 结构,也是作为一个输出,这样输入输出可以使我们堆叠多次 Transformer 的架构。

2023072518201282f81c7189d75f4e04292544392f59780346ca917

那么初始的帧向量是怎么来的?因为我们有大量的这种基于图片的质量评估的数据,所以可以从通过图片质量数据训练出来的一个模型中抽取向量,最后得到一个 128 位的向量作为视频帧里边的向量。

20230725182049c6c382f33263678a12b09562e56193c2abca36254

上图是我们的方法和业界的方法在开源数据上的一些对比的结果。从结果上看我们的方法还是有一些优势的。因为我们会从帧级别,段级别多个维度去考量视频的质量。

4、具体应用

2023072518201402c547c74c69ef29852011335bcd89114c9188796

在做推荐的时候,首先有一个物料池,给某一个人推什么物料肯定都是来自于这个池子的。通过一些策略或者一些模型去做召回,完了之后再做一个排序,最后再推给最终的内容的消费端。所以我们应用点有两个。

第一个是判断视频是否放到物料池,需要对质量分数做一个阈值,作为其中一个条件,协同其他条件或者模型最后做综合判断。第二个应用的地方是精排和粗排,排序的时候会优先推荐视频质量好的物料。

四、文字识别

1、技术背景

20230725182014088235e7633eeb8f95c4676ec803e3ef00f904261

文字识别其实是很早就有的一个算法,经历了一系列的发展。最初的时候是要求图片的背景需要比较干净,这样检测起来比较容易,分割也比较容易。

到了现在,因为图片是各种各样的,比如有自然场景的图片,比如路边的招牌或者店的招牌这种信息。场景里面这种图片,它的字体以及大小是各种各样的,是非常复杂的。第二种是网络图片,比如网络的截图或者广告上面的图,微信的截图之类的网络的图片。第三种是文档图,比如一些扫描件。第四种是手写体,手写体是非常难的。

2、业界做法

20230725182015a6cd17f3729108e4c7498632e059bf9a7040d8659

文字的识别基本上有两个大块的内容,第一个是文字的检测,第二个是文字的识别。文字的检测就是输入的是一个图片,算法要去确定这个图片的哪个位置有文字,然后用框给框出来。文字识别就是输入前面这个框把图像给抠出来之后,过文字识别模型,然后就能够输出这一块图像里边包含的是什么字。最后输出的其实就是文本。

文字识别的发展大概可以分为从两阶段模型到现在的端到端模型这么一个过程。两阶段模型是指把文字检测作为一个单独的模型,检测完了之后再做文字识别,它又是一个单独的模型。这种方式计算成本是比较高的,因为需要过两个网络。发展到最近几年变成了一个模型,这一个模型它既能做检测,又能做识别,这样效率就是非常高的。

20230725182015896139694c31a7e8c1a074579f7daa8b6b8ada202

文字识别,尤其是中文的识别,难度是比较大的。第一个是中文不管是字符还是整行,做检测的时候比较难。第二个是中文的字符特别的多,常见的汉字就超过 3000,还有很多不常见的,这么一算估计得上万。另外,现在很多论文,一些开源的算法,基本上都是在英文场景下去做的,直接搬到中文的场景下,效果会打一个折扣。

20230725182015f4492c4209ba4696487766956cc01c604744bb798

检测文字的检测,早期的时候基本上是当成普通的目标检测的方式,比如用 Fast-CRNN 或者 Yolo 模型去检测。对于水平的文字,用这些模型检测一般是没问题的。然而随着发展,对倾斜的文本需求也越来越大,所以大概在 2017/2018 年的时候,就有一些论文去做倾斜的文本检测。这些检测的方法除了预测框的坐标以外,还要预测一个角度的信息,所以就能够检测倾斜的文本。最近几年,因为算法越做越复杂,需求也越来越复杂。有很多文字的边不是直的,可能是弯的。最近的一些论文想去攻克这个问题,怎么样去检测不是一条直线的文本。它的大概思路基本上是不一次性就把整个文本的位置给预测出来,而是分块的。比如以 TextSnake (ECCV2018)为例,它通过预测一个圆参数。比并以它为中心去预测一个圆的半径,从而画出一个圆,通过圆边把文本区域检测出来。

20230725182050f49719b44cbd4c1703d03163fc2c7785b66d49582

上图是最近 5 年比较有代表性的论文。在 4 种不同场景下,最近 5 年的论文的数据表现除了文档类的指标比较高以外,其他三种场景其实指标都不是特别高。尤其是在手写体上,其实提升是非常非常难的。

普遍方法还是做完文字检测之后,比如用 CNN 抽特征,在特征的基础上去建立序列之间的关系。一般有做 LSTM 的,或者 Attention 来做的,大部分思路都是这样子。最后再做一个 CTT 的这种解码。

20230725182016c3989c236fc09b51d076932c483b7392fa3969254

前面主要是把检测和识别是分开的,这里介绍的是端到端的模型,就是它就能做到既检测又识别。这种方式最早的一篇非常有代表性的论文是 FOTS(CVPR2018),它在当时是效果非常好的。上图下部列举了端到端模型的主要流程结构,首先输入图片,然后是一个特征抽取的网络,一般来说都是使用 CNN 来抽取特征,然后通过金字塔方式去用多层次特征或者用 U-Net。最后这一块 Text Spotting 的部分回去探测文本的位置,然后识别。 

3、我们的做法

20230725182016547d59d279257c9a9808511b7fd68f5667933d985

具体在微博的场景下,早期的时候也是采用 2 阶段模型,因为当时 1 阶段模型还没有,或者不是太成熟,现在也改到使用端到端模型。采用的基础架构是 FOTS 这种方式,因为在微博的文字识别场景里面,它能够节省大量的集团资源。当原封不动地去采用它的结构,上图上面部分是 FOTS 原始的结构设计,有个主干模型和特征金字塔。它会用主干模型里边不同层的 feature map 去构建金字塔结构。相当于能够产生检测和识别的特征了。特征再给到检测模块,它可以输出文本的位置。检测模块的输出是一个矩形框,这个矩形框它有可能是倾斜的,所以识别的时候,需要做旋转,再用得到的坐标去特征金字塔里边把特征拿出来,然后再给到分支模型去给识别模型做最终的识别,识别出最终的结果。

但是原始 FOTS 检测和分支是共用的一个特征金字塔,经过测试了之后发现,在微博的场景里面,如果共用,尤其是识别中文的情况下,它的效果不是特别好,因为它的原始论文是在英文场景下做的,毕竟英文的识别比中文要简单一些。我们做的唯一的改动就是把特征拆开,检测是检测的特征,识别是识别的特征,就是这么一个简单的改动就非常大地提升了我们在中文字符识别的效果。当然,由于共用了主干模型,我们的计算还是非常高效的。因为特征金字塔,它的计算复杂度也不是特别高。这里就看看在微博场景里面,文字识别在什么样的场景去用。

4、具体应用

20230725182017e570cd995e9b2a8565e31230d2ba051fc3a8c1868

第一个是视频里的文字识别。有一些视频在上传的时候,它就会配一些比较重要的文字,一般这几个文字基本上就能够代表了整个视频的内容。所以我们把它识别出来之后,第一个是作为文字,可以跟我们的博文拼到一起,去做一些内容的理解。第二个就是在做视频打标的时候,它也是可以把文本和视频画面结合起来,作为一个模态的输入做视频打表。

第二个是图片文字的识别,在微博场景里面有很多产品的介绍,比如上图右侧,这些文字一般对于理解这张图片来讲是非常有意义的。所以我们把文字识别了之后,再根据图像的特征去对这张图片去做一些理解,不管是抽 embedding 还是分类,都是可以用上的。

第三个是头像文字的识别,在比较特殊的一些场景里面,比如色情的场景,头像里边有一些特殊的字,就是为了吸引别人的。我们也对头像会用 OCR 去识别。

第四种场景是证件文字的识别,有一些用户,他是需要认证的,比如企业需要拿营业执照做认证,所以营业执照上面信息,我们也是通过 OCR 去抽取,如果纯粹靠人工去的敲字,第一方面是容易犯错,第二个是人力成本。所以我们也是通过算法的方式来做识别。

五、视频embedding

1、背景介绍

20230725182017a19f983150452450e55798da925c5f19235280364

视频 embedding 在微博场景里面,很多业务都有需求,但是不同的业务对 embedding 的要求是不一样的。比如版权保护,它对 embedding 的要求是比较细致的。为什么?因为版权保护没法完全用算法来确定视频是不是侵权了。因为版权的确权是没法用算法完全确定的,肯定是需要人工去审核的。人工审核的时候,他就需要明确地知道这两个视频从第几秒开始到第几秒结束,他是侵权的,需要精确的时间节点。如果整个视频单独的一个向量,肯定刻画不了这个信息。所以对于这种场景,视频会按每秒去抽一帧,每一帧都会有个相应的向量,这样能够算出时间的信息。

第二种比较典型的需求就是视频的去重。视频的去重大部分应用在推荐的场景,对于具体是在第几秒发生重复它不是特别的关心,它只需要知道这两个视频有多长时间,它重复的大概位置就行。有一点点偏差是可以的。这个时候抽取的时候我们会把视频给它分成段,每一段有个向量,这个时候我们是能够判断出两个视频它有多长是重复的,同时可以节省很多存储的资源,因为每一段一个向量数明显会少很多。再一个应用是视频广告的检测,广告通常也是一段一段的,所以可以按段来做匹配。

第三种是推荐场景,可能有时候需要从整体上、从语义层次上理解视频。他希望的是一个视频就一个向量或者一个 ID,这样可以嵌到推荐的精排算法里边去做具体的推荐。不同的业务有不同的需求,那怎么样去用一个统一的算法架构去满足不同业务需求?

20230725182018f36eb64380decae45fa58073a72054b0841878147

上图展示了我们整体的视频 embedding 的架构。输入有两种信息,一种是视频的画面,另一种是视频的音频画面。按每秒去抽帧,每一帧会训练一个网络去抽帧的向量。网络的训练方式是通过对比学习的方式去训练的,是一个无监督的任务。下面的音频也是一样,会把音频按照每秒切成一段,每一段抽出一个向量,训练的方式也是比较相同的。这个时候我们每秒都有一个向量,这个向量是可以解决版权这种要求比较高的业务。我们把向量称为帧的向量。

第二种向量,我们把它称为段的向量,段的向量是把帧的向量融合成的一个向量。会单独用一个模型去做这种融合,这样就可以满足视频去重的要求。那么为什么视频去重不直接用帧向量去做去重呢?就是考虑到资源的问题,去重会对过去几个月的数据进行去重,每当有个新的视频来了之后,要去看过去几个月里有没有视频重复。如果过去几个月的视频量是非常非常大的,可能会超过 1 亿或者 2 亿。那每一个视频去抽 200 帧,这个库里面可能有几百亿个向量。如果要这样子去检索恐怕是不太现实的。所以必须把向量的数量降低,所以才会按照段来抽取向量。

在这个项目的基础上,还会对整体视频的描述会抽一个唯一的向量,这也是从通过一个模型来算最终的视频级的向量。这个向量就可以用到具体的视频推荐业务里面去,也可以用来做视频的聚类。当然还有很多其他应用方式。

2、具体应用

20230725182018065c69498b317ebd0e25423734c05156cd1b52881

以上介绍了视频 embedding 的一些典型的应用场景。当然应用场景非常多,我主要是列了一些比较重要的。比如第一个版权保护的,我们库里边存的是帧的向量,这个时候其实库不是特别大,因为具有版权的视频,它量不会特别多,所以可以用更加精细的 embedding。第二种是视频去重的功能,我们用的是段向量,可以相对于帧向量来比,去重库所占的资源是比较小的。第三个是标签的复用。标签复用它的场景是这样,我们有好些个物料都是人工标注的,这些标注的信息是高度准确的,所以把这些向量和对应的标签放到一个库里边。来了新的视频之后,先看看有没有跟他高度相同的视频,曾经人工是标过的,如果已经标过了,直接给他打标签就可以了。第四个应用是视频的聚类,也是应用到推荐里面去的。为什么会有视频聚类这么一个特征?通常来讲,视频的理想化刻画有分类的方式,但是分类有一个限制,一个模型训练了几个分类,就只能支持几个视频类别的分类,通过聚类的方式,可以是作为分类的一种补充,可以是不同层次的聚类。比如可以根据向量去聚 1 万个类,这个时候相当于有 1 万个标签,甚至聚 10 万个类都可以。这样相当于标签就有不同的层次,比如是 1 万类,10 万类。并且这个时候是不需要监督信号的。在推荐的场景,也是取得了比较好的推荐的效果。

六、CV-CUDA在微博场景的应用

20230725182019d814b8149068b55ca7d2710aab8724aa501b44693

一般来说视频处理的传统做法是先把帧在 CPU 的环境里边解码,把原始的字节流解码成 BGR 数据,再做一些常规的操作,比如 resize 的、crop 之类的,再把数据上传到 GPU 去做具体的模型的运算。

202307251820511460570952554d83b098150dd724dc1196f9d4289

而应用 CV-CUDA 之后,处理方式是 CPU 解码之后,在内存里会有 JPG 的字节流,再把字节流上传到 GPU 上做解码。当然这个解码也有可能不完全在 GPU 上,这跟 CUDA 的内部属性有关。假定它就在 GPU 上,这个时候所有的预处理都是在 GPU 上,所以就可以跟具体的模型无缝的衔接,而不需要显存到内存的拷贝,或者内存都显存的拷贝。

20230725182019824b2c728a38c17d870426408801406cb240c4387

从算法层面和 OpenCV 做对比。即使是使用 OpenCV,也可以调用 CUDA 的解码函数在来解码 JPG 数据。所以上图 OpenCV 部分会划两个流程。第一个流程是解码在 GPU 上,然后把 GPU 上解码之后的图像数据拷贝到 CPU,再走 OpenCV 的预处理,处理完之后传到 GPU,再次过模型。第二种方式是 OpenCV 自己的函数在 CPU 上去解码,再走后面的流程。CV-CUDA 的部分,图像先传到 GPU,然后解码预处理再次过模型这三个步骤都是在 GPU 环境。

20230725182020c1aeab250578406d8741813595a513cc08a80b283

在算子层面是分开来对比的。OpenCV 用 CPU 的方式来解码,CV-CUDA 用 GPU 的方式来解码,都加上预处理。途中蓝色部分是模型的消耗时间,橘黄色部分是解码消耗的时间。可以看到在微博视频处理的测试场景里边,解码是非常耗时间。因为处理的是视频,每一个视频它有非常多的帧,每一帧都要去做解码,所以它耗时相对会比较长。

绿色部分是预处理的耗时。基本上 CV-CUDA 的预处理耗时可以忽略不计,可能也跟我们的预处理不是特别复杂有关系。可能在你的环境里面测,如果预处理的复杂度特别高,可能会有不太一样。

20230725182020c44113c98f01660a7bc2088c25e57d1bc20526813

上图是 OpenCV 使用 GPU 去做解码的情况下,去对比这个效果。最下面还是模型的运算时间,中间是解码的时间,因为都是 GPU 解码,所以耗时是差不多的。在预处理这一块,CV CUDA 已经做得非常好了,预处理时间是非常非常短的,整个 pipeline 的对比也是有提升的,大概 50% 左右。

20230725182021e265cc0518df80077789980d0f5447650a8980943

最后一块的内容,具体在微博线上具体的业务中,在线上去做的测试,我们的目标是在限定的硬件场景里边,怎么样去充分利用硬件资源,做到单位时间处理更多的数据。上图可以看到用 OpenCV 去做预处理的时候,整体的 CPU 的利用率基本上已经已经涨满,达到 300%-350% 。但此时它 GPU 的利用率它是偏低的,低于 10% 了。整体  pipeline 的 QPS 是零点八六,指一秒钟处理零点八六个视频。上传 gpu 的意思是用  OpenCV 需要 GPU 上传的数据量。

再看 CV-CUDA 的一些性能数据,相对来讲,它的显存会占比较多一些。因为它把原始数据在 GPU上做解码,相当于做了展开。这样原始的图片在 GPU 上显存上,它肯定会占得多一些,内存的占用会少一点。这个时候它的 CPU 利用率降低了,同时 GPU 的利用率提升了,整体的 QPS 提升了 70%,同时上传的数据量减少了非常多。从资源的利用来看,通过两个方面来讨论,第一个是考虑 CPU 的利用率,要把 GPU 打满,在 GPU的利用率只有 10% 的情况下,需要十倍的 CPU 才能把 GPU 打满利用率。而对于使用 CV-CUDA 来说,CPU 和 GPU 的总体利用率会比较均衡。能够使用更少的 CPU 资源把 GPU 的利用率拉到最大。

七、问答环节

Q1:请问有总结如何排查预处理瓶颈吗?

A1:预处理瓶颈在你的整个 pipeline 里面,你先得知道你的预处理在你整个 pipeline 里面占的时间占比是多少。比如你占比多,肯定预处理是有提升空间的。如果它整体占比少,那基本上的耗时都在你的模型上。预处理做得再好,也不会对整个 pipeline 的提升也不大。

Q2:没太弄明白刚才您的 10% 是怎么算出来的,可以再讲一下吗?

A2:这个会跟测试的环境有一定的关系,这个地方可以初步地去算一下,如果 GPU 利用率是 10%。能把 GPU 打满的情况下,Open CV 需要多少个 CPU 和 CUDA 需要多少个 CPU 这样子去算的。

Q3:您说训练框架用的是 Python 是吗?有 demo 可以参考一下吗?

A3:我的分享主要是 CV-CUDA 在我们推理的环节里边去做的。训练框架我们都是用的PyTorch,Demo 因为涉及到我们具体的业务场景,涉及到我们业线上的代码。不是特别确定能不能分享。

Q4:您介绍的 Open CV 与 CV CUDA的效率对比,那里图表可以看到预处理速度有很大的提升。这里对比的预处理里面包含了 resize,包含了是如何打 batch 的。表中 batch 的 128 如何对比的细节可以再介绍一下吗?

A4:预处理是包含 resize 的,如何打 batch 的话,CV-CUDA 本身就支持 batch。如何对比,这个是在一个限定了资源的情况下,我们通过多线程或者多进程的方式,把资源用到最大的情况之下去做的对比。对于 OpenCV,我们会采用多线程的方式,CV-CUDA 会打 batch。

Q5:业务 pipeline 总共是多少个算法?是刚才讲的所有算法都包括了吗?

A5:我这里讲的只是其中的四个比较有代表性的。因为时间有限,我没法把所有的都介绍一遍,所以就从这里面挑选了 4 个比较有代表性,同时也是挑使用了 CV CUDA 做了测试的场景的算法进行了介绍。

Q6:镜头分割时,有的非常短,有的有很长,是怎么控制的?

A6:其实长短对于我们的理解来讲,影响不是特别大,可能有一些极端的情况。镜头的切换比较频繁,这个时候可能会产生一些比较短的镜头。但是我们镜头的切割它只是第一步,后面还有模型去做这种预测和融合,所以它即使切得比较短,也不会太影响最终的结果。可能后面的模型里边会根据前后卷的关系以及一些语义的信息做一些融合。

Q7:推理或者训练的时候从远程拉图片数据比较慢,微博是怎么解决的?可以介绍一下吗?

A7:拉数据,训练或者推理拉数据。我们因为我们公司内部的集群都是万兆的带宽,目前拉数据。可能我理解你是不是你把数据拉到本地,又要下载纯实盘。通常我们的做法是我们拉取图片数据的时候是不会落到磁盘的。如果只是作为推理或者训练,直接拿到内存,直接根据 jpg 字节码去做解码了。包含 OpenCV,它也有这个功能,不需要存磁盘的。如果你去存磁盘,因为受到磁盘的性能的影响,可能会有影响速度。我们的做法是在内存去解码 jpg 数据。另外一点是,把图片数据下载,解码,预处理,模型计算进行并行化,各个模块间通过队列进行通信。

Q8:请问 embedding 向量是多久更新一次?

A8:embedding 向量的更新,更新的频次是根据业务上的需求来定的,我们通常在确定了更新之后导致的效果差异,在一个可以接受的范围之内,我们才去做更新。如果业务上认为我们 embedding 不好的时候,我们才会去更新的。

Q9:详细介绍一下视频分段 embedding?

20230725182021581770545741b88e66b156ab0f220a0ec368b5349

A9:其实这个图我是画了一个统一的结构图。在训练的时候,它可以用 3 个 loss 来训练。但是具体在我们做的时候,其实是分开来训的,当然你要做成统一的训练也是可以的。所以这个地方训练每帧的向量,它是有一个对比学习的。这个时候是通过数据增强的方式,包含语音也是一样,也是通过数据增强的方式来做对比的训练。有了帧向量之后,再去训练段向量的时候,这个时候也是包含语音和视频的片段,也是做一些增强,这个地方去做了一个对比学习。

至于向量对比学习,我们会做一些不仅仅是通过增强的方式,因为增强的方式很难去把视频增强得非常的丰富。在我们的场景里面,还是有一些比如话题,比如标签之类的带有标注性的信息,有时候会使用增强,有时候会比如从同一个话题里边抽取,通过一些规则去筛,基本上基于这个规则之下,我知道这两个视频它有一定相同的语义含义。数据扩展这一块,第一个方面是有正向,第二个方面是通过规则筛出来的,它是一对正样本的数据去做对比学习。

© 版权声明

相关文章

没有相关内容!