LEANN 如何用 LAION 多模态基准通过 90% Recall@3 目标二分搜索出最优 search complexity?
2026/9/15 18:22:06 网站建设 项目流程

LEANN 如何用 LAION 多模态基准通过 90% Recall@3 目标二分搜索出最优 search complexity?

【免费下载链接】LEANN[MLsys2026 Best Paper]: https://arxiv.org/abs/2506.08276. RAG on Everything with LEANN. Enjoy 97% storage savings while running a fast, accurate, and 100% private RAG application on your personal device.项目地址: https://gitcode.com/GitHub_Trending/le/LEANN

LEANN 的搜索质量由complexity(搜索复杂度/候选列表大小)参数控制:api.py 中的文档字符串将其解释为 "Search complexity/candidate list size, higher = more accuracy but slower",即值越大结果越准但越慢。问题随之而来:多大的complexity刚好满足业务需要的精度目标?LEANN 仓库自带的 LAION 多模态基准(benchmarks/laion/README.md)把这件事做成了 Stage 3——在 caption→图片的自召回检索上,对 complexity 做 1–128 的二分搜索,自动找出达到 90% Recall@3 的最小复杂度,并在最优值附近做验证。本文按 setup_laion.py 和 evaluate_laion.py 的真实实现,还原这条从建索引到拿到最优 complexity 的操作路径。

准备条件:环境与依赖

运行基准脚本前需要:

  • Python >= 3.10(pyproject.toml 中requires-python = ">=3.10"),以及uv
  • 克隆 LEANN 仓库并进入仓库根目录,从源码同步工作区依赖。Linux (Ubuntu/Debian) 路径如下(README.md Installation 一节):
sudo apt-get update && sudo apt-get install -y \ libomp-dev libboost-all-dev protobuf-compiler libzmq3-dev \ pkg-config libabsl-dev libaio-dev libprotobuf-dev \ libmkl-full-dev uv sync --extra diskann

LAION 基准使用 HNSW 后端,如果你只需要 HNSW,README 说明可以用libopenblas-dev替代 MKL,并在同步命令中去掉--extra diskann

Stage 3 还有几个脚本自身会检查的前置条件:

  • FAISS flat 基线文件必须存在于baseline/目录(faiss_flat.indexmetadata.pkl),否则 evaluate_laion.py 会打印 "FAISS baseline not found" 并提示先运行setup_laion.py,然后退出;
  • 评估查询文件data/evaluation_queries.jsonl必须由 setup 生成;
  • 脚本会用sentence-transformers加载clip-ViT-L-14模型(首次运行会下载模型权重,需要网络)。

第一步:准备数据、索引与基线

benchmarks/laion目录下运行 setup 脚本(README.md Quick Start 的命令):

cd benchmarks/laion python setup_laion.py --num-samples 10000 --num-queries 200

该脚本会依次完成(见 setup_laion.py):

  1. 从 HuggingFacelaion/laion400m流式读取样本,异步并行下载图片到data/laion_images/
  2. clip-ViT-L-14(768 维、归一化向量)为每张图片生成嵌入,保存到data/clip_image_embeddings.npy
  3. 构建两个 LEANN 索引:紧凑索引data/laion_index.leannis_recompute=True, is_compact=True)和非紧凑索引data/laion_index_noncompact.leannis_recompute=False, is_compact=False),均为 HNSW 后端、graph_degree=32complexity=64cosine距离;
  4. 构建 FAISS flat 基线(IndexFlatIP)到baseline/faiss_flat.index,并保存图片 id 的metadata.pkl——这是 Recall 计算的 ground truth 来源;
  5. 从样本 caption 中抽样生成data/evaluation_queries.jsonl(随机种子固定为 42)。

注意该步骤有网络下载副作用(LAION 子集 + CLIP 模型权重),文件全部写入benchmarks/laion/data/benchmarks/laion/baseline/

第二步:运行 Stage 3 二分搜索

setup 完成后,在同一目录运行:

python evaluate_laion.py --index data/laion_index.leann --stage 3

--stage只接受2345all3表示 complexity 分析,all会顺序执行所有阶段。Stage 3 的内部流程(evaluate_laion.py):

  1. 重建非紧凑索引用于加速搜索。脚本先以is_recompute=Falseis_compact=False基于现有 passages 和预计算嵌入重建非紧凑索引到data/laion_index_noncompact.leann。原因是二分搜索要反复跑 Recall 评估,非紧凑索引可直接用存储的嵌入、跳过 recompute,搜索更快。

  2. 取前 50 条 caption 查询captions[:50])作为测试集。

  3. 二分搜索。固定target_recall = 0.9,搜索范围min_complexity, max_complexity = 1, 128,每轮取mid = (min + max) // 2

    • 若该复杂度下 Recall@3 ≥ 90%:记录为当前最优,令max_complexity = mid - 1,向更低复杂度搜索;
    • 否则:令min_complexity = mid + 1,向更高复杂度搜索。

    每轮评估都会打印当前 complexity 的 Recall@3 以及 "Target reached" / "Below target" 提示。

  4. 最优值附近验证。找到最优 complexity 后,脚本会额外测试best-2best+2共 5 个复杂度(上限 512),逐个打印 ✅(达到 90%)或 ❌(未达到),方便确认边界。

  5. 紧凑索引对照。最后用紧凑索引(recompute_embeddings=True)取前 10 条查询测试最优 complexity,打印 Recall 及与非紧凑索引结果的差值,让你确认 recompute 模式下精度没有明显漂移。

如何判断结果

成功时控制台会输出:

🎯 Optimal complexity found! Complexity: <找到的最小 complexity> Recall@3: <对应的 recall>

以及验证块:

🔬 Verification test around optimal complexity: ✅/❌ Complexity <N>: <xx.x>%

判断依据是"达到 90% 且复杂度尽可能小":脚本记录的是最后一个满足recall >= 0.9mid,且每次命中后继续向更小值收缩。如果 1–128 全部低于目标,脚本会打印 "Could not find complexity achieving 90% recall / All tested complexities were below target"——此时需要扩大搜索范围或检查数据,文档没有给出进一步的自动处理。

benchmarks/laion/README.md 中的 Benchmark Results 给出了文档示例结果(示例数值,不是每次运行都能复现的固定值):

Target Recall: 90% Optimal Complexity: 85 Binary Search Range: 1-128 Non-compact Index (fast search, no recompute)

限制与边界说明

  • 文档内部有一处配置口径不一致:benchmarks/laion/README.md 的 "Dataset Configuration" 写的是 CLIP ViT-B/32(512 维),但 setup_laion.py 与 evaluate_laion.py 实际加载的是clip-ViT-L-14(768 维),README 的 Benchmark Results 一节也写的是 ViT-L/14 768 维。按脚本实际行为为准。
  • README Notes 提到 "当前实现使用 dummy 数据演示、CLIP 嵌入随机生成",而脚本源码已实现真实下载与真实 CLIP 编码;如果你换过脚本版本,建议以运行输出中的 embedding shape 确认为何值。
  • Stage 3 会额外写出一个非紧凑索引(*_noncompact.leann)并保留给 Stage 4 使用;如果直接跑--stage all,全部阶段结束后脚本会自动删除这个临时非紧凑索引(按其文件名前缀匹配删除文件),这是脚本内置的文件删除行为。
  • --stage all还会执行 Stage 5 多模态生成,需要transformersQwen/Qwen2.5-VL-7B-Instruct模型;只做 complexity 搜索时不需要,用--stage 3即可。
  • Recall 的 ground truth 来自 FAISS flat 全量近邻搜索(IndexFlatIP,k=3),每条查询的 recall 按与 ground truth 三个 id 的交集大小除以 3 计算,平均后与 90% 目标比较。

下一步

拿到最优 complexity 后,脚本在--stage all结尾给出的建议是 "Use optimal complexity for best speed/accuracy balance"。实际搜索时把它传给LeannSearcher.search(caption, top_k=3, complexity=<最优值>, ...)即可(complexity的 API 默认值为 64)。如果需要进一步量化紧凑索引的存储节省与搜索速度比,可运行 Stage 4:

python evaluate_laion.py --index data/laion_index.leann --stage 4 --output results.json

Stage 4 会复用 Stage 3 留下的非紧凑索引,对比两类索引的.index大小、存储节省百分比与平均搜索时间,并把指标 JSON 写入--output指定的文件。

【免费下载链接】LEANN[MLsys2026 Best Paper]: https://arxiv.org/abs/2506.08276. RAG on Everything with LEANN. Enjoy 97% storage savings while running a fast, accurate, and 100% private RAG application on your personal device.项目地址: https://gitcode.com/GitHub_Trending/le/LEANN

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询