通过深度学习的神经网络模型,可以将图片、视频、语音、文本等非结构化数据转化为特征向量。除了结构化向量之外,这些数据往往还需要添加其他属性。例如人脸图片,可以添加性别、是否戴眼镜、拍摄时间等标签;对于文本,可以添加语言类型、语料分类、文本创建时间等标签。由于这些特点,往往需要实现结构化数据和非结构化数据的混合查询。Milvus是一个开源的海量特征向量相似度搜索引擎。在此之前,Milvus已经给出了结合PostgreSQL实现混合查询的方案。解决方案是先在Milvus中进行特征向量的相似度检索,然后通过PostgreSQL对Milvus返回的结果集进行结构化属性过滤,得到最终结果。由于先进行向量相似度搜索,然后从相似度搜索得到的结果中筛选出满足属性条件的结果,可能会造成结果集的丢失,因为可能会丢失一些满足属性的结果集在向量相似性搜索中。已经被过滤掉,但是相似度最高的向量集不满足附加属性条件。得益于Milvus0.6.0新增的分区功能,上述问题在Milvus0.6.0有了新的解决方案,Milvus的应用场景也更加广阔(Milvus分区功能详解:Milvus0.6.0新功能:隔断面)。那么,Milvus分区函数是如何解决混合查询问题的呢?解决方案是将非结构化数据对应的多个属性标签组合成一个字符串作为一个Milvus分区的标签。特征向量将按分区存储。在根据对应分区中的属性进行检索时,可以快速得到非结构化和结构化数据混合过滤的结果。具体流程如下图所示(橙色线代表存储过程,蓝色线代表检索过程):本文将通过一个用例来详细讲解如何使用Milvus分区功能实现混合查询结构化数据和非结构化数据。场景描述库中有数亿张图片,通过深度学习模型转化为特征向量。每张图片都有对应的属性(图片获取时间、性别、是否戴眼镜)。知道了待查询图片的一些属性,需要在基础库中快速找到满足该属性且与给定图片相似的前N张图片。使用Milvus分区函数将具有相同属性的向量分组到同一个分区中,并将这些属性标签替换为字符串(例如:'2019-11-22/female/False')作为分区标签(Partition_tag)。搜索时,将过滤条件按照相应的规则转化为字符串,在一个或多个对应的分区中寻找相似的向量。选择分区时,支持正则表达式匹配对应的分区。数据准备本次实现的Milvus混合查询,从ANN_SIFT1B中BaseSet文件中的1亿条数据(128维)中提取特征向量,检索时从Queryset中提取特征向量。假设ANN_SIFT1B数据集是人脸特征向量。并随机生成性别、拍照时间、是否戴眼镜标签,将这三个属性标签组合成一个字符串作为分区的partition_tag。在本文描述的用例中,随机生成了总共十个分区标签。#随机生成性别、是否戴眼镜、图片拍摄时间等标签sex=random.choice(['female','male'])get_time=fake.date_between(start_date="-30d",end_date="today")is_glasses=random.choice(['True','False'])#将三个属性组合成一个字符串作为分区标签p_tag=str(get_time)+"/"+sex+"/"+str(is_glasses)功能实现1.特征向量存储数据准备完成后,需要在Milvus中创建一张表,根据上面生成的分区标签在该表上创建十个分区,每个分区都有对应的分区名和分区标签(每个分区名称和分区标签不能重复)。然后将向量导入到相应的分区中。同一分区中的特征向量具有相同的属性标签。数据导入Milvus后,返回的id是每个vector的唯一表示(id可以自定义):指定分区状态,ids=milvus.add_vectors(table_name=MILVUS_TABLE,records=vectors,ids=vectors_ids,partition_tag=partition_tag)2.特征向量检索将要搜索的向量传入Milvus。设置TOP_K=10,TOP_K表示搜索和查询向量之间相似度最高的前10个结果。搜索时,Milvus会根据给定的属性条件在一个或多个指定的分区中搜索(指定partition_tag时支持正则表达式)。由于分区标签是按照'time/sex/glasses'方式设置的,所以在查询前可以指定查询的分区如下。#知道所有属性(时间,是否戴眼镜,性别),明确指定一个分区$partition_tag1='2019-11-22/female/False'#指定部分属性对应的分区(性别)$partition_tag2='.*/male/.*'#指定分区对应一些属性(时间,性别)$partition_tag3='2019-12-21/male/.*'#指定分区在某月,性别为男:$partition_tag4='2019-12-.*/male/.*'使用欧氏距离计算指定分区中两个向量的相似度。查询时,Milvus查询结果会返回向量对应的id。#指定一个分区查询状态,results=milvus.search_vectors(MILVUS_TABLE,query_records=vector,top_k=10,nprobe=64,partition_tags=[partition_tag1])#查询多个分区中的状态,results=milvus.search_vectors(MILVUS_TABLE,query_records=vector,top_k=10,nprobe=64,partition_tags=[partition_tag1,partition_tag2,partition_tag3])Milvus在对亿级数据进行混合查询时,秒级即可得到搜索结果。上述方案的实现案例可以参考:https://github.com/milvus-io/..._hybrid_search与结合PostgreSQL实现的混合查询方案相比,基于分区函数的混合查询是更贴近实际需求,即先根据确定的属性条件进行Filter,然后在过滤后的向量集中进行向量相似度检索,最终的结果集会符合预期。当属性标签类别较少时,基于Milvus的分区函数实现特征向量和结构化数据的混合查询是一个不错的选择。其良好的性能、简便的操作和维护将为您带来卓越的体验。更多过往实战系列不容错过?Milvus实战|AI加速新药研发,实现化合物虚拟筛选Milvus在行动|基于Keepalived的高可用解决方案欢迎来到Milvus社区Milvus源码github.com/milvus-io/milvusMilvus官网milvus.ioMilvusSlack社区milvusio.slack.comMilvusCSDN博客zilliz.blog.csdn.net?2020ZILLIZ?
