当前位置: 首页 > news >正文

ElasticSearch向量检索技术方案介绍

1、背景

      在人工智能快速发展的今天,推荐技术、以文搜图、以文搜视频、以图搜图等技术已经得到了广泛的应用,在百度、小红书、抖音、快手等app上随便输入一段文本,搜索结果已不像早些年那么单一:只有一些文字信息,现在的搜索结果里不仅有文字,还能够搜索出与检索词高度相关的图片、视频、或者商品(电商app),甚至都不用检索,feed流推荐的内容或者商品都是自身感兴趣的,大家一定会有疑问,整个系统背后是如何实现的呢,为什么输入一段文字,就能检索到相关的视频、音频或者图像呢?不同的内容形式,中间是怎么实现的匹配呢?

      答案就是向量匹配,不同形式的内容需要转化成一个统一的结构化数据。

      AI的出现,实现了这个过程,他可以以一定的算法提取文字、图像、音频、视频等各种形式内容的特征向量,实现了将所有内容形式转化为特征向量的过程。

      内容结构化为特征向量后,那么如何进行检索呢?这就涉及到了本文的主题:向量检索了。

2、es向量检索

2.1 检索算法

1、KNN算法

KNN (K-Nearest Neighbor Search)指的是最近邻搜索。它的原理是:计算待查询向量与数据库中所有向量之间的距离,然后按照距离从小到大排序,选择距离最近的 K 个向量作为查询结果。KNN 算法的优点是可以保证精确的结果,但是效率较低。

2、ANN算法

ANN(Approximate Nearest Neighbor Search) 表示近似最近邻搜索,是一种用于高维数据空间中快速查找最近邻点的方法。与KNN(最近邻搜索)相比,ANN 牺牲了一定的精度以换取更高的搜索速度,因此在处理大规模数据集时具有较高的效率。

ANN 会对数据进行预处理,从而在查询时减少计算距离的次数。其优点是速度快、效率高,但精度有所下降。

3、HNSW

HNSW(Hierarchical Navigable Small World) 是一种基于图的高维向量相似性搜索算法。通过构建一张图来表示向量之间的相似度关系,并使用一些优化策略来加速搜索过程。

2.2 向量距离

向量检索的本质就是计算向量之间的距离,向量距离的大小直接反映两个向量的相似程度,距离越小,两个向量越相似,反之,相似度越低。

常用的距离度量有:

  • 欧式距离:l2
  • 余弦距离:cosine
  • 内积:innerproduct

2.3 elasticsearch环境

es使用的是厂内的:百度Elasticsearch,最新版本7.10,支持向量检索。

2.4 创建索引

以下面创建索引的语句为例说明,这个索引即为工作中开发使用到的,只是对字段做了精简。

{"settings": {"index": {"knn": true,"number_of_shards": 9,"number_of_replicas": 1}},"mappings": {"_source": {"excludes": ["IFV","TFV"]},"properties": {"car_id": {"type": "keyword","ignore_above": 256},"camera_type": {"type": "keyword","ignore_above": 256},"image_id": {"type": "keyword","ignore_above": 256,"index": false},"bbox": {"properties": {"left": {"type": "integer","index": false},"top": {"type": "integer","index": false},"width": {"type": "integer","index": false},"height": {"type": "integer","index": false}}},"IFV": {"type": "bpack_vector","index_type": "hnsw_sq8","dims": 768,"space_type": "l2","parameters": {"m": 32,"ef_construction": 256}},"TFV": {"type": "bpack_vector","index_type": "hnsw_sq8","dims": 768,"space_type": "innerproduct","parameters": {"m": 32,"ef_construction": 256}}}}
}

各重要字段的含义如下: 

字段示例说明
setting{
        "index": {
            "knn": true,
            "number_of_shards": 9,
            "number_of_replicas": 1
        }
    }

knn:设置为ture,开启向量检索功能。

number_of_shards:分片数量,与集群节点数量一致。

number_of_replicas:副本数量,一般设置为1.

excludes
: {
            "excludes": [
                "IMAGE",
                "TEXT"
            ]
        },
这个字段主要是为了减少数据的存储,这样可以大大降低对存储的消耗(IFV、TFV为向量字段)
IMAGE
            "IMAGE": {
                "type": "bpack_vector",
                "index_type": "hnsw_sq8",
                "dims": 768,
                "space_type": "l2",
                "parameters": {
                    "m": 32,
                    "ef_construction": 256
                }
            }

type:向量字段类型固定为 bpack_vector

index_type: 向量检索算法,hnsw算法+sq8量化

dims:向量维度,768维

space_type:距离计算方式,l2,欧式距离

m:hnsw算法参数。此参数表示构造期间为每个新元素创建的双向链接数,主要影响内存、存储消耗以及召回率。m值越高,意味着更高消耗的内存和存储,更慢的索引构建时间,以及更好的召回率。建议根据min(向量维度 * 1.5, 32)取值,以保证性能,12-48可以满足大多数场景的需求。

ef_construction:hnsw算法参数。此参数表示在索引构建过程中,最近邻居的动态扫描区域大小。该值越大,越不容易陷入局部最优解,召回率更高,但是索引构建越慢,取值范围为[2,+∞]。需要注意,如果用户业务需求要求检索top k,那设置的ef_construction值需要大于k。

注意,向量检索算法、维数、距离计算方式千万不能出错,否则会出现检索结果相关性降低,甚至是不相关。

索引创建完成后,就可以正是写入数据了。

2.5 检索

检索dsl:

{"size": 2,"query": {"knn": {"image-vector": {"vector": [3,4,5,6],"k": 2,"ef": 100,"filter": {"term": {"car_id": "A88888"}}}}}
}

百度elasticsearch的向量检索与官方8.x版本es的检索语句稍有不同,支持向量检索和标量的组合检索。

3、代码实现(golang)

向量检索与普通检索在代码的实现上区别不大,重点是dsl的构建与普通检索略有不同,目前在自研的dsl包(elasticsearch查询语言DSL构建包使用及实现原理(golang)_golang es包-CSDN博客)也实现了向量检索dsl的构建,可以直接使用,非常方便,使用示例:

package mainimport ("fmt""github.com/liupengh3c/esbuilder"
)func main() {vector := []float64{0.045727044343948364, 0.029040496796369553,0.02996855601668358, 0.0001537138596177101,-0.011850773356854916, 0.016586067155003548,0.029250113293528557}dslQuery := esbuilder.NewDsl()knnQuery := esbuilder.NewKnnQuery("IFV")knnQuery.SetK(10).SetEf(256).SetVector(vector)filter := esbuilder.NewTermQuery("car_id.keyword", "京AJB139")knnQuery.Filter(filter)dslQuery.SetQuery(knnQuery)fmt.Println(dslQuery.BuildJson())
}

构建的dsl如下:

{"query": {"knn": {"IFV": {"ef": 256,"filter": {"term": {"car_id.keyword": "京AJB139"}},"k": 10,"vector": [0.045727044343948364,0.029040496796369553,0.02996855601668358,0.0001537138596177101,-0.011850773356854916,0.016586067155003548,0.029250113293528557]}}}
}

含义为,检索car_id为京AJB139且与检索条件中向量近似的数据。

4、展望

      向量检索在信息技术和数据处理领域具有广泛的应用前景和重要性。随着技术的不断发展,向量检索的性能和准确性将不断提高,为各个领域带来更多的创新和价值。


http://www.mrgr.cn/news/69436.html

相关文章:

  • Java异常处理
  • Android setContentView执行流程(一)-生成DecorView
  • AcWing 29:删除链表中重复的节点
  • 动态规划 —— dp 问题-买卖股票的最佳时机含冷冻期
  • Mysql基础 03 pymysql库、事务命令
  • 《Python编程实训快速上手》第四天--字符串操作
  • 【Java 多线程】:线程状态 线程操作 线程同步
  • Oracle OCP认证考试考点详解082系列17
  • 如何处理模型的过拟合和欠拟合问题
  • python可视化进阶
  • 科研绘图系列:R语言文章组合图形(barplot scatterplot)
  • Gen-RecSys——一个通过生成和大规模语言模型发展起来的推荐系统
  • 青藤深度参编的终端安全国家标准正式发布
  • 电商系统中,如何解决部分商品在短时间大量访问的单一热点问题?------Range范围分片
  • rce代码层面
  • Asyncio是Python库,它允许我们使用async/await语法编写并发代码。学习如何使用此库编写异步代码。
  • 探索10款音频剪辑软件,让你轻松编辑声音。
  • 链表类算法【leetcode】
  • 记录一次性能优化流程
  • Controlnet作者新作IC-light V2:基于FLUX训练,支持处理风格化图像,细节远高于SD1.5