HNSW 索引简介及Chroma索引配置

问题引入

ChromaDB 是一个 kinf od 向量数据库,能够存储文本文档、音频和图像等高维数据。为了存储这些高维数据,ChromaDM 使用嵌入以多维向量的形式重新发送这些数据。这意味着所有这些类型的文本、图像都以向量的形式存储在 ChromaDB 中,向量由多个维度组成。

在检索过程中,输入查询或问题被转换为多维向量,所需的数据或用户输入或查询的答案通过使用相似距离(如余弦等)来检索。这意味着给定一个 input 查询,它被转换为 vector 和 cosine similarity 或者计算此 input query 和所有其他 embeddings 之间的任何其他相似性。也就是说对于每个问题,计算量等于 ChromaDB 中存储的嵌入数。

可以想见, 在 ChromaDB 中给定 n 个问题和 m 个向量嵌入,计算总数为 n*m。随着问题的增加和规模的增长,检索问题答案所需的计算将成为瓶颈。

ChromaDB 中索引的重要性:

为了减少计算向量的数量,Db 像 ChromaDB 一样引入了索引的概念。索引是一个概念,它通过引入一个向量/嵌入来加快计算速度,该向量/嵌入将表示一组类似的向量嵌入。此索引的重要性在于,它在单个嵌入向量之上创建一个附加层,其中每个索引映射到一组相似的向量。因此,索引将搜索空间划分为离散数量的分区。使用这些分区,查询的搜索空间可以只关注向量索引的几个部分,而不是完整的搜索空间。

这个概念的优点是,每当使用用户输入查询嵌入从 ChromaDB 中检索类似的答案时,它不需要与每个向量进行比较,而是首先尝试找到查询和索引之间的距离。由于每个索引都映射到一组相似的嵌入,因此与对每个嵌入进行相似性搜索相比,计算次数要少得多。

确定合适和相似的索引后,仅将查询嵌入与所选索引相关的向量嵌入进行比较,该向量嵌入与查询的相似度最高。因此,使用这种 partition logic ,计算在很大程度上减少了,延迟也得到了改善。

ChromaDB 的默认索引策略 (HNSW):

在这里插入图片描述
Hierarchical Navigable Small World (HNSW) : HNSW 是构建向量索引的最流行的算法之一。它非常快速和高效。

HNSW 是一种用于索引数据的多层图形方法。在最低级别,捕获索引中的每个向量。当我们在图表中向上移动图层时,数据点会根据相似性分组在一起,以指数方式减少每层中的数据点数量。在单个层中,点根据其相似性进行连接。每一层中的数据点也连接到下一层中的数据点。

HNSW 创建一个分层的树状结构,其中树的每个节点都表示一组向量。节点之间的边表示向量之间的相似性。该算法首先创建一组节点,每个节点都有少量的向量。这可以随机完成,也可以通过使用 k-means 等算法对向量进行聚类来完成,其中每个聚类都成为一个节点。

使用聚类算法识别节点后,它会检查每个节点及其关联的向量。在两个具有相似向量的节点之间绘制一条边。

HNSW 索引使用两个概念来构建索引:

Probability Skip List 概率跳过列表

Skip lists 通过构造多层链表来工作。在第一层上,跳过大多数中间节点/顶点的链接。向下移动层,跳过的数量会减少。在跳过列表中搜索时,我们从跳过时间最长的最高层开始,然后沿着边缘向列表右侧移动。如果当前节点键大于我们正在搜索的键 — 我们知道我们已经超过了目标,因此我们在下一级别向下移动到前一个节点。

Navigable Small World Graphs

要了解有关 HNSW 指数的更多信息,请参阅文章:
https://www.pinecone.io/learn/series/faiss/hnsw/

要初始化 HNSW 索引,我们必须考虑两个参数:

  • M — 这表示我们在插入时添加到每个顶点的邻居数。这是 ChromaDB M_max 和 M_max0 隐式设置的另外两个参数。M_max值设置为 M,M_max0 设置为 M*2。
  • ef — 这表示在收集前 M 个最近的邻居时要考虑多少个候选人。
    这是我们在 ChromaDB 中使用 HNSW 索引时必须仔细调整的两个值。
db = Chroma.from_documents(docs, embedding_model, persist_directory="./chroma_db_instance",collection_metadata={"hnsw:M": 1024,"hnsw:ef": 64})

References: 引用:
https://www.pinecone.io/learn/series/faiss/hnsw/
https://arxiv.org/pdf/1603.09320.pdf
https://www.pinecone.io/learn/vector-database/
https://15721.courses.cs.cmu.edu/spring2018/papers/08-oltpindexes1/pugh-skiplists-cacm1990.pdf
https://github.com/hwchase17/chat-your-data/blob/master/state_of_the_union.txt

### Chroma 向量召回实现方法 Chroma 是一种高效的向量数据库解决方案,特别适用于处理大规模的向量数据。为了实现高效且精准的向量召回,通常采用以下几种关键技术: #### 1. 数据预处理与嵌入生成 在进行向量召回之前,需要先将原始数据转换为固定长度的向量表示形式。这一步骤可以通过训练好的神经网络模型来完成,例如 BERT 或者其他预训练的语言模型。 ```python from sentence_transformers import SentenceTransformer model = SentenceTransformer('all-MiniLM-L6-v2') sentences = ["This is an example sentence", "Each sentence is converted"] embeddings = model.encode(sentences) print(embeddings.shape) # 输出 (2, 384),其中384是embedding维度 ``` 这种做法不仅提高了效率还增强了语义理解能力[^4]。 #### 2. 构建索引结构 对于大量向量数据来说,直接线性扫描是非常低效的方式。因此,在实际应用中会构建特定类型的索引来加速最近邻搜索过程。常见的索引类型包括但不限于 FAISS、HNSW 等。 ```python import faiss index = faiss.IndexFlatL2(768) # 使用 L2 距离度量创建索引 index.add(embeddings.astype('float32')) # 添加向量至索引库 D, I = index.search(xq=queries, k=5) # 查询最相似的前五个结果 ``` 此步骤显著减少了查找时间并提升了系统的响应速度[^3]。 #### 3. 召回优化技巧 除了上述基础设置外,还可以采取一些额外措施进一步改善性能表现: - **多级过滤机制**:当面对极其庞大的数据集时,可以考虑引入分级检索策略,即先粗略定位可能区域再精细挑选目标对象。 - **负样本挖掘**:通过分析历史交互记录中的错误案例,主动识别那些容易被误判的情况作为反面教材加入训练集中重新学习调整参数配置从而降低未来犯错几率。 - **动态更新维护**:随着新资料不断涌入旧有的知识体系可能会变得过时所以有必要定期刷新内容保持最新状态同时也要注意平衡增量部分与其他已有条目间的关系确保整体连贯一致而不至于造成混乱局面。 这些方法有助于提高最终输出的质量以及用户体验满意度[^1]。 #### 4. 常见问题及对应方案 尽管已经做了很多努力但仍不可避免遇到各种挑战比如冷启动难题(Cold Start Problem)、热门偏差现象(Popularity Bias)等都需要针对性地加以克服: - 对于初次访问的新用户由于缺乏足够的行为特征可供参考往往难以给出个性化推荐此时可借助外部资源如社交平台上的好友圈子偏好趋势来进行初步猜测引导直至积累起一定量级的信息后再逐步过渡到基于个人兴趣爱好的精细化服务模式上去。 - 针对某些高频次出现却未必真正受欢迎的内容过度曝光问题则建议实施多样化的展示逻辑打破单一排序规则限制鼓励探索未知领域给予更多机会让优质但低调的作品浮出水面获得应有的关注。 综上所述通过对以上几个方面的深入研究实践相信能够在很大程度上缓解乃至彻底解决这些问题带来的困扰使得整个系统更加稳健可靠易于管理维护同时也更好地满足了广大用户的多样化需求期待着在未来的发展道路上取得更大的进步空间[^2]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值