精华内容
下载资源
问答
  • Milvus 笔记

    千次阅读 2020-10-01 23:38:53
    Milvus 能够帮助用户轻松应对海量非结构化数据(图片/视频/语音/文本)检索。单节点 Milvus 可以在秒内完成十亿级的向量搜索,分布式架构亦能满足用户的水平扩展需求。 18位贡献者;3,600次commit;5个re...

    Milvus安装手册:

    https://www.bookstack.cn/read/milvus-0.8/guides-get_started-install_milvus-install_milvus.md

    https://www.lmlphp.com/user/8607/article/item/384785/

     

    https://gitee.com/mirrors/Milvus?_from=gitee_search

    参考;https://blog.csdn.net/yangschfly/article/details/105292534

    Milvus 高性能向量搜索引擎已经开源了。GitHub Repo:https://github.com/milvus-io/milvus (或点击阅读原文查看)。

    Milvus 能够帮助用户轻松应对海量非结构化数据(图片/视频/语音/文本)检索。单节点 Milvus 可以在秒内完成十亿级的向量搜索,分布式架构亦能满足用户的水平扩展需求。

    18位贡献者;3,600次commit;5个release迭代;近一年的深入调研与密集开发;以及无数根头发,共同见证了Milvus的研发历程。

    一路走来,Milvus 已被10多家科技公司使用,助力互联网娱乐(图片搜索/视频搜索)、新零售(以图搜商品)、智慧金融(用户认证)和智能物流(车辆识别)等领域。

     

    milvus是干什么的?通俗的讲,milvus可以让你在海量向量库中快速检索到和目标向量最相似的若干个向量,这里相似度量标准可以是内积或者欧式距离等。借用官方的话说就是:

    Milvus 是一款开源的、针对海量特征向量的相似性搜索引擎。基于异构众核计算框架设计,成本更低,性能更好。 在有限的计算资源下,十亿向量搜索仅毫秒响应。

    说白了就是速度快,先不说十亿向量,自己写代码去完成对100万300维向量的余弦相似度计算并排序就需要不小的响应时间吧,就本人测试而言,即便使用scipy库计算速度依然要比milvus慢很多。

    milvus和Faiss的对比
    其实在milvus开源之前,也存在高性能向量相似性搜索引擎(库),这个引擎就是Facebook的Faiss,它的功能和milvus是一样的,所以就不再做过多介绍,具体可以参考官网

    就我个人而言,我是推荐使用milvus的,主要是在我个人看来,milvus有如下几个好处:

    多平台通用,mac,windows和linux都是支持的,因为milvus可以通过docker部署,因此平台通用性好了不少。
    支持编程语言多,Java,c,c++和python都支持,要知道Faiss是不支持java的,这一点简直让人抓狂,github上好几个项目就是关于把Faiss转成java的,因为我Java和python都是要使用的,我把github上关于faiss转java的项目都试了个遍,结论就是非常难安装,只要Faiss版本更新了,必须要重来一遍,即便最后java可以用了,也不敢保证其稳定性。所以想在Java上用Faiss还是放弃吧。
    在速度方面,就我自己测试而言,milvus不输Faiss,但是我没有使用GPU测试,有兴趣的小伙伴可以试一下。
    当然milvus也有难用的地方,我自己发现了两点,如果是我自己使用不当造成的,还请各位朋友在评论指出:

    milvus的向量格式不支持numpy,要用列表的形式存储向量,而列表占用内存要远远大于ndarray的,这对于小内存主机简直是个天灾,我16GB内存情况下,把500000*768的矩阵转成list,电脑直接卡死。
    milvus在第一次search时速度会慢,之后机会快起来了,这应该是个小bug,有人在github提出了,应该很快就可以修复,所以你们在测试milvus的速度时千万别算第一次的时间。
    milvus 安装及常见问题
    milvus 一共有两种安装方式:自己编译安装和使用docker安装。这里推荐大家使用docker安装,docker安装方便快捷,可在Windows上使用。自己编译安装,由于每个人环境不同,很容易出问题。本文只介绍基于docker的安装,另外因为我比较穷,所以只介绍cpu版本的安装,不过gpu安装也是大同小异。

    基于docker安装milvus CPU版本
    简言之安装比较简单,毕竟大佬们已经把milvus部署在了docker里,我们只要启动起来就行了。

    安装docker

    首先就是要安装docker,还不了解docker可以了解一波,非常好用的虚拟机工具,直接去官网下载对应平台的安装文件即可。

    下载相应版本镜像

    安装好docker后,要去pull对应的镜像(image),首先进到dockerhub官网中,然后搜索milvus,第一个结果就是。因为我们安装的是CPU版本,所以在tags里找cpu-latest,然后pull下来就可以了,即在你的命令行窗口输入
    docker pull milvusdb/milvus:cpu-latest。注意:随着版本迭代更新,这一条命令在未来可能会失效,建议先去dockerhub搜索一下,去看一下应该用什么tag。

    设置工作目录和配置文件

    在创建启动容器之前,我们要先设置好工作目录和配置文件。

    一共要设置三个目录,分别是数据库存储目录,日志存储目录和配置文件目录。其中配置文件目录就存放着我说的配置文件。配置文件一共有两个,分别是服务器设置文件和日志设置文件。

    所以我们要想好这三个文件夹放在哪里,比如我们可以在当前用户目录下建立一个milvus文件夹,然后在这里面存储上述三个目录。下面我们需要设置两个配置文件,记得要把服务器配置文件名改为server_config.yaml,把日志配置文件改为log_config.conf。
    两个配置文件的内容:服务器配置文件 日志配置文件。配置文件也可以到官网下载。

    下面是我的文件目录结构,共大家参考:

      milvus
        │
        ├─conf //配置文件目录
        │      log_config.conf  //服务器配置文件
        │      server_config.yaml  //日志配置文件
        │
        ├─db //数据库存储目录
        │
        └─logs //日志存储目录
        │
    启动docker服务

    设置好工作目录后,就可以使用镜像创建容器了,我的工作目录是C:\Users\Zhdun\milvus,所以我的创建命令是:

    docker run -td --name mymilvus -e "TZ=Asia/Shanghai" -p 19530:19530 -p 8080:8080 -v C:\Users\Zhdun\milvus\db:/var/lib/milvus/db -v C:\Users\Zhdun\milvus\conf:/var/lib/milvus/conf -v C:\Users\Zhdun\milvus\logs:/var/lib/milvus/logs milvusdb/milvus:cpu-latest
    命令看起来有点长, 我稍微解释下,-td是后台运行,--name是给自己的容器起个名字,-p是端口映射,不想用默认的话,可以去服务器配置文件里改,-v就是为了映射三个工作目录。具体可以参考docker的run命令。

    执行完命令后,运行docker ps -a,如果发现自己创建的容器excited的了,那就docker logs一下,看出了什么问题。如果发现容器在运行了,就代表基本没问题了。

    接下来我会说一下常见的安装问题,以及如何去使用milvus。

    安装时的常见问题及解决

    Config check fail: Invalid config version: . Expected config version: 0.1 遇到这种问题就在服务器的配置文件第一行加上version: 0.1。

    Config check fail: Invalid cpu cache capacity: 1. Possible reason: sum of cache_config.cpu_cache_capacity and db_config.insert_buffer_size exceeds system memory.
    这种问题就说明内存超出了限制,首先检查服务器配置里的 cpu_cache_capacity 和 insert_buffer_size 是不是过大了。

    然后再检查给定docker设定的内存是多少,可以通过docker info来检查。

    milvus 基本使用
    安装完成后,终于可以开始使用milvus了,milvus支持python,java和c++。在这里我只介绍python的使用。
    首先安装 pymilvus库:pip install pymilvus,然后就可以使用这个库来写代码了,接下来我会直接把自己写的范例代码贴上去,其中每一步的具体含义以及可能的扩展我会直接在注释里告诉大家,如有错误还请各位指出。

    # -*- coding: utf-8 -*-
     
    #导入相应的包
    import numpy as np
    from milvus import Milvus, IndexType, MetricType
     
    # 初始化一个Milvus类,以后所有的操作都是通过milvus来的
    milvus = Milvus()
     
    # 连接到服务器,注意端口映射,要和启动docker时设置的端口一致
    milvus.connect(host='localhost', port='19530')
     
    # 向量个数
    num_vec = 5000
    # 向量维度
    vec_dim = 768
     
    # 创建表
    # 参数含义
    # table_name: 表名
    # dimension: 向量维度
    # metric_type: 向量相似度度量标准, MetricType.IP是向量内积; MetricType.L2是欧式距离
    table_param = {'table_name': 'mytable', 'dimension':vec_dim, 'index_file_size':1024, 'metric_type':MetricType.IP}
    milvus.create_table(table_param)
     
    # 随机生成一批向量数据
    vectors_array = np.random.rand(num_vec,vec_dim)
    vectors_list = vectors_array.tolist()
     
    # 官方建议在插入向量之前,建议先使用 milvus.create_index 以便系统自动增量创建索引
    # 索引类型有:FLAT / IVFLAT / IVF_SQ8 / IVF_SQ8H,其中FLAT是精确索引,速度慢,但是有100%的召回率
    index_param = {'index_type': IndexType.FLAT, 'nlist': 128}
    milvus.create_index('mytable', index_param)
     
    # 把向量添加到刚才建立的表格中
    # ids可以为None,使用自动生成的id
    status, ids = milvus.add_vectors(table_name="mytable",records=vectors_list,ids=None) # 返回这一组向量的ID
     
    # 官方建议 向量插入结束后,相同的索引需要手动再创建一次
    milvus.create_index('mytable', index_param)
     
    # 输出一些统计信息
    status, tables = milvus.show_tables()
    print("所有的表格:",tables)
    print("表格的数据量(行):{}".format((milvus.count_table('mytable')[1])))
    print("mytable表格是否存在:",milvus.has_table("mytable")[1])
     
    # 加载表格到内存
    milvus.preload_table('mytable')
     
    # 创建查询向量
    query_vec_array = np.random.rand(1,vec_dim)
    query_vec_list = query_vec_array.tolist()
    # 进行查询, 注意这里的参数nprobe和建立索引时的参数nlist 会因为索引类型不同而影响到查询性能和查询准确率
    # 对于 FLAT类型索引,两个参数对结果和速度没有影响
    status, results = milvus.search(table_name='mytable', query_records=query_vec_list, top_k=4, nprobe=16)
    print(status)
    print(results)
     
     
     
    # 删除表格和索引, 不删除的话,下一次还可以继续使用
    milvus.drop_index(table_name="mytable")
    milvus.delete_table(table_name="mytable")
     
    # 断开连接
    milvus.disconnect()
    milvus 多进程使用
    写这一章的主要目的是为了进行并发测试,以及多进程能否节省时间,官方说明在使用多进程时需要满足下面两个条件:

    程序执行时主进程中没有创建 client
    每个子进程分别创建 client 进行操作
    下面是我的测试代码:

    # -*- coding: utf-8 -*-
    import time
    from multiprocessing import Pool
    import numpy as np
    import random
    from milvus import Milvus, IndexType, MetricType
     
    def create_data(host,port,num_vec,vec_dim):
        """ 创建一些表格和索引用来做多进程测试 """
        milvus = Milvus()
        milvus.connect(host=host, port=port)
        # 创建2个表
        table_param = {'table_name': 'table1', 'dimension':vec_dim, 'index_file_size':1024, 'metric_type':MetricType.IP}
        milvus.create_table(table_param)
        table_param = {'table_name': 'table2', 'dimension':vec_dim, 'index_file_size':1024, 'metric_type':MetricType.L2}
        milvus.create_table(table_param)
        # 随机生成一批向量数据
        vectors_array = np.random.rand(num_vec,vec_dim)
        vectors_list = vectors_array.tolist()
        # 创建索引
        index_param = {'index_type': IndexType.FLAT, 'nlist': 128}
        milvus.create_index('table1', index_param)
        milvus.create_index('table2', index_param)
     
        # 添加数据
        milvus.add_vectors(table_name="table1",records=vectors_list,ids=None)
        milvus.add_vectors(table_name="table2",records=vectors_list,ids=None)
     
        # 创建索引
        milvus.create_index('table1', index_param)
        milvus.create_index('table2', index_param)
        print(milvus.show_tables())
        # 断开连接
        milvus.disconnect()
    def clear_table(host,port):
        """ 清空表格和索引 """
        milvus = Milvus()
        milvus.connect(host=host, port=port)
        for table_name in milvus.show_tables()[1]:
            milvus.drop_index(table_name=table_name)
            milvus.delete_table(table_name=table_name)
        milvus.disconnect()
    def milvus_search(host,port,table_name,query_vec,search_time=10):
        """ 测试查询, 返回查询的秒数"""
        milvus = Milvus()
        milvus.connect(host=host, port=port)
        # 因为bug的原因,要先搜索一次
        milvus.search(table_name,4,8,query_vec)
        # 开始测试
        for _ in range(search_time):
            query_vec[0][0] = random.random() # 稍微随机化一下
            milvus.search(table_name, 4, 8, query_vec)
     
     
    if __name__  == "__main__":
        host = "localhost"
        port = "19530"
        num_vec = 100000
        vec_dim = 768
        num_proc = 3 # 进程数
        search_time = 2000 # 搜索次数
        ####### Step1 先创建用于测试的数据 运行一次就行了
        # create_data(host=host,port=port,num_vec=num_vec,vec_dim=vec_dim)
        # clear_table(host,port)
        # exit(0)
     
        ####### Step2 测试依次执行的时间
        start_time = time.time()
        for _ in range(num_proc):
            query_vec = np.random.rand(1,vec_dim).tolist()
            milvus_search(host,port,"table1",query_vec,search_time)
        end_time = time.time()
        print("顺序执行milvus_search的时间总和是:",end_time-start_time)
     
        ####### Step3 测试多进程时间
        pool = Pool(num_proc)
        start_time = time.time()
        for _ in range(num_proc):
            query_vec = np.random.rand(1,vec_dim).tolist()
            pool.apply_async(milvus_search,args=(host,port,"table1",query_vec,search_time))
        pool.close()
        pool.join()
        end_time = time.time()
        print("并行执行milvus_search的时间总和是:",end_time-start_time)
     
    结论就是对于search操作,依次search100次,和10个进程同时开,每个进程search10次,开多进程速度是会变快的。

    感谢阅读,如有问题,烦请指出。

    展开全文
  • 为了让尝试“以图搜图”的相似图片检索的场景,基于ES向量索引计算和图片特征提取模型 VGG16 设计了一个以图搜图系统。 开源地址:https://github.com/yaolipro/image-retrieval 检索场景 推理流程:读取图片,...

    概述

    • 为了让尝试“以图搜图”的相似图片检索的场景,基于ES向量索引计算和图片特征提取模型 VGG16 设计了一个以图搜图系统。
    • 开源地址:https://github.com/yaolipro/image-retrieval

    检索场景

    • 推理流程:读取图片,算法生成特征向量
    • 特征入库:把特征向量存入Milvus中
    • 检索流程:线上实时向量检索
    • 具体流程如下图:

    Milvus服务端安装

    • 安装指南:https://milvus.io/cn/docs/milvus_docker-cpu.md
    • 下载配置
      mkdir -p milvus/conf && cd milvus/conf
      wget https://raw.githubusercontent.com/milvus-io/milvus/0.10.6/core/conf/demo/server_config.yaml
    
    • 服务启动
      docker run -d --name milvus_cpu_0.11.0 \
      -p 19530:19530 \
      -p 19121:19121 \
      -v <ROOT_DIR>/milvus/db:/var/lib/milvus/db \
      -v <ROOT_DIR>/milvus/conf:/var/lib/milvus/conf \
      -v <ROOT_DIR>/milvus/logs:/var/lib/milvus/logs \
      -v <ROOT_DIR>/milvus/wal:/var/lib/milvus/wal \
      milvusdb/milvus:0.10.6-cpu-d022221-64ddc2
    

    Milvus向量索引建库

    • 此处选用已落盘的h5py向量库进行建库
    • 检索类型为内积:MetricType.IP
      # 1. 读取索引
      h5f = h5py.File(index_dir, 'r')
      self.retrieval_db = h5f['dataset_1'][:]
      self.retrieval_name = h5f['dataset_2'][:]
      h5f.close()
      # 2. 入库Milvus
      if self.index_name in self.client.list_collections()[1]:
          self.client.drop_collection(collection_name=self.index_name)
      self.client.create_collection({'collection_name': self.index_name, 'dimension': 512, 'index_file_size': 1024, 'metric_type': MetricType.IP})
      self.id_dict = {}
      status, ids = self.client.insert(collection_name=self.index_name, records=[i.tolist() for i in self.retrieval_db])
      for i, val in enumerate(self.retrieval_name):
          self.id_dict[ids[i]] = str(val)
      self.client.create_index(self.index_name, IndexType.FLAT, {'nlist': 16384})
      # pprint(self.client.get_collection_info(self.index_name))
      print("************* Done milvus indexing, Indexed {} documents *************".format(len(self.retrieval_db)))
    

    Milvus检索实现

    • 根据加载索引时的定义,此处检索采用点积距离计算方式,具体代码如下:
    _, vectors = self.client.search(collection_name=self.index_name, query_records=[query_vector], top_k=search_size, params={'nprobe': 16})
    
    • 可切换至欧氏:MetricType.L2

    操作简介

    python index.py
    --train_data:自定义训练图片文件夹路径,默认为`<ROOT_DIR>/data/train`
    --index_file:自定义索引文件存储路径,默认为`<ROOT_DIR>/index/train.h5`
    
    • 操作二:使用相似检索
    python retrieval.py --engine=milvus
    --test_data:自定义测试图片详细地址,默认为`<ROOT_DIR>/data/test/001_accordion_image_0001.jpg`
    --index_file:自定义索引文件存储路径,默认为`<ROOT_DIR>/index/train.h5`
    --db_name:自定义ES或者Milvus索引库名,默认为`image_retrieval`
    --engine:自定义检索引擎类型,默认为`numpy`,可选包括:numpy、faiss、es、milvus
    

    总结

    • 基于库的管理方式便捷易懂
    • 使用姿势类似ES,但性能优于ES
    • 由于当前Milvus只支持向量检索,不支持标量相关,如果涉及标量过滤需要自建业务库
    • Milvus社区后续会支持分布式,可以更加方便的应对大索引场景

    That’s all!

    展开全文
  • 又拍图片管家亿级图像之搜图系统的两代演进及底层原理 又拍图片管家当前服务了千万级用户,管理了百亿级图片。当用户的图库变得越来越庞大时,业务上急切的需要一种方案能够快速定位图像,即直接输入图像,然后根据...

    又拍图片管家亿级图像之搜图系统的两代演进及底层原理

    又拍图片管家当前服务了千万级用户,管理了百亿级图片。当用户的图库变得越来越庞大时,业务上急切的需要一种方案能够快速定位图像,即直接输入图像,然后根据输入的图像内容来找到图库中的原图及相似图,而以图搜图服务就是为了解决这个问题。

    本人有幸独立负责并实施了整个以图搜图系统从技术调研、到设计验证、以及最后工程实现的全过程。而整个以图搜图服务也是经历了两次的整体演进:从 2019 年初开始第一次技术调研,经历春节假期,2019 年 3、4 月份第一代系统整体上线;2020 年初着手升级方案调研,经历春节及疫情,2020 年 4 月份开始第二代系统的整体升级。

    本文将会简述两代搜图系统背后的技术选型及基本原理。


    基础概要

     

    图像是什么?

    与图像打交道,我们必须要先知道:图像是什么?

    答案:像素点的集合。

    比如:

    左图红色圈中的部分其实就是右图中一系列的像素点。

    再举例:

    假设上图红色圈的部分是一幅图像,其中每一个独立的小方格就是一个像素点(简称像素),像素是最基本的信息单元,而这幅图像的大小就是 11 x 11 px 。

     

    图像的数学表示

    每个图像都可以很自然的用矩阵来表示,每个像素点对应的就是矩阵中的一个元素。

    二值图像

    二值图像的像素点只有黑白两种情况,因此每个像素点可以由 0 和 1 来表示。

    比如一张 4 * 4 二值图像:

    0 1 0 11 0 0 01 1 1 00 0 1 0

    RGB 图像

    红(Red)、绿(Green)、蓝(Blue)作为三原色可以调和成任意的颜色,对于 RGB 图像,每个像素点包含 RGB 共三个通道的基本信息,类似的,如果每个通道用 8 bit 表示即 256 级灰度,那么一个像素点可以表示为:

    ([0 .. 255], [0 .. 255], [0 .. 255])

    比如一张 4 * 4 RGB 图像:

    图像处理的本质实际上就是对这些像素矩阵进行计算。

     

    搜图的技术问题

    如果只是找原图,也就是像素点完全相同的图像,那么直接对比它们的 MD5 值即可。然而,图像在网络的传输过程中,常常会遇到诸如压缩、水印等等情况,而 MD5 算法的特点是,即使是小部分内容变动,其最终的结果却是天差地别,换句话说只要图片有一个像素点不一致,最后都是无法对比的。

    对于一个以图搜图系统而言,我们要搜的本质上其实是内容相似的图片,为此,我们需要解决两个基本的问题:

    •把图像表示或抽象为一个计算机数据•这个数据必须是可以进行对比计算的

    直接用专业点的话说就是:

    •图像的特征提取•特征计算(相似性计算)


    第一代搜图系统

     

    特性提取 - 图像抽象

    第一代搜图系统在特征提取上使用的是 Perceptual hash 即 pHash 算法,这个算法的基本原理是什么?

    如上图所示,pHash 算法就是对图像整体进行一系列变换最后构造 hash 值,而变换的过程可以理解为对图像进行不断的抽象,此时如果对另外一张相似内容的图像进行同样的整体抽象,那么其结果一定是非常接近的。

     

    特性计算 - 相似性计算

    对于两张图像的 pHash 值,具体如何计算其相似的程度?答案是 Hamming distance 汉明距离,汉明距离越小,图像内容越相似。

    汉明距离又是什么?就是对应位置不同比特位的个数。

    例如:

    第一个值: 0 1 0 1 0第二个值: 0 0 0 1 1

    以上两个值的对应位置上有 2 个比特位是不相同的,因此它们的汉明距离就是 2 。

    OK ,相似性计算的原理我们知道了,那么下一个问题是:如何去计算亿级图片对应的亿级数据的汉明距离?简而言之,就是如何搜索?

    在项目早期其实我并没有找到一个满意的能够快速计算汉明距离的工具(或者说是计算引擎),因此我的方案进行了一次变通。

    变通的思想是:如果两个 pHash 值的汉明距离是接近的,那么将 pHash 值进行切割后,切割后的每一个小部分大概率相等。

    例如:

    第一个值: 8 a 0 3 0 3 f 6第二个值: 8 a 0 3 0 3 d 8

    我们把上面这两个值分割成了 8 块,其中 6 块的值是完全相同的,因此可以推断它们的汉明距离接近,从而图像内容也相似。

    经过变换之后,其实你可以发现,汉明距离的计算问题,变成了等值匹配的问题,我把每一个 pHash 值给分成了 8 段,只要里面有超过 5 段的值是完全相同的,那么我就认为他们相似。

    等值匹配如何解决?这就很简单了,传统数据库的条件过滤不就可以用了嘛。

    当然,我这里用的是 ElasticSearch( ES 的原理本文就不介绍了,读者可以另行了解),在 ES 里的具体操作就是多 term 匹配然后 minimum_should_match 指定匹配程度。

    为什么搜索会选择 ElasticSearch ?第一点,它能实现上述的搜索功能;第二点,图片管家项目本身就正在用 ES 提供全文搜索的功能,使用现有资源,成本是非常低的。

     

    第一代系统总结

    第一代搜图系统在技术上选择了 pHash + ElasticSearch 的方案,它拥有如下特点:

    pHash 算法计算简单,可以对抗一定程度的压缩、水印、噪声等影响。•ElasticSearch 直接使用了项目现有资源,在搜索上没有增加额外的成本。

    当然这套系统的局限性也很明显:由于 pHash 算法是对图像的整体进行抽象表示,一旦我们对整体性进行了破坏,比如在原图加一个黑边,就会几乎无法判断相似性。

    为了突破这个局限性,底层技术截然不同的第二代搜图系统应运而生。


    ​第二代搜图系统

     

    特性提取

    在计算机视觉领域,使用人工智能相关的技术基本上已经成了主流,同样,我们第二代搜图系统的特征提取在底层技术上使用的是 CNN 卷积神经网络。

    CNN 卷积神经网络这个词让人比较难以理解,重点是回答两个问题:

    CNN 能干什么?•搜图为什么能用 CNN ?

    AI 领域有很多赛事,图像分类是其中一项重要的比赛内容,而图像分类就是要去判断图片的内容到底是猫、是狗、是苹果、是梨子、还是其它对象类别。

    CNN 能干什么?提取特征,进而识物,我把这个过程简单的理解为,从多个不同的维度去提取特征,衡量一张图片的内容或者特征与猫的特征有多接近,与狗的特征有多接近,等等等等,选择最接近的就可以作为我们的识别结果,也就是判断这张图片的内容是猫,还是狗,还是其它。

    CNN 识物又跟我们找相似的图像有什么关系?我们要的不是最终的识物结果,而是从多个维度提取出来的特征向量,两张内容相似的图像的特征向量一定是接近的。

    具体使用哪种 CNN 模型?

    我使用的是 VGG16 ,为什么选择它?首先,VGG16 拥有很好的泛化能力,也就是很通用;其次,VGG16 提取出来的特征向量是 512 维,维度适中,如果维度太少,精度可能会受影响,如果维度太多,存储和计算这些特征向量的成本会比较高。

     

    向量搜索引擎

    从图像提取特征向量的问题已经解决了,那么剩下的问题就是:

    •特征向量如何存储?•特征向量如何计算相似性,即如何搜索?

    对于这两个问题,直接使用开源的向量搜索引擎 Milvus 就可以很好的解决,截至目前,Milvus 在我们的生产环境一直运行良好。

     

    第二代系统总结

    第二代搜图系统在技术上选择了 CNN + Milvus 的方案,而这种基于特征向量的搜索在业务上也提供了更好的支持。


    作者上一篇文章 Milvus 开发者专栏|以图搜图系统工程实践 已经简单的介绍过 Milvus,

    这里就不再多做介绍。如你对以图搜图技术感兴趣, 你也可以阅读我们过去分享过的其他以图搜图相关内容, 或是加入 Milvus 社区交流群与我们交流:

    视频|10分钟讲清楚Milvus 以图搜图、以图搜视频

    直播回放| 轻松三步搭建 Milvus 以图搜图系统

    Milvus实战 | 轻松搭建以图搜图系统

     

    本文转载自公众号 Node Python Go 全栈开发,作者 rifewang

     

    | 欢迎加入 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 #16: Milvus 分布式扩展方案-Mishards |Milvus Q&A 部分文字实录 Attendee= 参会者 Attendee A:你好顾老师, 我想了解一下 Mishards 它具体在扩容的过程怎么实现的?动态扩容那...

    Chat with Milvus #16: Milvus 分布式扩展方案-Mishards

     

     

    | Milvus Q&A 部分文字实录

     

    Attendee= 参会者

     

    Attendee A:你好顾老师, 我想了解一下 Mishards 它具体在扩容的过程怎么实现的?动态扩容那一步,就是 Milvus readonly 服务它扩容具体怎么实现?

     

    顾老师 @Milvus: 现在我们的分布式其实是做第一步相对比较简单的,应该称之为分布式扩展。我们还没有把整个 Milvus 构建成一个分布式集群的模式,因为之前也跟大家有解释这个原因,其实我们有很多功能还在不断的引入当中。因为一个分布式集群,当你开始做分布式集群的时候,就意味着你自己自身的单点的能力也好,都要相对到一个平台期,那么在做那个会比较的自然一点,不然的话因为我们现在很多功能要引入进去,那么其实如果是在一个分布式集群的环境里面的话,它会变得非常的复杂,所以现在更多的是做一个分布式扩展。

     

    分布式扩展其实是现在主要的方式,也就是提供一些这种分布式代理像 Mishards,然后前面可以借 nginx 去帮助大家做一些这种动态的负载均衡。扩容这部分的话,其实我们即便是把它做成一个集群,我们因为最终奔着一个云的环境去的,所以我们也不会说把所有的功能都让自己去做实现,更多的是会利用现代的组件,怎么样去利用 k8s 去新增节点,然后去注册服务,然后怎么样把它加入到负载均衡的里面,所以其实我们不会说自己单纯做一套完整的东西去做所有的东西。

     

    Attendee A:在查询文件的过程中是挨个对文件进行查找,然后查找过来,然后在内存中....

     

    顾老师 @Milvus:你是说搜索的时候?

     

    Attendee A:对,我在看的查找的过程中,不是挨个文件,就是在 search 的时候挨对每一个文件夹进行比较,求出 Top N,然后再归并是吧?

     

    顾老师 @Milvus:对的,是这么个过程。

     

    Attendee A:我看到咱的在知乎上分享的文章里面,怎么是还往内存中加载的时候用的 LRU(Least Recently Used)策略,既然对每一个文件都进行了 Top N,它不就没有必要进行 LRU?

     

    顾老师 @Milvus:这个是两个不同的方面,LRU 主要是指的是因为在 Milvus 服务当中,它有一个内存当中的 cache 缓存这一层,那么其实所有的数据文件都先放在内存当中,然后我去进行搜索,这是速度最快的。所以这部分是挨个搜索其实就是发生在内存里的。但是如果说你的文件特别大,然后你的服务器内存也不是那么够,那么你不可能把所有的文件都放在内存里面,这个缓冲区它肯定需要一些淘汰的机制,对吧?

     

    我读了 10 个文件,现在你第 11 个文件要进来,我不是已经放不下了,我就要把最早的文件清除掉,释放的空间去给后面新的文件。它其实更多是指的一个缓冲区的内存淘汰的一个机制。您那边现在是一个什么样的场景?

     

    Attendee A:就是 10 亿级的这种的向量,512 维的。如果我一个节点写入,然后多个节点可以查询的话,我从删除然后到可以进行查询,可以同步到这能用,这多长时间?

      

    顾老师 @Milvus:你是说被删掉的,然后到查询的时间是吗?肯定是要有一个延迟的。你如果要在 10 亿的规模上做一个几百的并发度的话,其实已经算是一个比较高的规模相对会比较大一点,硬件的规模。

     

    Attendee A:实际上咱们那个工具的话算了一下,1700多G。

     

    顾老师 @Milvus:10 亿的话内存的话,我想一想,如果你是带压缩的话,应该不会那么大,可能在 500 就 600 多 G 左右。如果不这样做的话,可能它就一个 T,一点几个 T 了。

     

    Attendee A:对。就这种全量匹配的不进行压缩的话,也不进行聚类,如果这样查询的话,这种速度查 Top10 的话,多长时间能够返回?

     

    顾老师 @Milvus:10 亿的我们没有测过 512 的,我们只测过 128 的,128 的 10 亿的带点压缩的话,差不多是在 400 毫秒左右。因为我们公开数据是 128 维的 sift-1b 的数据集。

     

    Attendee A:咱们提供的 bootcamp 里面,如果按分布式的操作的话,它只有没有 k8s的部署是吧?

     

    顾老师 @Milvus:Bootcamp 里面我们应该没有给分布式的教程,应该分布式的教程都是在本身就是 Milvus 主 repo 的。因为 Bootcamp 中的教程都是偏向于一些小型的应用场景,就是告诉大家怎么和自己的应用去结合的。

     

    Attendee A:Bootcamp 里面有一个叫《基于 Mishards 的分布式方案》,这个不是基于 k8s 的,它是直接自己部署的是吧?

     

    顾老师 @Milvus:对的。所以你的并发度要能达到几百的话,你这个场景还是比较繁忙的,而且又不断的有数据更新进来。我不知道你这些更新的频率大概是什么样的?

     

    Attendee A:整个底库的更新的话不是很大,但是有删除的操作。

     

    顾老师 @Milvus:就是时不时有一些删除,但是更新的量每天会新增加来多少呢?百万级的吗?还是说千万级的这样?

     

    Attendee A:每天大概百万级左右。

     

    顾老师 @Milvus:其实之前也有很多人有类似的一个问题,我觉得给大家建议。把底库和增量的部分创建两个不同的索引的 collection,因为这样的话,不同的 collection 可以有不同的这种文件大小的配置,比较适合不同的场景。

     

    因为底库本身特别大,但是又不怎么更新,相对来说比例不是那么高的话,它文件可以放大一点,它搜索的效率就会高一点。但是动态增加的部分就文件可以小一点的,你可以更快的构建起索引去搜索它。 


    B 同学是做电商的, 希望用 Milvus 做商品图片的搜索(因为多是做场景的讨论所以这里就不写出来, 想了解的可以看视频 16:27-38:30 的部分)


    Attendee C:因为最近主要看向量搜索,其实我们主要是做 1 比 N 这个方案,让我看到了Milvus。然后我们之前考虑了有大概 4 个方案,1 个是 PG 的就是 PG 拿它插件,还有 image signal 来做,只不过它那个维度比较低。然后也考虑了一下 ES 的,只不过 ES 用了它特性 dense vector 来做,还也就前几天我看到你这个叫 Milvus 的。稍微测试了一下,感觉性能还有一些周边的生态都做得还可以,基础的有的都有,所以我想更深入的了解一下这块。

     

    我现在的话我有几个问题,第一个像提取特征值这一块,因为刚才顾老师有说到 VGG 那个模型是吧?然后我想你们这边之后做就是说无论是图片还是一些文字,还是一些声音频之类的,像这种提取特征值这块你们有做一个什么口子来做吗?给别人提供一个比如说一个算法插件什么之类的,然后相当于直接把图片转成一些特征值,然后直接就可以跟你 Milvus 结合起来,会有这方面的考虑?

      

    顾老师 @Milvus:是会有的,其实我们在做的图片搜索套件也是就帮助大家去构建这样一个 pipeline,然后你这边图片就是你配好流水线,然后你把图片提交过来之后,它可以帮你去按照你的要求的操作,比如说做一些对象的侦测,然后根据得出来的对象,然后去按照你指定的模型过一下这些特征值,然后再插入到 Milvus 当中。

     

    但是因为这部分的东西它其实它更偏向于应用层,所以它不在 Milvus 里面,但是它会在非结构数据服务的大的框架里面,所以我们是会在 Milvus 的上游去提供这些东西,方便大家去做这些东西。

     

    Attendee C:对这边可能更专注于做向量搜索引擎这一块整个的方案是吧?

     

    顾老师 @Milvus:对,Milvus 本身它是一个怎么说,这是一个大的非结构数据服务当中一个比较核心的高性能的向量搜索引擎。然后什么模型的推理,pipeline 的构建,这些其实也在我这个框架里面,但是它是在 Milvus 的外部去做这些事情。

     

    Attendee C:

    我想问一下有没有一些落地的这种与业务场景的集成?就是与场景它肯定有一些业务场景方面的一些参数,这边的集成是怎么做的,因为我看到像比如说有图片,这可能用户说我根据以图所图,我可能在 Milvus 里面我可能搜出的是一段特征值,对吧?但是我最终要返回给用户的肯定不能是一些特征值,而且是相应的一些图片的数据。我现在想的看是不是大家都是用那个特征值的 ID 来做是吧?ID 来做一些相关的联系是吗?

     

    顾老师 @Milvus:对没错,而且我们的以图搜图的示例里面也是这么搞的。

     

    Attendee C:还有一个是涉及到分布式这一块,因为我们这边的量还是挺大的,量还是非常大。单依靠单机的话可能...单机的话不是说性能不好单机的话也好,但是可能还是想做分布式这一块。我看到这边只支持一个 Mishards 是吧?他好像是用 Python 来做的是吧?

     

    顾老师 @Milvus:是的,但是后续其实这部分也会去做一些优化,然后我们肯定会提高扩展的能力,这是肯定的,只是说 Milvus 本身还有很多功能需要去增加进来,去帮助大家更好的处理非结构数据的,所以我们是把它单独当成一个新的场景,非结构数据服务的场景来做的。所以他其实会比一般的 ES 也好,或者说某一个结构化数据库的向量插件也好,它会有更多的东西和更多的可能性你要加入进去。所以在这部分确实我们是先想把基础打好了之后,再往这种集群的,分布式集群的方向去做一个延伸。

     

    Attendee C:好的。我看了你们的一些文档,好像跟我理解的有些出入,我看你们这边是对请求,比如说他不同的用户,他可能发的有比如说 10 个关于特征检索的这一个请求,当然这个特征检索可能会分为不同的 collection。那么你这里我看到你们那边设计是将不同的请求分发到通过负载均衡一些方式,分发到不同的读写可读的节点去做的是吗?

     

    顾老师 @Milvus:对,因为每个节点他有的服务的索引不可能是不一样的,比如说你有 10 个索引,10 个索引文件,可能 12345 在 A 节点的时候,678910 是在 B 节点上。因为你分布式扩展有几种,这有两种典型的情况,比如说第一种是你的 10 个索引文件,其实它太大,它超过了你单机内存能够处理的,能够容纳的一个大小,这个时候你做分布式的扩展,更多的是你扩机器来增加整个内存的容量,然后能够把所有这些文件放下,就可能是在节点 A 上有一些文件,在节点 B 上有一些文件。

     

    它可能就是要去不同的机器去进行搜索,所以就会有一个路由的过程。情况就是说我可能就是只有一个数据文件,但是我一个机器可能跑不过来,我需要把它放在多个机器当中,我利用这个更多机器的 CPU 的计算的资源,来提供更高并发服务这样的一种模式,所以他其实会不太一样。

      

    Attendee C:我看你们知乎上面有一篇专栏,上面讲了一下,就是说 Mishards 负责将来自客户端的请求拆分,并路由到内部各细分子实例,最后将子实例结果汇总,返回给客户端,对吧?好像跟你刚才描述的不太一致。

                   

    顾老师 @Milvus:因为这说的是另外一种情况,就是说是比如说这索引它很大,它有好多的文件,他可能这些文件都落在不同的只读节点上,那么你是需要在所有这些只读节点上都查完一个 top k 最后再做一次合并,你才知道最终的结果。这个其实是我刚才说的第一种情况,就是你要你索引它包含 10 个文件,但是一个机器放不下这种情况。

     

    Attendee C:对,然后还有可能还剩下一种情况,反正就像我刚刚说的分发不同的请求,就是说可能说有不同的 collection,然后它索引,然后比如说有三个集合的索引放在一个节点上,另外几个节点,另外几个的索引放在另一个节点上,实际上他们索引都不是特别大。

     

    现在 Mishards 都是支持的,是吗?还是说我需要定制化的去做一些什么操作,然后才能满足这两个情况?

     

    顾老师 @Milvus:都是支持的。

    你之前在 ElasticSearch 上尝试做的图片搜索,你觉得他支持的怎么样?

     

    Attendee C:ES 其实我当时也是测了大概维度比较低,也就 1000 万左右,100 维的这种特征值,实际上速度的话,因为我们单机比较慢,因为我没有做任何的优化,还是比较慢的。

     

    遇到的问题的话也没有特别多,因为它有一个特性,7.6 左右版本,提供了一个两个相应的 vector 数据类型,对吧?然后可能当时考虑的是把这些 vector 这种特征值直接存放到 ES 里面,然后在其他的一些相应的业务数据,我们可能就会用另外的来进行陈述,实际上他们两个之间的关联也是通过一些正如 Milvus 一样的,有一些特定的什么 ID 来进行一些这样的一个关联。

     

    现在主要考虑 Milvus 是因为它像你们这边一些具体的方案都有了,因为还要看有落地的这些方案。然后 ES 这边我们如果要做的话,可能像其他的一些前面的工作,包括做一些自定义 API 什么, 做一些相应的开发任务,还有后面那些具体的当时有没有考虑太细,但是现在目前来看还是打算用你们 Milvus 来做。

     

    我当时做的主要是单机的,没有考虑到分布式这个场景,有可能 ES 那边的分布式场景的话,跟你们这还是有相比的话有一定的优势。

     

    顾老师 @Milvus:ES 它确实本身是有分布式的,但是它的这种关键词型的这种 IVF 索引,就是文本型的索引,它的原理和向量的搜索的原理还是不太一样的,所以这部分分布式能的话能不能带来一个很好的效果,其实可能你们得试过才知道。对。它应该还是能提供一些分布式基本的保证,但对向量的效果这个可能需要自己实测过。

     


     

    Attendee D:我们其实是做推荐的一些东西的,然后推荐里面可能是召回的一个环节。对召回的话,其实原来它向量确实是可以匹配上的比较好的一种方式,但其实对于业务来说,我们其实还是会对这种标量的过滤有挺强需求的,我想了解一下现在 Milvus 对标量的支持是一个什么样的一个计划?

     

    顾老师 @Milvus:对属性的过滤会在下一个版本里面,具体就是在 0.11.0 版本,按照现在的规划来说。

     

    Attendee D:那它的具体的实现是会像 ES 那样的倒排来做吗?

     

    顾老师 @Milvus:不是,是这样的,就是说从我们的角度来讲,我们也不叫标量了。这两部分结合在一起是向量数据和属性数据,我们称之为属性的数据,那么我们可以允许用户定义一些属性,当然它长度也会有限制,后续我们也会确定一下。然后每一个属性可以是整型的数字也可以是浮点型的数字。然后在搜索的时候是会以向量搜索为主,以向量索引的这个方式,以 ANN (approximate nearest neighbor, 近似最近邻算法)的方式为主,但是 ANN 比如说是一个 IVF 型的索引,他会先去搜寻一个区域的聚类,对吧?我去搜寻这一个区域的聚类里的具体每一条向量的时候,我们这个时候会做一次属性的过滤,这样的话能够确保最终出来的结果一定是比较准确的,是符合你的属性的要求的。然后这个数量也是能够达到,比如说你求 top 10 一定会给你返回 10 条记录,它是经过属性过滤之后的相似性的结果。

     

    Attendee D:就是说它可能还是说是所有的向量都会去扫一遍?

     

    顾老师 @Milvus:它不是一个所有向量都会去扫一遍,因为刚才我讲了他是以 ANNS 的模式为主的。这 ANNS 的模式,比如说 IVF 类的索引,他会首先去计算你搜索向量它所坐落的最近的图形在哪里,然后就图形周围的一片区域看它搜索区域,所以它只会搜索那一小片区域。

     

    先确定你这条搜索向量应该落在索引当中的哪一个聚类当中,然后在聚类周围你可以指定一片区域,它不一定是去聚类的,他说他应该带的聚类那一小个类是可以搜,比如说周围 10 个类这样。对他扫描的那一个子空间里的所有的向量,先做从属性的过滤,然后再去做相似的计算。

     

     

     

    | 欢迎加入 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

     

    展开全文
  • 本文主要介绍基于 Milvus 搭建的多模态图文检索系统。检索流程为:1. 通过 TIRG(Text Image Residual Gating)模型将图片特征和文本特征转化为多模态特征向...
  • Chat with Milvus #10 Benchmark Testing 如果你不知道 Milvus 性能指标要怎么看或是在哪里看的话,可以看此视频- Milvus 的顾老师教你怎么看 Milvus 性能报告与如何达到最佳性能。 也可以到以下这两个地方,...
  • Google 的 BERT 模型在 NLP 领域中具有巨大的影响力。它是一个通用的语言表示模型,可以应用于诸多领域。本文的项目是将 Milvus 与 BERT 模型结合搭建文本搜索引擎...
  • Chat with Milvus #7 视频 谢谢各 Milvuser 的参与,Milvus 线上问答来到了第7期!每次会议都会有小伙伴为我们带来不一样的想法和视角,或是让我们知道我们有哪里可以做的更好。 如果你想来和大家分享你对 ...
  • Milvus 究竟是一个计算平台,还是一个数据库?应用在哪些场景?诸如此类的问题我们的开发者常常在群里被小伙伴问到。这次我们对 Milvus 做了一个简单的概述,让大家可以更清楚Mil...
  • 背景介绍由于巨大的利益,论文造假屡见不鲜,在部分国家或地区甚至形成了论文造假的产业链。目前大部分论文查重系统只能检查论文文字,不能检查图片。因此,论文图片查重已然成为了学术论文原创性...
  • Milvus 搜索引擎使用

    2021-02-01 10:02:34
    文章目录一、安装部署:二、使用 MySQL 管理元数据三、监控与报警 Milvus 搜索引擎使用文档:https://www.milvus.io/cn/docs/v0.10.5/example_code.md ...sudo docker pull milvusdb/milvus:0.10.5-cpu-d010621-4eda
  • Milvus用于猫和狗的基于内容的图像检索 挑战在于使用Milvus创建端到端的应用程序场景。 从David Shvimer的Towards Data Science帖子( )中汲取灵感,我决定使用Milvus检测图像的矢量相似性,主要是猫和狗。 就像在...
  • 在实现食谱检索时,首先会使用模型 im2recipe 将实物图片转化为向量,然后使用该图片向量在 Milvus 中检索出与其相似的食谱向量,并得到食谱向量的 id, 最后在 MySQL 中找到食谱向量 id 对应的食谱信息,如下图橙色...
  • 本期的 Milvus 线上问答由我们 15 年经验的数据库专家-顾老师,带你总结主流数据库的发展与未来方向。视频中我们分析了传统数据库的架构,挑战&解法、分布式数据库的优势与劣...
  • 点击观看完整视频实录本周的 Milvus 线上会议中,我们与参加者分享了两个好消息,一个是 Milvus 教程的上线。以后你就可以更轻易的在 Milvus 官网上找到开发需的资源啦!第二...
  • milvus高性能向量数据库学习笔记

    千次阅读 2020-10-26 19:55:17
    文章目录一.milvus是什么二.安装milvus三.使用milvus四.总结 一.milvus是什么 milvus 是一款开源的向量相似度搜索引擎,支持针对 TB 级向量的增删改操作和近实时查询,具有高度灵活、稳定可靠以及高速查询等特点。...
  • # Get embeddings that users like _, user_like_vectors = milvus.get_entity_by_id(milvus_table, ids) # Get the information with similar movies _, ids = milvus.search(param = {milvus_table, user_like_...
  • 安装milvus 关于milvus milvus作为一个集成的开源平台,目标就是向量检索的集成平台。类似于elasticsearch集成了搜索。细节大家可以直接看官网。https://www.milvus.io/cn/docs/v0.11.0/overview.md 安装 说起来其实...
  • ‍‍|部分Q&A文字实录User A:我今天没有准备好,第一次看到你们这个项目,想要了解一下。顾老师 @ Milvus:好,没有关系,这不需要准备,我们也想了解一下,就是...
  • 文章目录简介Milvus部署Docker 和 Docker Compose...普遍用于图片搜索、智能问答、以商品搜商品等场景 Milvus部署 Docker 和 Docker Compose环境检查 Milvus是基于Docker部署的,你的Docker需要符合以下条件 Dock
  • Milvus 向量检索-Mishards架构介绍

    千次阅读 2020-03-11 10:00:16
    向量搜索引擎 Milvus 旨在帮助用户实现海量非结构化数据的近似检索和分析。单个 Milvus 实例可处理十亿级数据规模,而对于百亿或者千亿规模数据的需求,则需要一个 Milvus 集...
  • #AprilZ星月度速览·基于 Milvus 的以图搜图系统 2.0上线,增强多物体图片检测的能力·Milvus 与 PaddlePaddle 深度整合,赋能工业级 AI 应用·...
  • 文章作者:黎阳,焦点科技软件开发工程师李成龙,Zilliz 数据工程师Milvus(https://milvus.io/) 向量搜索引擎开源半年以来,全球已经有数百家企业或组织用户。焦...
  • 首先放出官方指导文档和代码地址以及图片下载地址: 1.https://github.com/milvusio/bootcamp/tree/master/solutions/reverse_image_search/quick_deploy 2. ...
  • Milvus 以图搜图 1.0 版本自发布以来便受到广大用户的欢迎。近日,Zilliz 推出了 Milvus 以图搜图系统 2.0 版。本文将介绍 Milvus 以图搜图系统 2.0 版的...
  • Milvus 小编: 此篇文章是来自瞧好货app的工程师-凌虚的投稿,团队用 Milvus 实现了以图搜图的功能,提升了业务的效率。...我们的系统主要是各级代理商家之间会传递大量以图片为载体的商品信息,有时候下级商家看...
  • ‍‍完整视频请点|Milvus Q&A 与文字实录Attendee= 参会者Attendee A:我看了一下觉得 Milvus 还是挺不错的,因为瞄准了一些通用的一些计算的 o...
  • Milvus 是一款基于云原生架构开发的开源向量数据库,支持查询和管理由机器学习模型或神经网络生成的向量数据。Milvus 在一流的近似最近邻(ANN)搜索库(例如 Faiss、NMSLIB、Annoy)的功能基础上进行扩展,具有按需...
  • Torch、Java、Milvus快速搭建以图搜图系统 1 原理概述 以图搜图大致原理(口水话版) 以图搜图,即通过一张图片去匹配数据库中的图片,找到最相似的N张图。在我们普通的搜索系统中,文字匹配的搜索单纯的MySQL数据库...
  • Milvus 向量搜索引擎开源半年以来,全球已经有过百家企业或组织用户。小米作为一家专注于智能硬件和电子产品研发的全球化移动互联网企业,也是Milvus 的重要用户。 |应用场景 随着信息技术和互联网行业的...

空空如也

空空如也

1 2 3 4 5 ... 9
收藏数 162
精华内容 64
关键字:

milvus图片