Chat with Milvus #15 回顾-混合查询功能要来了?Milvus 未来增加Scoring & 按阀值搜索功能?...

| Milvus Q&A 与文字实录


Attendee= 参会者

 

Attendee A:我看你们以图搜图的基本上给的例子都是一个 general 的图,比方说是个牛、羊、人这样。我想问的一个场景就是说假设我们针对这个文档图片的这种搜索,当然OCR(Optical Character Recognition,光学字符识别)是一个方向,但我们想假设我们不用 OCR 有没有什么方式可以提取这个 feature,然后能更快的找到和文档比较相似的另外一个文档的这样一个图片,就从纯图片的角度去考虑这个问题?

 

顾老师 @ Milvus:你的场景能不能跟大家介绍一下?因为文档如果你是纯用图片来搜文档的话,如果你用白纸黑字的那种的话,我觉得应该会比较的困难。因为从机器视觉的角度来看,模型来说,白纸黑字的东西其实都差不多。

 

OCR 当然就可以把文字具体的提取出来,你可以把文字提取出来,你再做关键词搜索也好,或者再做语义的搜索也好,我觉得都还能处理。如果你只是想从整体图片上的话,我觉得感觉现在的这个模型应该都没有为这些去做。

 

Attendee A:因为我看你们基本给的例子都是说我一个图片出了一个向量,我想问一下有没有什么方法,比方说我一个图片出了不止一个向量,然后我再去做一些搜索之类的东西?

 

顾老师 @ Milvus:也可以阿,你先做一次目标的侦测,看看这当中有一些什么样的目标能提取出来。 因为是这样,就是说当然现在也不是所有的目标都提取出来,可能人们比较关注的一些什么动物的或者说人脸的这些这些对象能够提取出来,相对来说你是可以针对这些对象做一些有主题的搜索,这是可以做到的。包括我们现在给的以图搜图的例子当中,其实它应该是可以在图片框选一部分去进行一个特定区域的搜索,我们现在的例子当中是可以做这个的。当然那个例子比较简单,还没做这个事,但是我们接下来会给大家发一个开源的以图搜图的一个东西的话,它就会结合一个目标检测,然后先提取这种相关的目标,然后再去进行搜索,会有这样的元素在里面。所以你主要是关注什么领域的?

Attendee A:我的场景就是说,可能我这边有一些 general 的文档,然后可能用户他不一定说像我们扫描仪或者怎么着,做的特别干净规范了,然后 OCR 实际上像用户比方说手机随便照了一张图,但是实际上 OCR 有很多时候的效果并不好,就是有些乱七八糟的东西。所以我想问一下图搜图这个东西是不是说可以解决相关的问题?

 

顾老师 @ Milvus:这比较困难,除非这个文档是一模一样的。


Attendee B:我比较感兴趣的是向量检索它索引,如果我除了检索向量能不能复合一些其他的字段,比如说一些整型的字段?比如说我还有一些数字字段一起复合的查询?

 

顾老师 @ Milvus:这个是我们在接下来,应该是下下一个 release,会做一个这种向量结合属性的混合查询。当然属性我们一开始会相对来说规定得简单一点,它都是一种编码的属性,这个属性可能就是 12345,这 12345 什么含义,可能就是在你自己节点创建个码表,就有点像阿里云上的以图搜图,它电商的场景就是这样,1 就是上衣,2 就是裤子,他会给你加一个码表,这相对来说会比较简单一点,而且它会性能会好一些。因为这些属性它其实我没有存的话也得和向量存一起和索引存一起的,所以属性的部分如果占的比例太大的话,其实对于内存什么都会有一些的影响,所以我们会先把它做一个比较简单一点的方式。所以您这边主要关注的是一个什么样的场景?

 

Attendee B:我这边可能还是图片为主,做一些比如说相似相同图的召回。

 

顾老师 @ Milvus:你的图片当中是有标签的是吗?

 

Attendee B:对,比如说像你说的这种像衣服,比如说图片的,比如说它的质量这样的一些东西。

 

顾老师 @ Milvus:因为现在我们是可以做一个分区,在整个的 collection 上可以分区

。分区是根据一个属性字符串来进行分区的,它的属性字符串它可以是一个联合的,比如说它也可以是一个红色的车或者红色的小孩这种方式,去构建这样一个字符串,来作为它的属性去区别它的分区。这方式不是特别的灵活,但在一些场景下也能够帮到大家现在。你们现在图片大概会有多少呢?

 

Attendee B:图片应该不多,可能五六千万。

 

顾老师 @ Milvus:五六千万的话,我们最近有一个做企业大数据的用户,他是做企业的商标搜索,差不多是 5500 万的图片。还是比较快的,大概几十毫秒。

 

Attendee B:几十毫秒是那种 batch 的,还是说一张一张这么查下来是几十毫秒?

 

顾老师 @ Milvus:一张一张这么查下来,因为它的场景是一个互联网 APP 当中的这种场景,所以他都是一张一张这样子的。

 

Attendee B:确实还是比较快的,如果我要是有 5000 万图片,我们是对服务器要求大概是多少 G 的内存?

 

顾老师 @ Milvus:这个的话您可以在我们的网站上面,我们有一个 sizing tool,在上面

你可以把你的数据量,然后你所选的索引类型输入进去,它就会告诉你大概会消耗多少内存。

 

Chat with Milvus #15 回顾-混合查询功能要来了?Milvus 未来增加Scoring & 按阀值搜索功能?..._第1张图片


 

Attendee C:我们现在向量实际上都是会落盘的对吗?但是我们提供的主要功能还是去检索的,然后这时候检索的实际上是返回到它的向量的 ID 对吧?这个时候我其实是可以利用 ID 去检索到它对应的向量的值的对吧?我想知道你们这边有没有测过读向量的时候,这个性能是怎么样的?

 

顾老师 @ Milvus:通过向量 ID 拿向量这个功能之前的实现确实是有点慢。大家反映取向量本身比搜这个向量要慢的多一些,这部分我们在后续的版本当中是在不断的优化性能的,因为我记得好像是接下来的 6 月的版本当中应该是会对从 ID 获取向量的性能会有一些提高的,因为我们尝试了一些不同的实践的方式。通常来讲您是什么样的向量存在里面,需要去把这向量取出来呢?

 

因为之前我们好像是有一个音频类的用户,他是做音频类的这种 app,他们好像提到说他们很需要把向量取出来。听下来感觉是说用的场景是类似于说是一种推荐的场景,可能是一种传统机器学习的稀疏向量,那个向量它可能是带了一些用户的标签的属性的,所以他想把这个向量拿出来。我不知道您这边把向量取出来的原因是什么样子的呢?也方便我们更多的了解。

  

Attendee C:我这边的话是文本向量,拿到原始向量的话,是为了送到排序,一个是送到打分模型里去打分,因为它相当于一个特征。

顾老师 @ Milvus:对,但你打分模型是什么样子的呢?因为我理解是你搜完把它最接近的都找出来,不就可以了吗?为什么会要对这个向量本身去进行一个打分的计算?

它是个什么样的原理,你能不能给我们介绍一下?

 

Attendee C:它是一个文本分类的原理,我们所有的拿出来都是相当于是句向量,然后我们会输入到一个文本分类模型里面,然后把召回的这些向量输入到文本分类模型,会拿到一个它属于各个不同类别的分布的概率,然后这个概率的值实际上是我拿过来做排序的一个条件。

顾老师 @ Milvus:就是说相当于说你搜索完一遍之后,其实还是需要做一些 scoring。其实这个就是我们在上一次的 Chat with Milvus 讲整个整体的成长期的愿景当中也提到了,我们是希望把 scoring 的功能也放在 Milvus 里面,这样的话你拿你的向量出去就是为了做一次 scoring,如果我们可以在 Milvus 内部就给用户开放这样的 scoring 的自定的接口,相当于说你就不需要再传输这些向量出去,我可以内部就帮你全部都做完,搜索完再做完,scoring 再把结果返回给你,这样的话效率会高一点。

 

Attendee C:对,我们现在的做法就是把它写到了缓存里,但是非常吃内存。

 

顾老师 @ Milvus:对,肯定的。所以回头你可以跟我们分享一下您这个 scoring 的模型它的算法大概是什么样子的,我们也想看一下说这块它的 scoring 的复杂度究竟有多少。因为我们其实像支持混合查询、多模态,然后用户自定义的 scoring,这些其实我们都想去做,但是 scoring 这块的话,我们还是想知道用户究竟他 scoring function 的复杂度是什么样子的?能不能够沉淀在 Milvus 引擎里面,还是说我们会需要一个插件附着在 Milvus 的外部或者上面一层。所以很需要大家的这些反馈,然后让我们去更好地设计未来功能怎么去实现。

 

Attendee C:明白,我们现在这个模型是一个双向的 LSTM 模型。

 

顾老师 @ Milvus:所以他在做最后的 scoring 的时候,就是每一条向量去进行计算,然后给向量打一个分就可以了是吗?

 

Attendee C:对。

 

顾老师 @ Milvus:所以你比如说在您这边的自然语言处理的场景当中,其实是先从模型到向量,然后再由向量进入一个打分的模型,就是从模型到向量再到模型,最后出现了一个我不知道你的结果一般会是一个什么样类型的结果?

 

Attendee C:我最终拿到这个分布之后会综合一些特征,然后拿个排序,最终会返回一个文本。然后我还想问一个问题就是说,因为我们现在存储的这方面实际上是 LevelDB 和 RocksDB 这种类似的结构,但是他们的读的性能都很慢,你这边后续的优化的策略是什么呢?

 

顾老师 @ Milvus:后续的优化策略的话,应该其实是可以做一些索引的。我不知道在你们的自然语言场景下,你们会给向量指定 ID 吗?还是说可以接受向量系统自动生成?

 

Attendee C:这个的话一般情况下我们是自己有一个 ID 生成的工程,给他先去拿一部分 ID,然后把向量匹配上,如果新的向量来了, ID 不够了,我再去拿 IP 是这样的,相当于也是系统生成的 ID 但是可能生成的方式不太一样。

 

顾老师 @ Milvus:其实相当于是你们的在应用这一层,还有一个全局的 ID, 希望在所有的系统当中都用这个 ID。这块的话我们是在想怎么样去优化,今天有一些思路,之后会在群当中给你回复,跟大家介绍一下。

 

我们其实这个月最重要的工作,就是在给我们所有的 Milvus 做 reference,就是让大家更能够了解背后的一些原理,因为现在的文档可能更偏向于是一个简单的使用指南,就是这个东西怎么弄,然后参数是什么,但是对原理的介绍目前是比较欠缺的,所以这部分我们是在这个月其实是集中精力在补充这部分的内容。

 

Attendee C:这个挺好的,我因为这样看源码有一部分参考,但因为有的时候那就是内部设计还是比较复杂的,看起来挺头疼的。然后我还有一个问题是我们虽然现在的都是单节点的,我想做成高可用节点的这能怎么办?你下面的向量好像没有这种就构建完索引没有同步的机制。

 

顾老师 @ Milvus:是的, 我们现在分布式的方案相对是一个支持分布式扩展,并没有兼顾到高可用的需求,高可用我们之前更多的是类似于这种 keep alive 的方式去做的(可产考 Milvus实战 | 基于Keepalived的高可用方案)。然后数据的共享还是交给了这种共享存储去做到这样一个不同节点之间的共享。因为这部分的话从先期来看的话,大家对于分布式集群的需求其实就是说问的话大家都会说需要,但是在实际的使用场景当中,从目前的角度,我们发现在这块 AI 相关的东西的话,其实更多的可能还是受限于成本和硬件的规模,其实大家很多的都还是在这种单节点的在做部署。所以我们前期的精力都集中在把单点的性能和功能和它的稳定性都能够先做好。我们现在单点也增加了WAL (可参考Milvus之WAL介绍)去提升整个单点的可恢复性。

 

在后续的话确实我们也在考虑怎么去把分布式扩展,其实我们已经有一些思路,但是怎么去结合高可用这些的话,我们还是在研究当中,看看怎么找到一个能够让大家都觉得比较合理的方式。因为其实分布式的问题大家都很关心,但是分布式如果带来了比较多的内存消耗的话,大家可能在成本上也可能不能负担,所以这个东西我们也很纠结应该是什么样子的。


Attendee D:我们这边在构建一些 embedding 的东西,但是它的量都比较大的,可能差不多在四五亿这样的一个级别。然后我们是希望有一个离线的这种 batch 的方式去把两两的去计算两个 pair 之间的相似度,并不是点查的那种方式,所以我在想是直接用你们开源产品,还是说我们在基于这种 Spark 去构建一个这种分布式的离线的这种计算这样子,其实我这方面没有什么特别经验,想和你们确认一下。规模大概是四五亿的这样一个规模,然后每一个点可能大概是在 50~100 的这样的一个 dimension。

 

顾老师 @ Milvus:每个点在 50~100 维其实还好。

 

Attendee D:我初步的一个想法,是不是我就遍历一遍就好了。我所有的这些 item,然后我就遍历一遍,然后就可以算出每一个 item 对应的那个 pair 对的相似度,我不确定这样的玩法行不行。因为我了解到很多用这个 tool 的话,它都是一个点查的这种方式。

 

顾老师 @ Milvus:其实批量也是挺多的,但是你刚才说的搜索,你是要求什么样的相似度?就是说比如说你的一个批量,我假定说有 100 条,每一条你是要查它的相似度是查什么呢?是他的这四五亿当中和他最像的前 1000 个吗?还是前 100 个这样子?top多少?

  

Attendee D:其实我们有几种场景,其中一个场景就是说我们是需要...其实不是那种 KNN 的方式,我们是需要两个, 就一个 pair 我们会算出一个相似度,比如说算一个 Jaccard 相似度。

 

顾老师 @ Milvus:你这一个 pair 怎么理解呢?

 

Attendee D:比方说两个 item 之间,我们会把它 embedding 成一个向量,然后再用比如 Jaccard 或其他一些 metrics 去计算相似度。

  

顾老师 @ Milvus:就是你计算 Item A 和 Item B 的 Jaccard 相似度。那你在做批量的时候,你的意思是说比如说我取出了一个 Item A 我需要去和这四亿条都做一次相似度的比对?

 

Attendee D:我们是想找出超过一定阀值的所有 pair,比方说他超过一定阀值但它并不是超过一定数量。

 

顾老师 @ Milvus:这个向量是从深度学习的模型出来的吗?还是一些规则生成的?

 

Attendee D:你可以理解成是模型出来的,所以说里面应该不会有太稀疏的东西在里面。

 

顾老师 @ Milvus:明白。所以这种情况的话,其实很多的人使用我们去都是在做批量的,但是当中有一个就是说,我们现在主要是支持的是这种取 Top 的形式去进行搜索,就你 top 1000、top 500 这样子。Threshold 的这个方式,就是我们会在未来的版本当中进行支持,但是现在的话我们并不是按 threshold 来支持。

 

Starlord @ Milvus:我有一个小问题,像阀值的话你们在实际中是怎么定阀值的?

 

Attendee D:阀值现在没有一个特别好的自动定的方式,也是需要有一定探索的。

 

Starlord @ Milvus:或者说为什么你要定阀值,用 topK 做不会更好一些,为什么你那个场景一定要有阀值?

 

Attendee D:就是说你要定义它相似度的话,因为相似度的话它肯定有一个量,比如说你是你要多相似,你是要 0.9 的相似度还是百分百相似,还是百分之六十的相似,但是其实相似的话我们并不知道,比如说我们定了个 70%,我们并不知道 70% 的相似里面的  pair 会有多少。

Starlord @ Milvus:对,所以其实在深度学习这个领域里面,其实没有这个说法,说70%的相似度的,就是这个东西是无法去衡量的。或者说你发现你物品 A 去换了一类物品或者换了一个模型以后,你这个阀值都会有很大的一个变化。

 

所以其实如果你要用阀值去做一个裁剪的话,这可能是一个永远你都不知道阀值怎么选的一个无解的问题。之前我们也探讨过这个问题,可能比较难(实现)。物品 A 跟物品 B 这个去比的话,就说他这样的阀值的话,你会发现差异会特别大。

 

顾老师 @ Milvus:这个我觉得这个要看,因为他刚才讲到的是 Jaccard 相似度,所以你 Jaccard 的相似度背后的实际的东西是什么?什么东西抽象成的向量?

 

Attendee D:我们现在一方面有可能是在 Risk 的场景去用的,所以说不是特别方便透露特别多细节,但是基本上我们之所以没有考虑到取 topK 的那种用法的话,因为我们现在是没办法知道我们跟它相似的是我们需要抓取的 k 是要定多少好。

 

Starlord @ Milvus:明白, 你刚才说的 risk 的话,我大概会理解你的含义的。因为就是说在金融做风控这样一些领域的话,其实你也是不能说用 topK 的,因为 topK 的话你有很大的一个这种 false positive 是这样的话你是不敢要的,对不对?

 

Attendee D:是的。所以我感觉像这种场景的话,用我们这个工具的话,我就非常暴力的去遍历一遍,我不确定这种做法可不可行。

 

顾老师 @ Milvus:暴力的去遍历一遍当然是可以的, 还是回到这个问题,你的服务的  SLA 是什么样子的,如果你只是每天跑一次批量,形成一个 report 的话,其实你遍历一遍也行,因为他可能给你的 SLA  的时间会特别长,那其实你怎么做空间很大。那如果你想做一个实时风控的场景,你希望在比如说出现问题的 5 分钟之内得到提示,或者说甚至 30 秒钟之内得到提示,你肯定就需要不能暴搜,你肯定得去用 ANN 的方式,这样的话你才有可能去做实时风控的事情。 

 

Attendee D:实时是另外一种策略了,我们现在只关注离线的这种。然后我现在想我是用 Spark,然后再加上实现一些 ANN 的算法去分布式的去把这个事情搞定了,还是直接单机去部署一个我们开源工具就直接用了,还是在探索的过程当中。所以如果你们那边有一些已经现成的一个经验的话,我可以借鉴过来,然后我就直接用了。

 

顾老师 @ Milvus:我觉得这个可能还是要看你这个服务这个 report 它的时间限制是多少。

 

Attendee D:这时间限制基本上比如说你在五六小时以内能够跑完其实也就 ok 了,因为一天只需要跑一次。

 

顾老师 @ Milvus:对,那种低频次,然后又是有五六个小时的这种窗口去跑的 report,其实你应该是有很多种选择的,你可能就会选择一个成本比较低的,像 Milvus 这种的单机去做,相对来说你四五亿的这种 50~100 维的,单机应该是都能支撑下来去做。Spark的话,我不知道它集群可能还是需要几个节点去做的,但是这个东西可能你得自己实测一下,因为五六个小时你不是很在乎时间的,你就看成本我觉得。

 

Starlord @ Milvus:如果你觉得阀值这个东西的话,是一个你们必须要做的一个东西的话,有产品的话,你也可以去 GitHub 给我们开一个 issue。我们是一个比较开放的这种社区的治理,我们的技术委员会去 review 用户提出来的这样的一些需求,然后我们会去定的话,下一个版本我们要把它用优先级。所以你把它提到 issue 里面的话,也许我们下一个版本,甚至再下一个版本也可以考虑去支持你用阀值去做一个搜索。

Attendee D:我们组里面有别人提过用那个 FAISS,这两个平台的话会有什么区别?

 

顾老师 @ Milvus:是这样,FAISS 因为是算法库,如果你用 FAISS 的话,你的数据文件可能得自己做好一些备份。因为也经常有人反映说在使用的过程当中,数据文件会损坏。Milvus 这边的,我们虽然是吸收和改进了 FAISS 的算法,但是我们底层的文件数据管理其实还是自己做一些工作,就是格式也是不太一样的。对这部分至少目前为止数据文件损坏的情况,在我们的用户当中还没有反应过。

 

Attendee D:从性能上来说会有什么区别吗?

 

顾老师 @ Milvus:就是说我觉得如果你的机器有 GPU 的话,那么因为 Milvu s在做这种  GPU 的计算的时候,其实还是为批量场景考虑的非常多的。像 FAISS 算法库它是把 GPU 的那些数据会常驻在 GPU 当中的。那其实显存是非常小的,虽然你这四五亿的 50~100 维的向量也不能算特别大,但是一两块 GPU 肯定是放不下。因为 Milvus 的话,它其实是不是常驻 GPU 的,它就是我们 Milvus 在使用 GPU 的时候就是把它当成一个批量的处理器了,它就是会把数据不断的复制到显存,然后进行计算,然后再出去。所以其实单块  GPU 卡也能够去一定程度上加速你的过程,虽然他会有一些内存不知道显存的时间开销,但是因为你是一个批量的,而且大规模批量的场景,所以这些复制的时间是比较可以忽略的。

 

Attendee D:所以说我的理解就是说我们可以在比较低成本的基础上面去应对一些大规模的这种向量索引,相比 FAISS 的话。我再多问一句,就是说如果说我的那个数据在 Milvus 内存里面,在 CPU内存里面放不下的话,也可以支持吗?

 

顾老师 @ Milvus:可以换入换出的,我不知道你们机器是私有化部署吗?还是说是云服务器?

 

Attendee D:是私有的,就是自己的。

 

顾老师 @ Milvus:私有部署的话,我们后续也会找英特尔的傲腾( AEP ) 来测试一下,看看在内存有限的情况下会不会提供更好的 I/O 性能。但是就是说你如果内存不足的话,其实因为文件我们是把数据分片存了很多个文件,很多的文件我们是可以进行置换的,在内存和磁盘间进行置换,他可以 swap 进来,swap 出去,所以这个不是一个问题。

 

Attendee D:那 AEP 的话可能就得再重新购买主机了,因为我估计他好像对 CPU 对主板有一定需求的好像是。

 

  

 

| 欢迎加入 Milvus 社区

github.com/milvus-io/milvus | 源码

milvus.io | 官网

milvusio.slack.com | Slack 社区

zhihu.com/org/zilliz-11/columns | 知乎

zilliz.blog.csdn.net | CSDN 博客

space.bilibili.com/478166626 | Bilibili

 

 

你可能感兴趣的:(Chat with Milvus #15 回顾-混合查询功能要来了?Milvus 未来增加Scoring & 按阀值搜索功能?...)