一、向量数据库简介

1、简介

向量数据库是一种专门用于存储和查询向量数据的数据库。
向量数据也就是embedding向量
典型结构是一个一维数组,其中的元素是数值(通常是浮点数)。这些数值表示对象或数据点在多维空间中的位置、特征或属性
在这里插入图片描述

2、常用的数据向量

  • 图像向量,通过深度学习模型提取的图像特征向量,这些特征向量捕捉了图像的重要信息,如颜色、形状、纹理等,可以用于图像识别、检索等任务;
  • 文本向量,通过词嵌入技术如Word2Vec、BERT等生成的文本特征向量,这些向量包含了文本的语义信息,可以用于文本分类、情感分析等任务;
  • 语音向量,通过声学模型从声音信号中提取的特征向量,这些向量捕捉了声音的重要特性,如音调、节奏、音色等,可以用于语音识别、声纹识别等任务。

3、向量数据库的主要功能

  • 管理:向量数据库以原始数据形式处理数据,能够有效地组织和管理数据,便于AI模型应用。
  • 存储:能够存储向量数据,包括各种AI模型需要使用到的高维数据。
  • 检索:向量数据库特别擅长高效地检索数据,这一个特点能够确保AI模型在需要的时候快速获得所需的数据。这也是向量数据库能够在一些推荐系统或者检索系统中得到应用的重要原因。

向量数据库的主要优点是,它允许基于数据的向量距离或相似性进行快速准确的相似性搜索和检索。这意味着,可以使用向量数据库,根据其语义或上下文含义查找最相似或最相关的数据,而不是使用基于精确匹配或预定义标准查询数据库的传统方法。向量数据库可以搜索非结构化数据,但也可以处理半结构化甚至结构化数据。例如,可以使用向量数据库执行以下操作,根据视觉内容和风格查找与给定图像相似的图像,根据主题和情感查找与给定文档相似的文档,以及根据功能和评级查找与给定产品相似的产品。

4、向量数据库如何工作

向量数据库专门用于存储和查询向量数据

假设一个图书馆就是一个数据库,而书就是数据库中的数据,在传统的教据库中,我们通过书名、作者、出版日期等关键词去搜索我们想要的书籍,这个过程类似于我们在数据库中通过关键词检索需要的数据。

在一个向是数据库中,假设读者不仅想找到一本特定的书,还想找到所有和这本书类似的书,例如内容、风格、主题都相似的书。这在传统图书馆中可能是一项极具挑战的任务,因为这需要逐一浏览和对比每一本书的内容。

在“向量“图书馆中,每本书都会被转换成一个向量,它像书的指纹,包含了书的所有特征信息。然后,我们可以通过计算这些向量之间的距离或相似度,找到与特定书最相似的其他书籍。这就是向量数据库的核心工作原理。

5、向量检索核心步骤

向量教据库的核心思想是将非结构化的文本信息转换为向量数据表示,再将转换后的向量数据以及原始文本一并存储在向量数据库。
当用户输入问题时,将问题描述转换为向量数据,在向量数据库中进行相似性计算,检索出与目标值最相似的向量以及上下文信息,最后将文本返回给用户。

下面是具体的操作流程:

1、生成并写入向量数据
向量数据可以来自各种数据源,例如文本、图像、音频等,每个向量数据都可以通过Embedding模型生成一个对应的特征表示,即向量数据。
向量数据库采用专门的数据结构和算法来存储和管理向量数据,以便快速地进行检索和分析。

2、建立向量索引
为了加速向量搜索,向量数据库通常会构建向量索引,通过计算和比较向量之间的相似度或距离,将向量数据有效地组织起来。
以便数据库快速地定位和检索与查询条件最相关的向量集合。

FLAT 索引:
将向量以列表的形式存储,不进行任何压缩或聚类。检索时,通过计算查询向量与索引中每个向量的相似度来找到最近邻,这种方法简单但效率较低,适用于数据量较小的情况。

倒排文件索引(Inverted File Index,IVF):
传统倒排索引由两部分组成:单词词典和倒排列表
单词词典:包含了文档集合中所有出现过的唯一单词,也称为词条(Term),每个词条会关联一个或多个文档ID。
倒排列表:记录了每个单词出现在哪些文档中,以及在文档中的位置信息。
IVF是一种优化的倒排索引,是一种聚类索引方法,将原始数据划分为多个簇,然后为每个簇建立倒排索引,从而加快检索速度IVF的变体索引。
包括IVF_FLAT、IVF_PQ和IVF_SQ
IVF_FLAT在聚类的基础上使用FLAT结构存储向量,适用于数据集不大且需要高精度的场景。
IVF_PQ使用乘积量化来压缩向量,以加快搜索速度并减少存储空间。

KD树索引:
KD树是一种二叉树结构,用于存储多维向是数据。它通过将向是空间划分为多个子空间,并将向量按照某种规则逐层分割,从而实现高效的向量搜索。

Ball树索引:
Ball树是一种非平衡的树结构,用于存储多维向量数据。它通过将向量空间划分为球形区域,并将向量按照某种规则逐层分割,从而实现高效的向量搜索。

HNSW 索引:
全称为 Hierarchical Navigable Small World,是一种图结构索引,通过构建分层图来组织数据。
它在每一层中将向量连接成图,查询时从高层开始,逐步下降到低层,直到找到最近邻。
HNSW在性能和召回率之间取得了良好的平衡。

局部敏感哈希(Locality Sensitive Hashing, LSH):
LSH是一种哈希技术,通过将相似的向量映射到相同的桶中来加速检索。它适用于高维稀疏向量数据。

乘积量化(Product Quantization,PQ):
PQ是一种向量压缩技术,通过将向量分割并量化来减少存储需求和提高检索速度。

3、向量搜索
在向量搜索中,用户输入一个查询向量,向量数据库通过相似性计算,会返回与查询向量最相似的向量,向量相似度通常使用余弦相似度、欧几里得距离等度量方式进行计算。

6、与传统数据库区别

向量数据库更适用于 AI运算、检索场景,数据接入效率是传统方案的10倍。

相较传统数据库具体有以下几个特点:

数据规模不同:
能够高效处理大规模数据;
对于传统数据库而言,1亿条数据已经是很大的业务流量,然而在向量数据库面向的场景中,单索引数据量可能达到千万级、甚至亿级别,单条向量数据的维度也会达到上千维。

查询方式不同:
传统数据库的查找方式都属于精确査找,而向量数据库通常是近似査找,即返回和输入内容最相近的 TOP K条数据

7、主要应用场景

RAG系统:企业知识库,行业知识库,知识沉淀等。
人脸识别:向量数据库存储大量的人脸向量数据,并通过向量索引技术实现快速的人脸识别和比对。
图像搜索:存储大量的图像向量数据,并通过向量索引技术实现高效相似度计算,返回与检索图像最相似的图像结果。
音频识别:存储大量的音频向量数据,并通过向量索引技术实现快速的音频识别和匹配。
自然语言处理:在自然语言处理(NLP)中,向量数据库通过存储文本向量并运用高效索引,极大提升文本数据的快速搜索和相似度匹配。
推荐系统:将用户行为特征向是化存储在向量数据库,当发起推荐请求时,系统会基于用户特征进行相似度计算,最终筛选用户可能感兴趣的物品推荐给用户。
数据挖掘:向量数据库可以存储大量的向量数据,并通过向量索引技术实现快速的数据挖掘和分析。

8、向量库(FAISS、HNSWLib、ANNOY)

向量数据库与向量库的区别在于,向量库主要用于存储静态数据,其中索引数据是不可变的,这是因为向量库只存储向量嵌入,而不存储生成这些向量嵌入的关联对象

与向量数据库不同,向量库不支持CRUD(创建、读取、更新、删除)操作。
在FAISS或ANNOY等向量库中向现有索引添加新文档可能比较难做到。
HNSWLib是个例外,它有CRUD功能,同时独特地支持并发读写操作。
作为一个向量库的局限性,即不提供部署生态系统、复制实例的能力以及容错性。

二、基本原理

1、相似性测量(Similarity Measurement)

在相似性搜索中,需要计算两个向量之间的距离,然后根据距离来判断它们的相似度。
而如何计算向量在高维空间的距离呢?
有三种常见的向量相似度算法:欧几里德距离、余弦相似度和点积相似度

(1)欧几里得距离(Euclidean Distance)

欧几里得距离(Eucidean Distance),也称为欧氏距离,是数学中最常见的距离度量方式之一,用于计算两个点在欧几里得空间中的直线距离。
在二维空间中,如果有两个点 P1(x1,y1)P2(x2,y2)那么它们之间的欧几里得距离 d 可以通过下面的公式计算:
在这里插入图片描述
在三维空间中,如果有两个点 P1(x1,y1,z1)P2(x2,y2,z2),那么它们之间的欧几里得距离 d 可以通过下面的公式计算:1
在这里插入图片描述
对于更高维度的空间,欧几里得距离的计算公式可以推广为:
在这里插入图片描述

其中,x1i 和 x2i 分别是点 P1 和 P2在第 i 个维度上的坐标值。

欧几里得距离算法的优点是可以反映向量的绝对距离,适用于需要考虑向量长度的相似性计算
例如推荐系统中,需要根据用户的历史行为来推荐相似的商品,要考虑用户历史行为的数值,不只是用户历史行为。

(2)余弦相似度(Cosine Similarity)

余弦相似度(Cosine Similarity)是一种常用于度量两个向量在空间中的相似度的方法。它通过计算两个向量的点积和它们各自的模长来确定这两个向量之间的余弦角,从而反映它们之间的相似程度。

定义
对于两个向量A和B,余弦相似度 cos(0)定义为:
在这里插入图片描述
其中:
在这里插入图片描述
计算公式:
如果向量A和B分别表示为:
在这里插入图片描述
那么:
在这里插入图片描述
余弦相似度对向量的长度不敏感,只关注向量的方向,因此适用于高维向量的相似性计算。例如语义搜索和文档分类
余弦相似度的范围从-1到1,其中1表示完全相同的方向(完全相似),0表示正交(完全不相似),-1表示完全相反的方向(完全不相似)。

(3)点积相似度(Dot product similarity)

点积相似度(Dot Product Similarity),也称为向量内积相似度,是一种衡量两个向量之间相似度的方法。它通过计算两个向量的点积来评估它们之间的相似性。

定义
对于两个向量 A 和 B,点积相似度定义为:
Dot Product Similarity =A · B
其中,点积 A · B 计算为:
在这里插入图片描述

计算公式
在这里插入图片描述
如果点积结果为正数,表示两个向量之间存在正相关性,即它们在某种程度上是相似的。
如果点积结果为负数,表示两个向量之间存在负相关性,即它们在某种程度上是相反的。
如果点积结果为零,表示两个向量之间没有线性相关性。

特点
无归一化:点积相似度没有进行归一化处理,因此它对向量的长度敏感,这意味着如果两个向量的长度不同,即使它们的方向相同,它们的点积也可能不同。
范围:点积的值可以是正的、负的或零,取决于向量之间的相对方向,正点积表示向量之间的角度接近0度,负点积表示向量之间的角度接近180度,而零点积表示向量正交。

与余弦相似度比较
点积相似度与余弦相似度的主要区别在于:
点积相似度:对向量的长度敏感,没有归一化。
余弦相似度:对向量的长度不敏感,因为已经通过模长进行了归一化。

2、相似性搜索(Similarity Search)

对于传统数据库,搜索功能都是基于不同的索引方式(B+Tree、倒排索引等)加上精确匹配和排序算法(BM25、TF-IDF)等实现的。
本质还是基于文本的精确匹配,这种索引和搜索算法对于关键字的搜索功能非常合适,但对于语义搜索功能就非常弱。

对于向量搜索,通过比较向量之间的距离来判断它们的相似度。
想要在一个海量的数据中找到和某个向量最相似的向量,需要对数据库中的每个向量进行一次比较计算,计算量非常巨大。

高效的搜索算法有很多,其主要思想是通过两种方式提高搜索效率:
减少向量大小——通过降维或减少表示向量值的长度。
缩小搜索范围——可以通过聚类或将向量组织成基于树形、图形结构来实现,并限制搜索范围仅在最接近的族中进行,或者通过最相似的分支进行过滤。

大部分算法共有的核心概念,也就是聚类

(1)K-Means

K-means算法的核心思想是将数据划分为K个独立的簇(cluster)
使得每个簇内的数据点距离尽可能小。
而簇与旗之间的距离尽可能大。

下面是K-means算法的具体步骤:
1.初始化:选择K个数据点作为初始质心(centroid),这些质心可以是随机选择的,也可以是通过其他方法选定的。
2.分配:将每个数据点分配到离它最近的质心所代表的簇中。
3.更新:重新计算每个族的质心,方法是将簇内所有数据点的均值作为新的质心。
4.重复步骤2和3,直到质心不再发生显著变化或达到迭代次数上限。

选择了三个初始质点:
在这里插入图片描述
更新完成质点后:
在这里插入图片描述
聚类数目(K)的选择
K-Means算法的第一步是确定要将数据划分成多少个簇。这个选择通常基于领域知识或使用Elbow方法等统计技巧来确定。
K的选择对于聚类结果有着重要的影响。
如果K选择过小,可能会导致簇的划分不够细致,无法准确地反映数据的结构;
如果K选择过大,可能会导致簇的划分过于细致,会被数据的声影响,导致分类不准确。

距离的度量
K-Means使用欧式距离(Euclidean distance)来度量数据点之间的相似性,但也可以根据具体问题选择其他距离度量方法。

质心
每个簇都有一个质心,它是该簇内所有数据点的均值。质心代表了簇的中心位置。

优化目标
K-Means的优化目标是最小化每个数据点到其所属簇质心的距离之和。

优点
K-means算法具有以下优点:
1.简单易懂:K-means算法的步骡简单,容易理解和实现。
2.计算效率高:K-means算法的时间复杂度相对较低,适用于大规模数据集。
3.可扩展性强:K-means算法可以通过各种改进和优化应用于不同类型的教据和问题。

缺点
K-means算法也存在一些局限性:
1.需要预先指定K值:在实际应用中,选定合适的K值可能需要尝试多种方法。
2.对初始质心敏感:算法的结果可能受到初始质心选择的影响,导致局部最优解。
3.对噪声和离群点敏感:K-means算法容易受到噪声和离群点的影响,可能导致簇划分不准确。
4.对簇形状和大小敏感:K-means算法假设簇是凸的和大小相似的,对于其他形状和大小的簇可能效果不佳。

(2)改进方法

针对K-means算法的局限性,有以下改进方法:
1.选择合适的K值:可以尝试不同的K值,通过轮廓系数(Silhouette Coefficient)、肘部法则(Elbow Method)等方法评估聚类效果,选择最佳的K值。
2.优化初始质心选择:使用K-means++算法改进初始质心选择,降低算法收敛到局部最优解的风险。
3.增量式K-means:对于大规模数据集,可以采用增量式K-means算法进行分布式计算,提高计算效率。
4.引入核函数:将K·means算法扩展为Kernel K-means算法,使用核函数将数据映射到高维空间,处理非线性可分的数据。

肘部法则(Elbow Method)
基本原理是,随着簇数量K的增加,每个簇内的样本数会减少,因此簇内样本与簇中心的平均距离(即簇内误差平方和SSE)会逐渐减小。
当K增加到一定程度后,每增加一个簇,SSE的下降幅度会逐渐减小,形成一个“肘部”拐点。
这个拐点就是最佳的簇数量,因为在此之后增加簇数所带来的分类精度提升将不再显著。
在实际操作中,我们通常会绘制一个曲线图,横轴表示簇的数量K,纵轴表示SSE。
然后,观察曲线的变化趋势,寻找“肘部”位置。在Python中,可以使用matplotlib库来绘制这个曲线图,并通过观家图形来确定最佳的K值。
在这里插入图片描述

K-means++
K-means++ 是一种改进的 K-means 算法,主要针对初始质心选择的问题。K-means++的优势在于能够选择更好的初始质心,从而提高算法的收敛速度,降低陷入局部最优解的风险。
初始质心选取的基本思路就是,初始的聚类中心之间的相互距离要尽可能的远。

算法描述如下:
1、随机选取一个样本作为第一个聚类中心c1;
2、计算每个样本与当前已有类聚中心最短距离(即与最近一个聚类中心的距离),用 D(x)表示;
这个值越大,表示被选取作为聚类中心的概率较大;
最后,用轮盘法选出下一个聚类中心;
3、重复2,直到选出k个聚类中心。
4、使用选定的初始质心运行K-means 算法。

Kernel K-means
Kernel K-means 是一种基于核方法的K-means 算法,可以处理非线性可分的数据。
核方法通过将数据映射到高维特征空间,使得原本在低维空间中不可分的教据在高维空间中变得线性可分,

Kernel K-means 的主要步骤如下:
1.选择合适的核函数(如 RBF 核、多项式核等)和参数。
2.将数据集映射到高维特征空间。
3.在高维特征空间中执行 K-means 算法。
4.将聚类结果投影回原始数据空间。

Kernel K-means 可以处理复杂的数据结构,但计算复杂度相对较高,可能不适合大规模数据集。在实际应用中,可以根据问题的特点选择合适的K-means 算法变体。

应用场景
K-means算法广泛应用于各个领域,如:
1.图像分割:将图像中的像素聚类为K个簇,可以实现图像分割和简化。
2.文档聚类:将文档按照内容相似度进行聚类,有助于文档分类、信息检索和推荐系统。
3.客户细分:将客户按照购买行为、兴趣爱好等特征进行聚类,有助于企业针对不同群体制定个性化的营销策略。
4.异常检测:通过聚类,可以发现数据中的离群点或异常点,进而进行异常检测或数据清洗。
5.降维:K-means算法可以与主成分分析(PCA)等降维技术结合,实现数据降维和可视化。

3、近似邻近(ANN)

除了暴力搜索能完美的搜索出最相邻,所有的搜索算法只能在速度和质量还有内存上做一个权衡,这些算法也被称为近似最相邻(Approximate Nearest Neighbor)。

(1)Product Quantization(PQ)乘积量化

在大规模数据集中,聚类算法最大的问题在于内存占用太大。
这主要体现在两个方面,首先因为需要保存每个向量的坐标,而每个坐标都是一个浮点数,占用的内存就已经非常大了。除此之外,还需要维护聚类中心和每个向量的聚类中心索引,这也会占用大量的内存。

对于第一个问题,可以通过量化(Quantization)的方式解决,也就是常见的有损压缩。

假设图片检索库有1000万张图片,每张图片提取多个128维的特征向量,把这128维向量分成8个短向量,每个短向量是16维,也就是说检索库总共包含1000万x8这么多个16维的短向量。
如果当做2维矩阵的话就是1000万行x8列,每一列就是1000万个的短向量,每一列就是由每个原始128维向量对应16维子向量组成。
在这里插入图片描述
把每一列的子向量都用 k-means 聚类为 256 类,每一个短向是我们都找到他属于一堆短向量的256类中的哪一类。
这样每一行的8个短向量,都会对应于各自列的256类中的一个(一共有8个独立的256类),用0-255表示(也叫码字)。
从存储上来说是 8/16xsizeof(type),type是如 foat32,float16等等,比如原来16个foat16的向量,变成了一个8bt的值,也就是1/32(保存有256个类的中心数据,不过对比1000万个数据来说已经很小啦)。

现在128维向量,由8个8bit的数字组成。
在这里插入图片描述

距离计算
查询x的时候,也需要把x先PQ量化

对称距离计算:
直接使用两个压缩向量x,y的索引值所对应的码字q(x),q(y)之间的距离代替之,而q(x),q(y)之间的距离可以离线计算,相当于计算两个子类中心的距离可以把q(x),q(y)之间的距离制作成查找表,只要按照压缩向量的索引值进行对应的查找就可以了,所以速度非常快,
每k=256个类别对应256x256个距离,一共只需要8x256x256个距离。

非对称距离计算:
使用x,q(y)之间的距离代替x,y之间的距离,其中x是查询向量。
虽然y的个数可能有上百万个,但是q(y)的个数只有k=256个,对于每个x,我们只需要在输入x之后先计算一遍x和k个q(y)的距离,
相当于计算 x和每个子类中心的距离。
在这里插入图片描述

(2)分层小世界导航(HNSW)

除了聚类以外,也可以通过构建树或者构建图的方式来实现近似最近邻搜索。
这种方法的基本思想是每次将向量加到数据库中的时候,就先找到与它最相邻的向量,然后将它们连接起来,这样就构成了一个图。
当需要搜索的时候,就可以从图中的某个节点开始,不断的进行最相邻搜索和最短路径计算,直到找到最相似的向量。
在这里插入图片描述
使用类似跳表算法,如下图要搜索跳表,从最高层开始,沿着具有最长“跳过”的边向右移动。
如果发现当前节点的值大于要搜索的值,表示超过了目标,因此我们会在下一级中向前一个节点。

在这里插入图片描述
HNSW 继承了相同的分层格式,最高层具有更长的边缘(用于快速搜索),而较低层具有较短的边缘(用于准确搜索)。

具体来说,可以将图分为多层,每一层都是一个小世界,图中的节点都是相互连接的。

而且每一层的节点都会连接到上一层的节点,当需要搜索的时候,就可以从最上层开始,因为最上层的节点之间距离很长,可以减少搜索的时间,然后再逐层向下搜索,又因为最下层相似节点之间相互关联,所以可以保证搜索的质量,能够找到最相似的向量。

HNSW 算法是一种经典的空间换时间的算法,它的搜索质量和搜索速度都比较高,但是它的内存开销也比较大,因为不仅需要将所有的向量都存储在内存中,还需要维护一个图的结构,也同样需要存储。所以这类算法需要根据实际的场景来选择。

(3)局部敏感哈希(LSH)

局部敏感哈希(Locality Sensitive Hashing,LSH)也是一种使用近似最近邻搜索的索引技术。它的特点是快速,同时仍然提供一个近似、非穷举的结果。

LSH 使用一组哈希函教将相似向量映射到“桶”中,从而使相似向量具有相同的哈希值,这样,就可以通过比较哈希值来判断向量之间的相似度。
在这里插入图片描述
传统hash算法
通常设计的哈希算法都是力求减少哈希碰撞的次数,因为哈希函数的搜索时间复杂度是 O(1)。
如果存在哈希碰撞,即两个不同的关键字被映射到同一个桶中,那么就需要使用链表等教据结构来解决冲突。搜索的时间复杂度通常是 O(n),其中n是链表的长度。为了提高哈希函数搜索效率,会让哈希函数碰撞概率尽可能小。

LSH
但是在向量搜索中,我们的目的是为了找到相似的向量,可以专门设计一种哈希函数,使得哈希碰撞的概率尽可能,并且位置越近或者越相似的向量越容易碰撞,这样相似的向量就会被映射到同一个桶中。
等搜索特定向量时,为了找到给定查询向量的最近邻居,使用相同的哈希函教将类似向量“分桶“到哈希表中。
查询向量被散列到特定表中,然后与该表中的其他向量进行比较以找到最接近的匹配项。
这种方法比搜索整个数据集要快得多,因为每个哈希表桶中的向是远少于整个空间中的向量数。

其实就是将高维数据转化为低维数据,同时还能在一定程度上保持原始数据的相似性。
但 LSH 是不确定的,是概率性的,有可能将两个原本很相似的数据映射成两个不同的 hash 值,或者原本不相似的数据映射成同一hash值。
这是高维数据降维过程中所不能避免的(因为降维势必会造成某种程度上数据的失真),可以设计LSH 让参数控制出现这种错误的概率。

随机投影Random Projection for LSH
随机投影的核心思想是Johnson-Lindenstrauss引理。
如果向量空间中的点具有足够高的维数,那么它们可以以某种方式投影到合适的低维空间中,并且以高概率近似地保持点之间的成对距离。
通俗版JL引理:塞下N个向量,只需要O(logN)维空间。
在这里插入图片描述
JL引理说的是,不管这N个向是原来是多少维的,我们都可以将它们降到O(logN),并将相对距离的误差控制在一定范围内。
这是一个非常强、非常反直觉、非常实用的结论,比如我们要做向量检索,原本的向量维度可能非常大,这样全量检索一次的成本也非常大,而JL引理告诉我们,可以将它们变换到O(logN)维,并且检索效果近似不变。
在这里插入图片描述

随机投影的几何解释:
随机投影的关键在于,随机矩阵的行向量通常是接近正交的,因此投影矩阵在将数据映射到较低维时,能够近似保留原始点集的几何结构(例如点对之间的距离)。尽管维度大幅降低,但由于随机矩阵的特性,这种投影方法不会显著扭曲数据。

随机投影背后的基本思想是使用随机投影矩阵将高维向量投影到低维空间中。
创建一个由随机数构成的矩阵,其大小将是所需的目标低维值,然后,计算输入向量和矩阵之间的点积,得到一个被投影的矩阵,它比原始向是具有更少的维度但仍保留了它们之间的相似性。
当我们查询时,使用相同的投影矩阵将查询向量投影到低维空间。然后,将投影的査询向量与数据库中的投影向量进行比较,以找到最近邻居。由于数据的维数降低了,搜索过程比在整个高维空间中搜索要快得多。

LSH 的哈希函数族(Hash Family)
那具有怎样特点的 哈希函数 才能够使得原本相邻的两个数据点经过 hash 变换后会落入相同的桶内?

哈希函数族的定义:
对于任意距离度量 D,局部敏感哈希函数族 H 满足以下性质:
在这里插入图片描述
1)如果d(x,y)≤ d1, 则h(x)= h(y)的概率至少为p1;
2)如果d(x,y)≥ d2, 则h(x)= h(y)的概率至多为p2;
其中 d(x,y)是x和y之间的一个距离度量,d1<d2, h(x)和 h(y)分别表示对x和y进行 hash 变换。
满足以上两个条件的 哈希函数称为(d1,d2,p1,p2)-sensitive。
而通过一个或多个(d1,d2,p1,p2)-sensitive 的 哈希函数,对原始数据集合进行 哈希生成一个或多个hash table 的过程称为 Locality-sensitive Hashing。
满足(d1,d2,p1,p2)-sensitlve的哈希函数构成了 LSH 的哈希函数族。

LSH 常见的 哈希函数:
并不是所有的距离度量都能够找到满足 locality-sensitive 的 哈希函数,下面我们介绍一些满足不同距离度.量方式下的locality-sensitive的哈希函数:

欧几里得距离 的哈希函数族:
针对欧几里得距离的 LSH 哈希函数族通常基于随机投影的思想。常见的方法是使用基于分段的哈希函数。
在这里插入图片描述
还有:
余弦相似度的LSH函数族
组合哈希函数族

4、过滤向量搜索

实际数据通常包含时间、类别、用户 ID 和其他关键词等属性。对这些属性应用一个或多个过滤条件可以显著提高检索增强生成(RAG)系统的准确性,也适合一些多租户系统。

在文档内容较少的场景中,纯向量检索通常可以返回相对准确的候选项。然而,随着文档数量的增加,检索的召回率通常会迅速下降。

在金融、大型企业应用等复杂文档系统中,相关内容非常丰富,纯向是检索往往会返回许多相似但不正确的段落,从而对LLM 的最终响应的准确性产生负面影。

例如,在金融分析场景中,用户可能会问:“<a公司>的管理风格是什么?”,当<a公司>是一个不太常见的公司名称时,纯向是检索通常会返回许多相似但不准确的内容,比如关于类似 公司管理风格的段落,而不是a公司的内容,这会阻碍LLM对响应的准确生成。

如果我们事先知道与<a公司>相关的文档标题中包含了这个关键词,可以使用 WHERE title like '%<a公司>%' 进行预过滤,从而将搜索结果缩小为只包含相关文档。

LLM可以自动提取 <a公司>,例如作为函数调用中的参数或从查询文本生成 SOL WHERE 子句,确保系统灵活易用。

通过使用这些结构化属性进行过滤,在金融文档分析和企业知识库等实际应用中有60%到 90% 的准确率提升,确保 RAG 系统内的高准确性查询。

(1)namespace 机制

在大规模向量数据集上以非常低的过滤比例实现异常高的查询准确性,向量数据库做了专门设计。

如 Pinecone、Weaviate和Milvus,引入了namespace 机制,开发人员可以将每个用户的数据放在单独的命名空间中,以确保査询准确性。这种方法限制了灵活性,因为单个查询只能在一个命名空间内搜索,例如,在社交网络中,用户可能需要查询与他们的朋友相关的内容,涉及到数百到数千个朋友的数据的查询。
在上下文分析和推荐系统中通常需要复杂的过滤查询,基于时间、作者、关键词等。

过滤向量搜索的实现有很多技术细节选择,例如预过滤(Pre-filtering)与后过滤(Post-filtering)、行存储与列存储以及图形与树算法

(2)预过滤与后过滤

在过滤向量搜索中,实现元数据过滤有两种方法:预过滤和后过滤。
预过滤首先使用元数据选择满足条件的向量,然后搜索这些向量。
这种方法的优点是,如果用户需要k个最相似的文档,数据库可以保证返回k个结果。
缺点就是如果过滤后的数据比较少时,影响近似搜索算法效果。

后过滤涉及先进行向量搜索以获取m个结果,然后对这些结果应用元数据过滤。
这种方法的缺点是,m个结果中有多少满足元数据过滤条件是不确定的,可能导致最终结果少于K个,当满足过滤条件的向量稀缺时,后过滤的准确性显著降低。
优点不影响近似搜索算法。

PostgreSQL的向量检索插件 pgvector 采用了预过滤,在符合条件的数据比例较低时准确性显著降低。
例如,广泛使用的 HNSW算法在预过滤比例低(例如,过滤后只剩下1%的向量)时,搜索效果显著下降。
行业内常贝的解决方案是在过预滤比例低于特定阈值时采用暴力搜索。例如,Pinecone、Milvus和 ElasticSearch 都采用了这种方法,但是这可能会严重影响大型数据集的性能。

在这里插入图片描述

(3)行存储与列存储

在采用预过滤策略时,高效扫描元数据对检索性能至关重要。数据库存储通常分为行存储和列存储两种类型。
行存储通常用于事务性数据库,如 MySQL或 PostgreSQL,对于事务处理,特别是点读和写入,更加友好。
列存储教据库(如ClickHouse)对于分析处理,特别是扫描教据、批量数据插入和压缩存储方面非常高效。

在这里插入图片描述
由于需要高效扫描元数据,许多专门的向量数据库,如 Milvus 和 Qdrant,也采用了列存储。

经过多年对大规模结构化数据分析查询的优化,列式 SQL数据库如 ClickHouse在许多实际场景中表现更加出色,使用了跳过索引和 SIMD 操作等技术,显著提高了数据扫描效率。

在 RAG等应用中,小型写事务的需求较少,但高效的数据扫描和分析至关重要,列存储是一个更合适的选择。
pgvector 和 pgvecto.rs 等系统由于 PostgreSQL的行存储的限制,面临着过滤搜索准确性或速度的问题。
列式数据库最大的挑战是它们的多列点读效率低,这是由于数据读取放大和解压缩开销导致的,可以使用无压缩数据缓存等技术来解决这个问题。

在实际的业务场景中,往往不需要在整个向量数据库中进行相似性搜索,而是通过部分的业务字段进行过滤再进行查询。

向量数据库通常维护两个索引:一个是向量索引,另一个是元数据索引。然后,在进行相似性按索本身之前或之后执行元数据过滤,都存在导致查询过程变慢的困难。

三、向量数据库选型

前面介绍了向量数据库的相似性搜索算法的原理和实现,相似性搜索算法是向量数据库的核心和关键点。
但是在实际的业务场景中,往往还需要考虑其它的因素,例如向量数据库的可用性、扩展性、安全性等,还有代码是否开源、社区是否活跃等等。

1、分布式

一个成熟的向量数据库,往往需要支持分布式部署,这样才能满足大规模数据的存储和查询。数据拥有的越多,需要节点就越多,出现的错误和故障也就越多,所以分布式的向量数据库需要具备高可用性和容错性。

数据库的高可用性和容错性,往往需要实现分片和复制能力。
在传统的数据库中,往往通过数据的主键或者根据业务需求进行分片。
在分布式的向量数据库中,就需要考虑根据向量的相似性进行分区,以便查询的时候能够保证结果的质量和速度。
其它类似复制节点数据的一致性、数据的安全性等等,都是分布式向量数据库需要考虑的因素。

2、访问控制和备份

当组织和业务快速发展时,是否能够快速的添加新的用户和权限控制,是否能够快速的添加新的节点,审计日志是否完善等等,都是需要考虑的因素。
数据库的监控和备份也是一个重要的因素,当数据出现故障时,能够快速的定位问题和恢复数据,是一个成熟的向量数据库必须要考虑的因素。

3、API & SDK

API & SDK可能是往往被忽略的因素,但是在实际的业务场景中,API & SDK 往往是开发者最关心的因素。
API & SDK 的设计直接影响了开发者的开发效率和使用体验。
一个优秀良好的 API & SDK 设计,往往能够适应需求的不同变化,向量数据库是一个新的领域,容易忽视。

4、向量数据库对比

以下向量数据库的对比表格,从多个维度比较了各自的优缺点,以助于您进行技术选型:
在这里插入图片描述
全文搜索数据库
全文搜索数据库(如ElasticSearch和OpenSearch)能支持比较全面的文本检索和高级分析功能。
执行向量相似性搜索和处理高维度数据时,落后于专门的向量数据库。
这些数据库往往需要与其他工具搭配使用才能实现语义搜索,因为它们主要依赖于倒排索引而不是向量索引。根据Qdrant的测试结果,Elasticsearch在与Weaviate、Milvus和Odrant等向量数据库相比时,性能有所落后。

支持向量的SQL数据库
SQL数据库(pgvector、Supabase、starRocks)通过它们的向量支持扩展,提供了一种将向量数据整合到现有数据存储系统中的方式,但与专用的向量数据库相比有明显的缺点。
传统SQL数据库的关系模型与非结构化向量数据存在不匹配。这种不匹配导致了涉及向量相似性搜索的作效率低下,这类教据库在构建索引和处理大量向量数据时性能表现并不理想。
pgvector支持的向量维度上限(2000维)与像Weaviate这样的专用向量数据库相比显得较低,后者能够处理高达65535维的向量数据。
在可扩展性和效率方面,专用向量教据库也更有优势,支持向量的SQL数据库扩展,例如pgvector,更适合于向是数据量较小(少于10万个向量)且向量数据仅作为应用程序的一个补充功能的场暴。
如果向量数据是应用的核心,或者对可扩展性有较高要求,专用向量数据库就会是更合适的选择。

支持向量的NoSQL数据库(Redis,MongoDB)
NOSQL数据库中新增加的向量支持功能尚属初级阶段,以Redis向量相似性搜索(VSS)为例,该功能刚于2022年4月对外发布,距今不足两年。
Redis VSS虽然可以作为一个多功能数据库提供服务,但其并非专为向量相似性搜索而优化设计。

专用向量数据库
专用向量数据库(Pinecone、Milvus、Weaviate、Qdrant、Vald、Chroma、Vespa、Vearch)天生支持各种向量运算,如点积、余弦相似度等。
这些数据库专为处理高维度数据而设计,能够应对大量查询请求,并能迅速完成向量间的相似性搜索。
为了达到这些目标,它们采用了多种索引策略,通常基于近似最近邻(ANN)算法。这些算法需要在效率、存储空间占用和搜索准确性之间做权衡。
比如,FLAT索引是一种不使用任何优化或近似技术的向量索引,意味着可以实现100%的召回率和精确度,但它也比其他类型的向量索引更慢且效率更低。
相对而言,IVF_FLAT索引通过牺牲一些精确度,以换取更快的搜索速度。
HNSW索引则在准确性和搜索速度之间提供了一个折中方案。

Chroma则是专门为音频教据设计的系统,但在处理文本数据方面并未进行特别优化。相较于其他主流的向量数据库,Chroma在综合性能基准测试方面的资料相对匮乏,由于Chroma在其0.4版本中采用SQLite作为文档存储方式,可能在可扩展性和效率上不及其他专为向量数据设计的存储方案。
因此,对于RAG来说,Weaviate、Milvus、Qdrant和Vespa可能是最好的几个选择,理论上来说,应该基于性能和可扩展性的基准测试(详见下文ANN Benchmarks ANN 基准测试)来选择最合适的系统。但是还有一些系统设计、功能特点也是需要对比的。

支持的距离度量
在这里插入图片描述

5、传统数据的扩展

除了选择专业的向量数据库,使用传统数据库进行扩展也是一种方法。
Redis 除了传统的 Key Value 数据库用途外,Redis 还提供了 Redis Modules,例如使用 RediSearch模块来扩展向量搜索的功能。
PostgreSQL 提供插件的方式来支持向量存储和搜索功能,例如 pgvector 来开启向量按索的功能。它不仅支持精确和相似性搜索,还支持余弦相似度等相似性测量算法。
利用 PostgreSQL的所有功能,例如ACID事务、并发控制、备份和恢复等,还拥有所有的 PostgreSQL客户端库,因此可以使用任何语言的 PostgreSQL 客户端来访问它。可以减少开发者的学习成本和服务的维护成本。
ES和Clickhouse也对向量数据存储和搜索提供支持。

Logo

AtomGit 是由开放原子开源基金会联合 CSDN 等生态伙伴共同推出的新一代开源与人工智能协作平台。平台坚持“开放、中立、公益”的理念,把代码托管、模型共享、数据集托管、智能体开发体验和算力服务整合在一起,为开发者提供从开发、训练到部署的一站式体验。

更多推荐