稠密向量搜索
重要概念
密集向量表示
可以将传统的标记化 倒排索引视为将文本建模为“稀疏”向量的过程,其中语料库中的每个术语对应一个向量维度。在这种模型中,维度数通常很高(对应于术语词典基数),并且任何给定文档的向量主要包含零(因此它是稀疏的,因为总体索引中存在的少数术语将出现在任何给定文档中)。
稠密向量表示与基于术语的稀疏向量表示形成对比,因为它将近似的语义含义提炼为固定(且有限)的维度数。
这种方法中的维度数通常远低于稀疏情况,并且任何给定文档的向量都是稠密的,因为其大多数维度都由非零值填充。
与稀疏方法(使用标记器直接从文本输入生成稀疏向量)相反,生成向量的任务必须在 Apache Solr 外部的应用程序逻辑中处理。
在某些情况下,直接搜索以向量形式原生存在的(例如科学数据)数据是有意义的;但在文本搜索上下文中,用户可能会利用深度学习模型(例如 BERT)将文本信息编码为稠密向量,在索引和查询时明确地向 Apache Solr 提供结果向量。
有关更多信息,你可以参考这篇 博客文章。
稠密检索
给定一个对信息需求进行建模的稠密向量 v
,提供稠密向量检索的最简单方法是计算 v
与表示信息语料库中某个文档的每个向量 d
之间的距离(欧几里得距离、点积等)。
这种方法相当昂贵,因此目前正在积极研究许多近似策略。
Apache Lucene 中实现并由 Apache Solr 使用的策略基于可导航小世界图。
它为高维向量提供了高效的近似最近邻搜索。
请参阅 基于可导航小世界图的近似最近邻算法 [2014] 和 使用分层可导航小世界图进行高效且稳健的近似最近邻搜索 [2018] 了解详情。
索引时间
这是 Apache Solr 字段类型,旨在支持稠密向量搜索
DenseVectorField
稠密向量字段提供了索引和搜索浮点元素稠密向量的可能性。
例如
[1.0, 2.5, 3.7, 4.1]
以下是如何在模式中配置 DenseVectorField
<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
vectorDimension
-
必需
默认值:无
要传入的稠密向量的维度。
可接受的值:任何整数。
similarityFunction
-
可选
默认值:
euclidean
向量相似性函数;用于在搜索中返回与目标向量最相似的 K 个向量。
可接受的值:
euclidean
、dot_product
或cosine
。
此相似性旨在作为执行余弦相似性的优化方式。为了使用它,所有向量都必须是单位长度,包括文档向量和查询向量。对非单位长度的向量使用点积可能会导致错误或搜索结果不佳。 |
-
cosine
:余弦相似性
执行余弦相似性的首选方法是将所有向量归一化为单位长度,然后使用 DOT_PRODUCT。只有在需要保留原始向量且无法预先对其归一化时,才应使用此函数。 |
要使用以下高级参数来自定义编解码器格式和 HNSW 算法的超参数,请确保模式编解码器工厂正在使用中。
以下是使用高级超参数配置 DenseVectorField
的方法
<fieldType name="knn_vector" class="solr.DenseVectorField" vectorDimension="4" similarityFunction="cosine" knnAlgorithm="hnsw" hnswMaxConnections="10" hnswBeamWidth="40"/>
<field name="vector" type="knn_vector" indexed="true" stored="true"/>
knnAlgorithm
-
可选
默认值:
hnsw
(高级)指定要使用的底层 knn 算法
可接受的值:
hnsw
。
请注意,knnAlgorithm
可接受的值可能会在未来版本中发生更改。
vectorEncoding
-
可选
默认值:
FLOAT32
(高级)指定稠密向量元素的底层编码。这会影响已编制索引和已存储字段(如果已启用)的内存/磁盘影响
可接受的值:
FLOAT32
、BYTE
。 hnswMaxConnections
-
可选
默认值:
16
(高级)此参数特定于
hnsw
knn 算法控制与新节点连接的最近邻候选节点的数量。
它与 2018 年论文中的
M
具有相同的含义。可接受的值:任何整数。
hnswBeamWidth
-
可选
默认值:
100
(高级)此参数特定于
hnsw
knn 算法它是为每个新插入的节点搜索图时要跟踪的最近邻候选节点的数量。
它与 2018 年论文中的
efConstruction
具有相同的含义。可接受的值:任何整数。
DenseVectorField
支持以下属性:indexed
、stored
。
目前不支持多值 |
以下是 DenseVectorField
的编制索引方法
JSON
[{ "id": "1",
"vector": [1.0, 2.5, 3.7, 4.1]
},
{ "id": "2",
"vector": [1.5, 5.5, 6.7, 65.1]
}
]
XML
<add>
<doc>
<field name="id">1</field>
<field name="vector">1.0</field>
<field name="vector">2.5</field>
<field name="vector">3.7</field>
<field name="vector">4.1</field>
</doc>
<doc>
<field name="id">2</field>
<field name="vector">1.5</field>
<field name="vector">5.5</field>
<field name="vector">6.7</field>
<field name="vector">65.1</field>
</doc>
</add>
SolrJ
final SolrClient client = getSolrClient();
final SolrInputDocument d1 = new SolrInputDocument();
d1.setField("id", "1");
d1.setField("vector", Arrays.asList(1.0f, 2.5f, 3.7f, 4.1f));
final SolrInputDocument d2 = new SolrInputDocument();
d2.setField("id", "2");
d2.setField("vector", Arrays.asList(1.5f, 5.5f, 6.7f, 65.1f));
client.add(Arrays.asList(d1, d2));
查询时间
这是 Apache Solr 查询方法,旨在支持稠密向量搜索
knn 查询解析器
knn
k-最近邻查询解析器允许根据给定字段中的索引密集向量,找到与目标向量 k-最近邻的文档。
检索到的文档的分数是到目标向量的近似距离(由索引时配置的 similarityFunction 定义)。
它采用以下参数
f
-
必需
默认值:无
要搜索的
DenseVectorField
。 topK
-
可选
默认值:10
要返回的 k-最近邻结果数。
以下是运行 KNN 搜索的方法
&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
检索到的搜索结果是输入向量 [1.0, 2.0, 3.0, 4.0]
的 k-最近邻,按索引时配置的 similarityFunction 排序。
与过滤器查询一起使用
knn
查询解析器可用于过滤器查询
&q=id:(1 2 3)&fq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
knn
查询解析器可与过滤器查询一起使用
&q={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]&fq=id:(1 2 3)
过滤器查询作为预过滤器执行:主查询细化从所有过滤器查询的应用中派生的搜索结果子集,这些查询组合为“必须”子句(布尔 AND)。 这意味着在
结果由 topK knn 检索预先过滤,然后仅返回与查询“q=id:(1 2 3)”匹配的此子集中的文档。 在
结果由 fq=id:(1 2 3) 预先过滤,然后仅将此子集中的文档视为 topK knn 检索的候选者。 如果您想将某些过滤器查询作为后置过滤器运行,则可以使用 Apache Solr 中的后置过滤标准方法,使用缓存和成本本地参数。 例如
|
作为重新排序查询使用
knn
查询解析器可用于重新对第一遍查询结果进行排序
&q=id:(3 4 9 2)&rq={!rerank reRankQuery=$rqq reRankDocs=4 reRankWeight=1}&rqq={!knn f=vector topK=10}[1.0, 2.0, 3.0, 4.0]
在重新排序中使用 仅当第一遍的文档 这意味着第二遍的 最终排名的结果列表将第一遍分数(主查询 有关使用重新排序查询解析器的详细信息,请参阅 查询重新排序 部分。 |