<?xml version="1.0" encoding="UTF-8"?>
<rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0">
  <channel>
    <title><![CDATA[Valentin Crettaz - Elasticsearch Labs]]></title>
    <description><![CDATA[Articles and tutorials from the Search team at Elastic]]></description>
    <copyright><![CDATA[© 2026. Elasticsearch B.V. All Rights Reserved]]></copyright>
    <image>
      <title><![CDATA[Valentin Crettaz - Elasticsearch Labs]]></title>
      <url>https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt1121c0bf0e8a6e65/6a88da6340a1841030ef456f/search-labs-thumbnail.png</url>
      <link>https://www.elastic.co/cn/search-labs/author/valentin-crettaz</link>
    </image>
    <link>https://www.elastic.co/cn/search-labs/author/valentin-crettaz</link>
    <atom:link href="https://www.elastic.co/cn/search-labs/rss/author/valentin-crettaz.xml" rel="self" type="application/rss+xml"/>
    <language><![CDATA[cn]]></language>
    <lastBuildDate>Tue, 22 Sep 2026 18:33:48 GMT</lastBuildDate>
  <item>
    <title><![CDATA[矢量搜索简介]]></title>
    <description><![CDATA[本文是三篇系列文章中的第一篇，将深入探讨矢量搜索（也称语义搜索）的复杂性以及如何在 Elasticsearch 中实现。]]></description>
    <content:encoded><![CDATA[<p>本文是三篇系列文章中的第一篇，将深入探讨矢量搜索（也称语义搜索）的复杂性以及如何在 Elasticsearch 中实现。</p><p>第一部分重点介绍嵌入向量的基础知识以及向量搜索的工作原理。</p><p>有了在第一篇文章中学到的所有知识，<a href="https://www.elastic.co/search-labs/blog/vector-search-set-up-elasticsearch">第二部分</a>将指导你如何在 Elasticsearch 中设置矢量搜索。</p><p>在<a href="https://www.elastic.co/search-labs/blog/hybrid-search-elasticsearch">第三部分</a>中，我们将利用在前两部分中学到的知识，在此基础上深入研究如何在 Elasticsearch 中创建强大的混合搜索查询。</p><p>在进入本文的正题之前，让我们回顾一下向量的历史，向量是语义搜索的一个关键概念。</p><h2>病媒并不新鲜</h2><p>相信每个人都会同意，自 2022 年 11 月 ChatGPT 问世以来，没有一天不听到或读到关于 "矢量搜索 "的消息。它无处不在，如此普遍，以至于我们经常会觉得这是一项刚刚问世的新尖端技术，但事实上，这项技术已经存在了六十多年！对这一主题的研究始于 20 世纪 60 年代中期，1978 年，信息检索专家杰拉德-萨尔顿和他在康奈尔大学的同事发表了第一批研究论文。萨尔顿在密集和稀疏向量模型方面的研究成果是现代向量搜索技术的基础。</p><p>在过去的 20 年里，基于他的研究成果，许多不同的<a href="https://db-engines.com/en/ranking/vector+dbms/all">矢量数据库管理系统</a>相继问世并推向市场。其中包括由 Apache Lucene 项目提供支持的 Elasticsearch，该项目于 2019 年开始<a href="https://issues.apache.org/jira/browse/LUCENE-9004">致力于矢量搜索</a>。</p><p>矢量现在无处不在，非常普遍，因此在使用矢量之前，首先要充分掌握其基本理论和内部工作原理。在深入探讨之前，让我们先快速回顾一下词法搜索和矢量搜索之间的区别，以便更好地理解它们的不同之处以及如何相互补充。</p><h2>矢量搜索与词法搜索</h2><p>介绍向量搜索的一个简单方法是将其与你可能已经习惯的更传统的词法搜索进行比较。矢量搜索（通常也称为语义搜索）和词法搜索的工作原理截然不同。词法搜索是我们在 Elasticsearch 中使用多年的一种搜索方式。简而言之，它并不试图理解所索引和查询内容的真正含义，而是努力将用户在查询中键入的单词或其变体（如词干、同义词等）的字面意思与之前已通过相似性算法（如 TF-IDF）索引到数据库中的所有字面意思进行<strong>词法</strong>匹配。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltfbb8e150865a5ec8/6a17e0c725daab50f408a16e/a4f3eba19599e5330e9b0d29ecdbbeac211cdab0-1600x583.png" alt="词法搜索示例" /><p>我们可以看到，左上方的三份文档已经进行了标记化和分析。然后，将得到的术语编入倒排索引，该索引只是将分析术语映射到包含这些术语的文档 ID。请注意，所有术语都只出现一次，没有任何文件共享这些术语。搜索 "优秀的德国教师 "时，三份文档的匹配得分各不相同，但没有一份真正符合查询的真正含义。</p><p>如下图 2 所示，在处理多义词或同形词（即拼写相同但<strong>含义不同的词</strong>（right、palm、bat、mean 等））时，情况会变得更加棘手。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltea0cc829ff2c8029/6a17e0c92f4a5c8107fa8811/ebb9cc1be03475bbf68269a8dcea5f08bcda0b64-1594x754.png" alt="用词法搜索查找同形词" /><p>搜索<em>"我不对"</em>，返回的文档与第一个返回结果的含义完全相反。如果搜索完全相同的术语，但为了产生不同的含义而对它们进行不同的排序，例如<em>"向右转 "</em>和<em>"</em> 右转"，则会得到完全相同的结果（即第三份文档 "向右转"）。当然，我们的查询过于简化，没有使用短语匹配等更高级的查询，但这有助于说明词法搜索并不了解索引内容和搜索内容背后的真正含义。如果还不清楚，也不要着急，我们将在第三篇文章中再次讨论这个例子，看看矢量搜索在这种情况下如何提供帮助。</p><p>对词法搜索来说，当你能够控制如何为<strong>结构化</strong>数据建立索引（如映射、文本分析、摄取管道等）以及如何制作查询（如巧妙制作的 DSL 查询、查询词分析等）时，你就能利用词法搜索引擎创造奇迹，这是毋庸置疑的！Elasticsearch 的词法搜索能力令人惊叹。在过去的几年里，它所取得的成就以及它对词法搜索领域的普及和改进确实令人瞩目。</p><p>但是，如果要为需要提出自由文本问题的用户提供<a href="https://www.elastic.co/what-is/unstructured-data"><strong>非结构化</strong></a><a href="https://www.elastic.co/what-is/unstructured-data"> 数据</a>（如图像、视频、音频、原始文本等）的查询支持，词法搜索就显得力不从心了。此外，有时查询的内容甚至不是文本，而可能是图片，我们很快就会看到。在这种情况下，词法搜索无法胜任的主要原因是，非结构化数据既无法像结构化数据那样被索引，也无法像结构化数据那样被查询。在处理非结构化数据时，<strong>语义学</strong>开始发挥作用。语义学是什么意思？很简单，就是这个意思！</p><p>让我们以简单的图像搜索引擎（如谷歌图像搜索或 Lens）为例。您只需拖放一张图片，谷歌语义搜索引擎就会找到并返回与您查询的图片最相似的图片。在下图 3 中，我们可以看到左侧是一张德国牧羊犬的图片，右侧是所有已检索到的相似图片，第一个结果是与所提供图片相同的图片（即最相似的图片）。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt3e0a0fb3c300537a/6a17e0cbe8fbce69d13a185d/c0dff24d4379141abd1038c9c4b5577fd2dca802-1600x657.png" alt="语义搜索示例：搜索图片" /><p>尽管这对我们人类来说听起来简单且合乎逻辑，但对计算机来说却是另一回事。这正是矢量搜索所能实现和帮助实现的。矢量搜索所释放的能量是巨大的，全世界最近都见证了这一点。现在，让我们揭开引擎盖，看看下面隐藏着什么。</p><h2>嵌入向量</h2><p>正如我们在前面所看到的，通过词法搜索引擎，文本等结构化数据可以很容易地被标记为在搜索时可以匹配的术语，而不管这些术语的真正含义是什么。然而，非结构化数据可以采用不同的形式，例如大型二进制对象（图像、视频、音频等），而且完全不适合采用相同的标记化流程。此外，语义搜索的整个目的就是为数据编制索引，以便根据数据所代表的意义进行搜索。我们如何做到这一点？答案就在两个字里：<strong>机器学习</strong>！或者更准确地说，是深度学习！</p><p><strong>深度学习</strong>是机器学习的一个特定领域，它依赖于基于人工神经网络的多层处理模型，可以逐步提取数据的真实含义。这些神经网络模型的工作方式在很大程度上受到了人脑的启发。下图 4 显示了神经网络的外观，包括输入层、输出层和多个隐藏层：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt8ca5fd8f0e61d939/6a17e0cd7f6f152a67c09a53/aeea3bab3c29e1c591a9c9082f2e73e7d3990ef1-1600x1116.png" alt="向量搜索中的神经网络层" /><p>神经网络的真正功能在于，它能够将单个非结构化数据转化为浮点数值序列，这些浮点数值被称为<strong>嵌入向量</strong>或简称<strong>嵌入</strong>。作为人类，只要将向量在二维或三维空间中形象化，我们就能很好地理解向量是什么。矢量的每个分量代表二维 x-y 平面或三维 x-y-z 空间中的一个坐标。</p><p>然而，神经网络模型所依赖的嵌入向量可能有几百甚至上千个维度，而且仅仅代表多维空间中的一个点。每个向量维度代表非结构化数据的一个<strong>特征</strong>或特性。让我们用一个将图像转化为 2048 维嵌入向量的深度学习模型来说明这一点。该模型将把我们在图 3 中使用的德国牧羊犬图片转化为下表所示的嵌入向量。请注意，我们只显示了前三个元素和后三个元素，但表格中还有 2,042 个列/维度。</p><p></p><p>is_red</p><p>是狗</p><p>blue_sky</p><p>…</p><p>no_gras</p><p>德国牧羊犬</p><p>is_tree</p><p>德国牧羊犬 嵌入</p><p>0.0121</p><p>0.9572</p><p>0.8735</p><p>…</p><p>0.1198</p><p>0.9712</p><p>0.0512</p><p>每一列是模型的一个维度，代表底层神经网络试图建模的一个特征或特性。根据输入与 2048 个维度中每个维度的相似程度，对模型的每个输入进行特征描述。因此，嵌入向量中每个元素的值表示该输入与特定维度的<strong>相似度</strong>。在这个例子中，我们可以看到模型检测到狗和德国牧羊犬之间的高度相似性，以及一些蓝天的存在。</p><p>与词法搜索相比，矢量搜索能让我们更好地了解非结构化数据与模型支持的每个维度的<em>相似</em>程度。因此，嵌入向量可以作为非结构化数据的绝佳语义表示。</p><h2>秘制酱汁</h2><p>既然我们已经知道深度学习神经网络是如何将非结构化数据切成嵌入向量的，这些嵌入向量可以从多个维度捕捉数据的相似性，那么我们就需要了解这些向量的匹配是如何进行的。事实证明，答案非常简单。相互<strong>接近</strong>的嵌入向量代表<strong>语义相似的</strong>数据片段。因此，当我们查询矢量数据库时，搜索输入（图像、文本等）首先会使用索引所有非结构化数据时使用的相同模型转化为嵌入矢量，最终目标是找到与该查询矢量<strong>最近的相邻矢量</strong>。因此，我们需要做的就是找出如何测量查询向量与数据库中索引的所有现有向量之间的 "距离 "或 "相似性"，仅此而已。</p><h3>距离和相似性</h3><p>幸运的是，由于有了向量算术，测量两个向量之间的距离是一个很容易解决的问题。因此，让我们来看看现代矢量搜索数据库（如 Elasticsearch）支持的最常用的距离和相似性函数。警告，前方有数学题！</p><h4>L1 距离</h4><p>两个向量 x 和 y 的 L1 距离（也称为曼哈顿距离）是通过将它们所有元素的成对绝对差值相加来测量的。显然，距离 d 越小，两个矢量就越接近。计算公式非常简单，如下所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt2df2e9bc20883491/6a17e0ce033c8d006a6bb0bf/2b17bcedfbedde61117a3e7970af55bc62318c6c-312x102.png" alt="向量搜索中的 L1 距离公式" /><p>下图 5 可以直观地说明 L1 距离：</p><p></p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb90a33e6b1cbe00b/6a17e0d0414c64eb76945096/52075441892151536ed216081817a8e852566daa-474x464.png" alt="可视化两个向量之间的 L1 距离" /><p>假设有两个向量 x 和 y，例如 x = (1, 2) 和 y = (4, 3)，那么这两个向量的 L1 距离为 | 1 - 4 | + | 2 - 3 | = 4。</p><h4>L2 距离</h4><p>测量两个向量 x 和 y 的 L2 距离（也称欧几里得距离）的方法是，首先求出它们所有元素成对差值的平方和，然后取其平方根。它基本上是两点之间最短的路径（也称为斜边）。与 L1 类似，距离 d 越小，两个向量越接近：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltae9b63fb593ae225/6a17e0d1af47b68379cddea8/b7675aa41f4f381e954c21dacd23a51a2dde6780-384x112.png" alt="向量搜索中的 L2 距离" /><p>L2 距离如下图 6 所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt32d913b46e07e79d/6a17e0d27f6f1582f7c09a57/bac99d08d6cf8a3a387a8acdc2e8f67357dad235-448x456.png" alt="可视化两个向量之间的 L2 距离" /><p>让我们重新使用与 L1 距离相同的两个样本向量 x 和 y，现在我们可以计算出 L2 距离为。10 的平方根就是 3.16。</p><p></p><h4>林夫距离</h4><p>两个向量 x 和 y 的 Linf（表示 L 无穷大）距离，也称为切比雪夫距离或棋盘距离，简单地定义为这两个向量的任意两个元素之间的最长距离，或沿其中一个轴/维测量的最长距离。计算公式非常简单，如下所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt863411e15de16fa3/6a17e0d4505ac30939ad8a48/179ea6c6520a59acd97638313a2fb1b105e2ffed-436x82.png" alt="矢量搜索中的林夫距离公式" /><p>林夫距离的表示方法如下图 7 所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt863ee7b51fd5fc15/6a17e0d56864a4772db686af/b75540d793cdc0645244d77dc36da9d5734ccbac-548x560.png" alt="两个向量之间的林夫距离" /><p>同样，取相同的两个样本向量 x 和 y，我们可以计算出无穷大距离为 max ( | 1 - 4 | , | 2 - 3 | ) = max (3, 1) = 3。</p><h4>余弦相似性</h4><p>与 L1、L2 和 Linf 不同的是，余弦相似度不是测量两个向量 x 和 y 之间的距离，而是测量它们的相对角度，即它们是否都指向大致相同的方向。相似度 s 越高，两个向量就越 "接近"。计算公式同样非常简单，如下所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt61d55341a6457ab7/6a17e0d7e9ea872b4ea9c4e2/931b6b90f0ee83e63a66496d06d6b4cef3affddd-304x72.png" alt="向量搜索中的余弦相似度公式" /><p>两个向量的余弦相似度的表示方法如下图 8 所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt50eb6399510b5380/6a17e0d83e9e45302cba139a/52092e8b5d366178e50a35f8c954ee8eaca76965-582x586.png" alt="两向量的余弦相似度" /><p>此外，由于余弦值始终处于[-1, 1]区间，-1 表示相似度相反（即两个矢量之间的夹角为 180°），0 表示相似度不相关（即夹角为 90°），1 表示相似度相同（即夹角为 0°），如下图 9 所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt785e195c75a5089e/6a17e0da1d1b8355bc93e398/fd2690a845b89b69ff202bd04192893638538aec-1600x456.png" alt="向量搜索中的余弦相似谱" /><p>
让我们再次使用相同的样本向量 x 和 y，用上述公式计算余弦相似度。首先，我们可以计算出两个向量的点积为。然后，我们将两个向量的长度（也称为幅值）相乘：最后，我们用点积除以乘积长度 10 / 11.18034 = 0.894427（即 26°角），这个值非常接近 1，因此可以认为这两个矢量非常相似。</p><h4>点积相似性</h4><p>余弦相似度的一个缺点是，它只考虑两个矢量之间的角度，而不考虑它们的大小（即长度），这意味着如果两个矢量大致指向同一方向，但其中一个矢量比另一个矢量长很多，那么这两个矢量仍然会被认为是相似的。点积相似度（也称为标量或内积）考虑了向量的角度和大小，从而改进了点积相似度，提供了更精确的相似度量。</p><p>点积相似性的计算有两个等价公式。第一种情况与我们之前在余弦相似性的分子中看到的相同：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f1c3369f8628457/6a17e0db1d1b832a1893e39c/52e2723926ab27cd96b688e805fae15f607073c8-482x104.png" alt="向量搜索中的点积相似性公式" /><p>第二个公式只是将两个矢量的长度乘以它们之间夹角的余弦：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt136dd2a749c2398a/6a17e0dc6df73108a80a0e1f/dc9b11fc67dd748d9f1f29b735f4726138cb7d39-452x70.png" alt="简化向量搜索中的点积相似性公式" /><p>下图 10 展示了点积相似性：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltb2c095e1c1948752/6a17e0dd6df731e30b0a0e23/1bda38cf82a1e1037f44b6e9657602c9efe1c0a6-558x574.png" alt="内积相似度" /><p>最后，我们取样 x 和 y 向量，使用第一个公式计算它们的点积相似度，就像之前计算余弦相似度一样，即 (1) + (2) = 10。</p><p>利用第二个公式，我们将两个矢量的长度相乘：+(4^2 + 3^2)^{1/2} = 11.18034，再乘以两个向量之间 26°夹角的余弦，就得到 11.18034(26°) = 10。</p><p>值得注意的一点是，如果首先对所有向量进行<strong>归一化处理</strong>（即长度为 1），那么点积相似度就会与余弦相似度（因为 |x| |y| = 1）完全相同，即两个向量之间夹角的余弦值。正如我们稍后将看到的，对向量进行归一化处理是一种很好的做法，这样可以使向量的大小变得无关紧要，从而使相似性只集中在角度上。它还能加快索引和查询时的距离计算速度，这在处理数十亿矢量时可能是个大问题。</p><h3>快速回顾</h3><p>哇，到目前为止，我们已经了解了很多信息，让我们稍停片刻，快速回顾一下目前的状况。我们了解到</p><ul><li><p>...语义搜索基于深度学习神经网络模型，擅长将非结构化数据转化为多维嵌入向量。</p></li><li><p>......模型的每个维度都代表了非结构化数据的一个特征或特性。</p></li><li><p>......嵌入向量是一串相似度值（每个维度一个），表示给定的非结构化数据与每个维度的相似程度。</p></li><li><p>......两个向量越 "接近"（即近邻），它们代表的语义概念就越相似。</p></li><li><p>......距离函数（L1、L2、Linf）可以测量两个向量的距离。</p></li><li><p>......相似函数（余弦和点积）使我们能够测量两个向量朝同一方向移动的程度。</p></li></ul><p></p><p>现在，我们需要深入研究的最后一个部分是矢量搜索引擎本身。当收到查询时，首先对查询进行矢量化，然后矢量搜索引擎会找到与查询矢量最近的相邻矢量。测量查询向量与数据库中所有向量之间的距离或相似性的粗暴方法可以适用于小型数据集，但随着向量数量的增加，这种方法很快就会失效。换句话说，我们如何才能索引数百万、数十亿甚至数万亿的向量，并在合理的时间内找到查询向量的近邻？这就需要我们发挥聪明才智，找出索引矢量的最佳方法，以便在不降低精度的情况下，尽可能快地找到最近的邻近矢量。</p><h3>矢量搜索算法和技术</h3><p>多年来，许多不同的研究团队投入了大量精力，开发出了非常聪明的向量搜索算法。在此，我们将简要介绍主要的几种。根据不同的使用情况，有的比有的更适合。</p><h4>线性搜索</h4><p>在前面提到将查询向量与数据库中的所有向量进行比较的粗暴方法时，我们简要地提到了线性搜索或平面索引。虽然它在小型数据集上运行良好，但随着向量和维数的增加，性能会迅速下降（复杂度为 O(n)）。</p><p>幸运的是，有一种更有效的方法被称为<strong>近似近邻</strong>（ANN），在这种方法中，嵌入向量之间的距离是预先计算出来的，相似向量的存储和组织方式可以使它们靠近在一起，例如使用聚类、树、哈希或图。这些方法被称为 "近似 "方法，因为它们通常不能保证 100% 的准确性。最终目标是尽可能快地<strong>缩小搜索范围</strong>，以便只关注最有可能包含相似向量的区域，或者<strong>降低向量的维度</strong>。</p><h4>K 维树</h4><p>K 维树（或 KD 树）是二进制搜索树的一种概括，它在 k 维空间中存储点，并通过将搜索空间连续分成较小的左树和右树来索引向量。搜索时，算法只需访问查询向量（图 11 中的红点）周围的几个树枝，就能找到最近的邻居（图 11 中的绿点）。如果请求的邻居超过 k 个，黄色区域就会扩大，直到算法找到更多邻居。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt55e01707cd9fca57/6a17e0dfbe60866a90004653/e21af2d613112279089b6fa2166359233b10019d-829x860.png" alt="向量搜索中的 KD 树算法" /><p>KD 树算法的最大优势在于，它可以让我们迅速只关注一些局部树枝，从而将大部分向量排除在外。不过，这种算法的效率会随着维数的增加而降低，因为需要访问的分支要比低维空间多得多。</p><h4>反转文件索引</h4><p>倒置文件索引（IVF）方法也是一种<strong>空间分区</strong>算法，它将彼此接近的向量分配到它们的共享中心点上。在二维空间中，使用 Voronoi 图最直观，如图 12 所示：</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7b7e4fe6deff5ef3/6a17e0e17b54f940eb8b381c/33ddaaa818ab2f2a5fc87982c82c2a34cb849e33-640x640.png" alt="二维空间中倒置文件索引的 Voronoi 表示法 " /><p>我们可以看到，上述二维空间被划分为 20 个聚类，每个聚类的中心点用黑点表示。空间中的所有嵌入向量都被分配到其中心点最接近的聚类中。在搜索时，算法首先通过找到与查询向量最接近的中心点来确定要关注的集群，然后就可以简单地将该区域归零，必要时还可以将周围的区域归零，以便找到最近的邻居。</p><p>这种算法在高维空间中使用时，也存在与 KD 树相同的问题。这就是所谓的 "维度诅咒"（curse of dimensionality），当空间体积大幅增加，以至于所有数据都显得稀疏，而要获得更精确的结果所需的数据量却呈指数级增长时，就会出现这种情况。当数据稀疏时，这些空间划分算法就很难将数据组织成群。幸运的是，还有其他算法和技术可以缓解这一问题，详情如下。</p><h4>量化</h4><p>量化是一种<strong>基于压缩的</strong>方法，通过降低嵌入向量的精度，我们可以减小数据库的总大小。这可以通过将浮点矢量值转换为整数值的<strong>标量量化 (SQ)</strong>来实现。这不仅将数据库的大小减少了 8 倍，还降低了内存消耗，并加快了搜索时向量间距离的计算速度。</p><p>另一种技术称为<strong>乘积量化（PQ），</strong>它首先将空间划分为低维子空间，然后使用聚类算法（类似于 k-means）在每个子空间中对相近的向量进行分组。</p><p>请注意，量化不同于<strong>降维</strong>，后者是减少维数，即简单地缩短向量。</p><h4>分层导航小世界（HNSW）</h4><p>如果光看名字就觉得很复杂，别担心，其实并不复杂！简而言之，"分层可导航小世界 "是一种基于多层图的算法，非常流行且高效。包括 Apache Lucene 在内的许多不同的矢量数据库都在使用它。下文图 13 显示了国家污水处理厂的概念图。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt7f4f4a8e393c8d53/6a17e0e3e8fbcefa193a1861/189ef9a8bec476e379222c454644ba4c1f952085-1400x840.png" alt="分层导航小世界（HNSW）" /><p>在顶层，我们可以看到一个由极少数向量组成的图，这些向量之间的链接最长，也就是说，这是一个相似性最小的连接向量图。我们越深入下层，发现的向量就越多，图形就越密集，越来越多的向量相互靠近。在最底层，我们可以找到所有矢量，其中最相似的矢量彼此距离最近。</p><p>搜索时，算法从顶层的任意入口点开始，找到最接近查询向量的向量（如灰色点所示）。然后，它再向下移动一层，从它留在上一层的同一个向量开始，重复同样的过程，如此逐层进行，直到到达最底层，并找到与查询向量最近的邻居。</p><h4>位置敏感散列（LSH）</h4><p>与迄今为止介绍的所有其他方法一样，对位置敏感的哈希算法试图大幅缩小搜索空间，以提高检索速度。通过这种技术，嵌入向量被转化为哈希值，同时保留了相似性信息，因此搜索空间最终变成了一个可以查询的简单哈希表，而不是一个需要遍历的图或树。基于哈希值的方法的主要优势在于，包含任意（大量）维度的向量可以映射为固定大小的哈希值，这大大加快了检索时间，同时又不会牺牲太多精度。</p><p>一般来说，散列数据，特别是嵌入向量，有许多不同的方法，但本文不会深入探讨每种方法的细节。传统的散列方法通常会对看似非常相似的数据产生截然不同的散列值。由于嵌入向量是由浮点数值组成的，因此我们取两个在向量运算中被认为非常接近的浮点数值样本（例如 0.73 和 0.74），然后通过几个常见的散列函数对它们进行运算。从下面的结果来看，普通的散列函数显然无法保留输入之间的相似性。</p><p>散列功能</p><p>0.73</p><p>0.74</p><p>MD5</p><p>1342129d04cd2924dd06cead4cf0a3ca</p><p>0aec1b15371bd979cfa66b0a50ebecc5</p><p>SHA1</p><p>49d2c3e0e44bff838e1db571a121be5ea874e8d9</p><p>a534e76482ade9d9fe4bff3035a7f31f2f363d77</p><p>SHA256</p><p>99d03fc3771fe6848d675339fc49eeb1cb8d99a12e6358173336b99a2ec530ea</p><p>5ecbc825ba5c16856edfdaf0abc5c6c41d0d8a9c508e34188239521dc7645663</p><p>传统的散列方法试图<em>尽量减少</em>相似数据之间的散列碰撞，而位置敏感散列的主要目标恰恰相反，即<em>尽量增加散列碰撞</em>，从而使相似数据以很高的概率落在同一个桶中。通过这种方法，多维空间中相距较近的嵌入向量将被哈希到属于同一个桶的固定大小的值。由于 LSH 允许这些散列向量保持其邻近性，因此这种技术在数据聚类和近邻搜索中非常有用。</p><p>所有繁重的工作都是在编制索引时进行的，此时需要计算哈希值，而在搜索时，我们只需要对查询向量进行哈希处理，以便查找包含最接近嵌入向量的桶。找到候选桶后，通常会进行第二轮，以确定与查询向量最近的相邻向量。</p><h2>结束语</h2><p>为了介绍矢量搜索，我们必须在这篇文章中介绍一些内容。在比较了词法搜索和向量搜索的区别之后，我们了解了深度学习神经网络模型是如何捕捉非结构化数据的语义，并将其意义转码为高维嵌入向量的。值得注意的是，向量搜索和词法搜索并不是相互竞争的信息检索技术，而是相辅相成的（我们将在本系列的第三部分深入探讨混合搜索）。</p><p>之后，我们介绍了向量搜索的基本构件，即距离（和相似性）函数，它允许我们测量两个向量的接近程度，并评估它们所代表概念的相似性。</p><p>最后，我们回顾了各种最流行的向量搜索算法和技术，它们可以基于树、图、簇或哈希值，其目标是快速缩小多维空间中特定区域的范围，以便找到最近的邻居，而无需像线性暴力搜索那样访问整个空间。</p><p>如果您喜欢现在阅读的内容，请务必查看本系列的其他部分：</p><ul><li><p><a href="https://www.elastic.co/search-labs/blog/vector-search-set-up-elasticsearch">第 2 部分：如何在 Elasticsearch 中设置矢量搜索</a></p></li><li><p><a href="https://www.elastic.co/search-labs/blog/hybrid-search-elasticsearch">第 3 部分：使用 Elasticsearch 进行混合搜索</a></p></li></ul>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/introduction-to-vector-search</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/introduction-to-vector-search</guid>
    <category><![CDATA[向量数据库]]></category>
    <dc:creator><![CDATA[Valentin Crettaz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blt70da374b8dc0c490/6a17e0e46864a473aab686b3/63eea8ea95b49e7241e539f65bf5aa3bb8823fff-1200x628.png" length="0" type="image/png"/>
    <pubDate>Thu, 06 Feb 2025 00:00:00 GMT</pubDate>
  </item>
  <item>
    <title><![CDATA[向量相似性测量和评分]]></title>
    <description><![CDATA[探索 Elasticsearch 中的向量相似性度量和评分，包括 L1&amp; L2 距离、余弦相似性、点积相似性和最大内积相似性。]]></description>
    <content:encoded><![CDATA[<p>当需要搜索自由文本，而 Ctrl+F / Cmd+F 又无法满足要求时，通常会想到使用词法搜索引擎。词法搜索引擎擅长分析和标记要搜索的文本，将其转化为可在搜索时匹配的术语，但在理解和理解被索引和搜索文本的真正含义方面，它们通常存在不足。</p><p>这正是矢量搜索引擎的优势所在。它们可以为同一文本编制索引，以便根据文本所代表的含义及其与其他具有相似或相关含义的概念之间的关系进行搜索。</p><p>在本博客中，我们将简要介绍矢量是如何传达文本含义的一个重要数学概念。然后，我们将深入探讨 Elasticsearch 在搜索相邻向量（即搜索含义相似的向量）时支持的不同相似性技术，以及如何对它们进行评分。</p><h2>什么是向量嵌入？</h2><p>本文不会深入探讨向量嵌入的复杂性。如果您想进一步了解这一主题，或者在继续学习之前需要一些入门知识，我们建议您查看<a href="https://www.elastic.co/cn/what-is/vector-embedding">以下指南</a>。</p><p>简而言之，矢量嵌入是通过机器学习过程获得的。深度学习神经网络），可将任何类型的非结构化输入数据（如原始文本、图像、视频、声音等）转化为承载其意义和关系的数字数据。不同类型的非结构化数据需要不同类型的机器学习模型，这些模型经过训练，可以"了解" 每种类型的数据。</p><p>每个矢量将特定数据定位为多维空间中的一个点，该位置代表了模型用来描述数据特征的一组特征。维度的数量取决于机器学习模型，但通常从几百到几千不等。例如，<a href="https://platform.openai.com/docs/guides/embeddings">OpenAI Embeddings 模型</a>拥有 1536 个维度，而<a href="https://docs.cohere.com/reference/embed">Cohere Embeddings 模型</a>则有 382 到 4096 个维度。从最新版本开始，Elasticsearch dense_vector 字段类型支持多达 4096 个维度。</p><p>向量嵌入的真正特点是，意义相似的数据点在空间中靠得很近。另一个有趣的方面是，向量嵌入也有助于捕捉数据点之间的关系。</p><h2>如何比较向量？</h2><p>我们知道，非结构化数据会被机器学习模型切割成向量嵌入，以捕捉数据在大量维度上的相似性，现在我们需要了解这些向量的匹配是如何进行的。事实证明，答案非常简单。</p><p>相互<strong>接近</strong>的向量嵌入代表<strong>语义上相似的</strong>数据片段。因此，当我们查询矢量数据库时，搜索输入（图像、文本等）首先会被转化为矢量嵌入，使用的机器学习模型与索引所有非结构化数据时使用的相同，最终目标是找到与该查询矢量<strong>最近的相邻矢量</strong>。因此，我们需要做的就是找出如何测量查询向量与数据库中索引的所有现有向量之间的"距离" 或"相似性" - 就是这么简单。</p><h2>距离、相似性和评分</h2><p>幸运的是，由于有了向量算术，测量两个向量之间的距离或相似性是一个很容易解决的问题。因此，让我们来看看 Elasticsearch 支持的最常用的距离和相似性函数。警告，前方有数学题！</p><p>在开始之前，让我们先来了解一下计分。事实上，Lucene 只允许分数为正。我们即将介绍的所有距离和相似度函数都能衡量两个向量的接近或相似程度，但这些原始数据很少适合用作分数，因为它们可能是负数。因此，需要从距离或相似度值中得出最终分数，以确保分数为正值，分数越大，排名越靠前（即向量越接近）。</p><h3>L1 距离</h3><p>两个向量和的 L1 距离（也称作曼哈顿距离）是通过将它们所有元素的成对绝对差值相加来测量的。显然，距离 越小，两个向量就越接近。L1 距离公式 (1) 非常简单，如下所示：</p><p>下图（红色）可以直观地说明 L1 距离：</p><p>计算以下两个向量的 L1 距离 \vec  </p><p><strong>重要：</strong> 值得注意的是，L1 距离函数仅支持使用<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/current/query-dsl-script-score-query.html#vector-functions-l1"> </a><code>script_score</code>DSL 查询进行<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.11/dense-vector.html#dense-vector-params"> 精确向量搜索</a> （又称暴力搜索），但不支持使用<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.11/knn-search.html#approximate-knn"><code>knn</code></a><a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/8.11/knn-search.html#approximate-knn"> 搜索选项</a> 或<a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/current/query-dsl-knn-query.html"><code>knn</code></a><a href="https://www.elastic.co/cn/guide/en/elasticsearch/reference/current/query-dsl-knn-query.html"> DSL 查询 进行 近似</a> kNN 搜索 。</p><h3>L2 距离</h3><p>两个向量和的 L2 距离（也称欧几里得距离）的测量方法是：首先求出它们所有元素的成对差值的平方和，然后取其平方根。它基本上是两点之间最短的路径。与 L1 类似，距离 越小，两个向量越接近：</p><p>下图中的 L2 距离用红色表示：</p><p>让我们重新使用与  距离相同的两个样本向量 和 距离为 。</p><p>就评分而言，两个向量之间的距离越小，它们就越接近（即越相似）。因此，为了得出分数，我们需要反转距离度量，使最小的距离产生最高的分数。使用 L2 距离计算分数的方法如下式（3）所示：</p><p>重复使用前面例子中的样本向量，它们的得分是 \frac  0.2352。相距很近的两个向量的得分将接近 1，而相距很远的两个向量的得分将趋于 0。</p><p>在总结 L1 和 L2 距离函数时，一个很好的类比方法是将 A 和 B 视为纽约市曼哈顿的两座大楼。一辆从 A 地开往 B 地的出租车必须沿着 L1 路径（街道和大道）行驶，而一只鸟可能会使用 L2 路径（直线）。</p><h3>余弦相似性</h3><p>与 L1 和 L2 不同的是，余弦相似度不是测量两个向量和 之间的距离，而是测量它们的相对角度，即它们是否都指向大致相同的方向。相似度 越高，两个矢量之间的夹角就越小，因此，"，它们之间的距离就越近，" ，它们所表达的含义就越相似，"，" 。</p><p>为了说明这一点，让我们设想两个人在野外朝不同的方向寻找。在下图中，穿蓝色衣服的人朝矢量的方向看，穿红色衣服的人朝矢量 的方向看。他们的视线越是朝向同一个方向（即他们的矢量越接近），蓝色和红色区域所代表的视野就越是重叠。它们的视场重叠程度就是它们的余弦相似度。但是，请注意，人 B 比人 A 看得更远（即矢量更长）。人 B 可能在看地平线上远处的一座山，而人 A 可能在看附近的一棵树。对于余弦相似度来说，这没有任何作用，因为它只与角度有关。</p><p>现在我们来计算余弦相似度。公式 (4) 非常简单，分子是两个矢量的点乘，分母是两个矢量的大小乘积（即长度）：</p><p>和之间的余弦相似度如下图所示，是它们之间夹角的度量（红色）：</p><p>让我们绕个弯，具体解释一下这些余弦相似度值的含义。从下面描述余弦函数的图片中可以看出，数值总是在区间内摆动。</p><img src="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/bltc0e4eb98ebb64cf3/6a17da287b54f983818b3783/e31145284b8c27d0bd9e3d2831f811388134fd83-1188x272.png" alt="余函数" /><p>请记住，要使两个矢量相似，它们之间的夹角必须尽可能锐利，最好接近，即完全相似度为。换句话说，当矢量...</p><ol><li><p>......彼此<strong>接近</strong>，其角度的余弦接近（即接近）。</p></li></ol><ol><li><p>......<strong>无关</strong>，它们的夹角余弦接近（即接近）。</p></li></ol><ol><li><p>......<strong>相反</strong>，它们的夹角余弦接近（即接近）。</p></li></ol><p>既然我们已经知道如何计算两个向量之间的余弦相似度，并对如何解释所得值有了很好的概念，那么我们就可以重新使用相同的样本向量和，并使用我们之前看到的公式 (4) 计算它们的余弦相似度。</p><p>我们得到的余弦相似度为，更接近于而不是，这意味着这两个矢量<strong>有些相似</strong>，即不是完全相似，但也不是完全无关，当然也没有相反的含义。</p><p>为了从任何余弦相似度值中得出正分数，我们需要使用下面的公式 (5)，该公式将在区间内摆动的余弦相似度值转换为区间内的分数：</p><p>因此，样本向量和的得分为\frac  0.8253。</p><h3>点积相似性</h3><p>余弦相似度的一个缺点是，它只考虑两个矢量之间的角度，而不考虑它们的大小，这意味着如果两个矢量大致指向同一个方向，但其中一个矢量比另一个矢量长很多，那么这两个矢量仍然会被认为是相似的。点积相似性（也称为标量或内积相似性）考虑了向量的角度和大小，从而改进了点积相似性，提供了更精确的相似性度量。为了使向量的大小变得无关紧要，点积相似性要求首先对向量进行归一化处理，因此我们最终只比较单位长度为 1 的向量。</p><p>让我们用同样的两个人来再次说明这个问题，但这次我们把他们放在一个圆形房间的中间，这样他们的视线范围就完全相同了（即房间的半径）。与余弦相似度类似，它们转向的方向越一致（即它们的矢量越接近），它们的视场重叠就越多。然而，与余弦相似性相反的是，两个矢量的长度相同，两个区域的表面相同，这意味着两个人看的是位于相同距离的完全相同的图片。这两个区域的重叠程度表示它们的点积相似度。</p><p>在介绍点积相似性公式之前，让我们先快速了解一下如何对向量进行归一化处理。这非常简单，只需两个微不足道的步骤即可完成：</p><ol><li><p>计算向量的大小</p></li><li><p>将每个分量除以 1 中得到的大小。</p></li></ol><p>举例来说，让我们把向量 \vec我们可以计算出它的大小 \Vert\Vert ，就像我们之前在回顾余弦相似性时看到的那样，即 \sqrt 。然后，将矢量的每个分量除以其幅度，我们就得到了下面的归一化矢量 ：</p><p>对第二个向量 \vec  ：</p><p>为了得出点积相似度公式，我们可以使用公式（4）计算归一化向量和之间的余弦相似度，如下图所示：</p><p>由于两个归一化向量的大小现在都是，所以点积相似公式 (6) 就变成了......你猜对了，两个归一化向量的点积：</p><p>在下图中，我们显示了归一化向量和，我们可以用一个向量在另一个向量上的投影（红色）来说明它们的点积相似性。</p><p>使用新公式 (6)，我们可以计算出两个归一化向量的点积相似度，不出意外，这将得到与余弦相似度完全相同的相似度值：</p><p>在利用点积相似性时，得分的计算方法会因向量包含浮点值还是字节值而有所不同。在前一种情况下，得分的计算方法与余弦相似性相同，使用下面的公式（7）：</p><p>但是，当向量由字节值组成时，计算得分的方法就有些不同了，如下式（8）所示，其中是向量的维数：</p><p>此外，为了获得准确的分数，还有一个限制条件，即包括查询向量在内的所有向量必须具有相同的长度，但不一定是 1。</p><h3>最大内积相似度</h3><p>自 8.11 版起，新的相似度函数比点积相似度的限制更少，因为向量不需要进行归一化处理。<a href="https://www.elastic.co/cn/search-labs/blog/lucene-bringing-maximum-inner-product-to-lucene">下面的文章</a>将详细解释其中的主要原因，但简单来说，某些数据集不太适合对其向量进行归一化处理（例如<a href="https://www.elastic.co/cn/search-labs/blog/elasticsearch-cohere-embeddings-support">Cohere 内嵌</a>），这样做可能会导致相关性问题。</p><p>计算最大内积相似度的公式与点积公式 (6) 完全相同。改变的是计算得分的方式，即使用一个片断函数对最大内积相似度进行缩放，该函数的计算公式取决于相似度是正还是负，如下式（9）所示：</p><p>这个分段函数的作用是，在区间内对所有负的最大内积相似度值进行缩放，在区间内对所有正值进行缩放。</p><h2>总之</h2><p>从数学的角度看，这真是一次不寻常的旅程，但这里有一些启示，你可能会觉得有用。</p><p>您可以使用哪种相似度函数，最终取决于您的向量嵌入是否经过归一化处理。如果您的矢量已经归一化，或者您的数据集与矢量归一化无关（即相关性不会受到影响），那么您可以继续对矢量进行归一化，并使用点积相似性，因为它的计算速度比余弦相似性快得多，因为不需要计算每个矢量的长度。在比较数百万个向量时，这些计算量会增加很多。</p><p>如果您的向量没有标准化，那么您有两种选择：</p><ol><li><p>如果无法对向量进行归一化处理，则使用余弦相似度</p></li><li><p>如果您希望矢量的大小对评分有帮助，可以使用新的最大内积相似性，因为它们确实有意义（例如，Cohere 嵌入）。</p></li></ol><p>至此，计算向量嵌入之间的距离或相似性，以及如何得出它们的分数，对你来说应该已经很清楚了。希望这篇文章对您有所帮助。</p>]]></content:encoded>
    <link>https://www.elastic.co/search-labs/blog/vector-similarity-measures-and-scoring</link>
    <guid isPermaLink="true">https://www.elastic.co/search-labs/blog/vector-similarity-measures-and-scoring</guid>
    <category><![CDATA[向量数据库]]></category>
    <dc:creator><![CDATA[Valentin Crettaz]]></dc:creator>
    <enclosure url="https://static-www.elastic.co/v3/assets/bltefdd0b53724fa2ce/blte5a3e9d39849d3ed/6a17da31a2929960a3d02b3f/4d9e89678798b9de68357b5cc06dbbd8b9c6e5e8-1440x823.webp" length="0" type="image/webp"/>
    <pubDate>Mon, 13 May 2024 00:00:00 GMT</pubDate>
  </item>
  </channel>
</rss>