当前位置: 首页 > news >正文

文献分享: DESSERT基于LSH的多向量检索(Part1——原理与实现)

原论文

1.   \textbf{1. } 1. 背景与导论

1.1.   \textbf{1.1. } 1.1. 向量集搜索是什么

1️⃣向量集搜索的过程

  1. 输入:查询向量集 Q = { q 1 , . . . , q m q } ∈ R m q × d Q\text{=}\{q_1,...,q_{m_q}\}\text{∈}\mathbb{R}^{m_q\text{×}d} Q={q1,...,qmq}Rmq×d,向量集的集合 D = { S 1 , . . . , S N } D\text{=}\{S_1,...,S_N\} D={S1,...,SN},其中 S i = { x i 1 , . . . , x i m i } ∈ R m i × d S_i\text{=}\{x_{i1},...,x_{im_i}\}\text{∈}\mathbb{R}^{m_i\text{×}d} Si={xi1,...,ximi}Rmi×d
  2. 输出:用 F ( Q , S i ) F(Q,S_i) F(Q,Si)衡量 Q Q Q S i S_i Si相似度,要求以 1 – δ 1–\delta 1–δ的概率返回与 Q Q Q相似度最高的 S i S_i Si,即 S ∗ = argmax ⁡ i ∈ { 1 , … , N } F ( Q , S i ) S^*\text{=}\mathop{\operatorname{argmax}}\limits_{{i\in\{1,\ldots{},N\}}}F\left({Q,{S}_{i}}\right) S=i{1,,N}argmaxF(Q,Si)

2️⃣对相似度 F ( Q , S i ) F(Q,S_i) F(Q,Si)的定义

  1. 子相似度:衡量每个 q r ∈ Q q_r\text{∈}Q qrQ x i j ∈ S i x_{ij}\text{∈}S_i xijSi时间的相似度
    👉举个例子,对于查询Q={q1,q2,q3}考虑下面向量集
      S1 = {x11, x12, x13, x14}
      S2 = {x21, x22, x23, x24, x25}
      S3 = {x31, x32, x33}
    👉让Q和S1进行内部聚合,先要算出全部的相似度(比如内积)
      Sim(q1,x11) Sim(q1,x12) Sim(q1,x13) Sim(q1,x14)
      Sim(q2,x11) Sim(q2,x12) Sim(q2,x13) Sim(q2,x14)
      Sim(q3,x11) Sim(q3,x12) Sim(q3,x13) Sim(q3,x14)
    
  2. 内部聚合 σ \sigma σ:让每个 q r ∈ Q q_r\text{∈}Q qrQ得到一共聚合后的相似度,类似于 ColBERT \text{ColBERT} ColBERT MaxSim \text{MaxSim} MaxSim
    👉对于每个qi,应用内部聚合函数σ
      Inner(q1,S) = σ{Sim(q1,x11),Sim(q1,x12),Sim(q1,x13),Sim(q1,x14)}
      Inner(q2,S) = σ{Sim(q2,x11),Sim(q2,x12),Sim(q2,x13),Sim(q2,x14)}
      Inner(q3,S) = σ{Sim(q3,x11),Sim(q3,x12),Sim(q3,x13),Sim(q3,x14)}
    👉在ColBERT中这个σ就是所谓的MaxSim
      Inner(q1,S) = Max{Sim(q1,x11),Sim(q1,x12),Sim(q1,x13),Sim(q1,x14)}
      Inner(q2,S) = Max{Sim(q2,x11),Sim(q2,x12),Sim(q2,x13),Sim(q2,x14)}
      Inner(q3,S) = Max{Sim(q3,x11),Sim(q3,x12),Sim(q3,x13),Sim(q3,x14)}
    
  3. 外部聚合 A A A:将每个 q r ∈ Q q_r\text{∈}Q qrQ内部聚合的结果进行处理,得到最后评分 F ( Q , S ) F(Q,S) F(Q,S)
    👉对每个内部聚合应用内部聚合函数A
      F(Q,S1) = A{Inner(q1,S),Inner(q2,S),Inner(q3,S)}
    👉在ColBERT中这个A就是逐个相加
      F(Q,S1) = Inner(q1,S) + Inner(q2,S) + Inner(q3,S)
    

1.2.   \textbf{1.2. } 1.2. 为什么最邻居搜索不够

1️⃣向量集搜索:基于单向量最邻近的方案

  1. 输入:给定查询 Q = { q 1 , q 2 , . . . , q m q } Q\text{=}\{q_1,q_2,...,q_{m_q}\} Q={q1,q2,...,qmq}和向量集的集合 D = { S 1 , S 2 , . . . , S N } D\text{=}\{S_1,S_2,...,S_N\} D={S1,S2,...,SN},其中 S i = { x i 1 , x i 2 , . . . , x i m i } S_i\text{=}\{x_{i1},x_{i2},...,x_{im_i}\} Si={xi1,xi2,...,ximi}
  2. 检索:让每个 q r ∈ Q q_r\text{∈}Q qrQ在所有 S 1 ∪ S 2 ∪ … ∪ S N S_1\text{∪}S_2\text{∪}\ldots\text{∪}S_N S1S2SN中执行 MIPS \text{MIPS} MIPS(最大内积搜索),得到其 Top- K \text{Top-}K Top-K的向量
  3. 候选:一共得到了 m q × K m_q\text{×}K mq×K个向量,分别确定每个向量所属的 S i S_i Si,合并得到候选集 D ′ = { S ( 1 ) , S ( 2 ) , . . . } D^\prime{\text{=}}\left\{S_{(1)},S_{(2)},...\right\} D={S(1),S(2),...}
  4. 重排:计算 Q Q Q与候选集中向量集的精确距离 F ( Q , S ( i ) ) F\left(Q,S_{(i)}\right) F(Q,S(i)),以对候选向量集进行重排

2️⃣存在的问题

  1. 检索效果上:假设某个 q r ∈ Q q_r\text{∈}Q qrQ的最邻近是 x i j ∈ S i x_{ij}\text{∈}S_i xijSi,二者各自的向量邻近和 F ( Q , S i ) F(Q,S_i) F(Q,Si)会很大没有半毛钱关系
  2. 检索成本上: S 1 ∪ S 2 ∪ … ∪ S N S_1\text{∪}S_2\text{∪}\ldots\text{∪}S_N S1S2SN中但向量规模是巨大的,成本会爆掉

1.3.   \textbf{1.3. } 1.3. 关于 LSH \textbf{LSH} LSH

1️⃣几种不同的 LSH \text{LSH} LSH回顾

  1. 基于余弦相似度的 LSH \text{LSH} LSH
    • 原理:一般用随机超平面对分割空间,一个子空间就是一个桶,两向量内积越大越可能落入同一桶
    • 例如: Muvera \text{Muvera} Muvera中用到的 SimHash \text{SimHash} SimHash
  2. 基于欧几里得距离的 LSH \text{LSH} LSH
    • 原理:一般将所有向量投影到随机方向的直线上,直线上每 w w w步长就是一个桶,两向量欧式距离近者更可能落入同一桶
    • 例如:经典的如 E2LSH \text{E2LSH} E2LSH,其基于动态分桶的改进 QALSH \text{QALSH} QALSH
  3. 基于 Jaccard \text{Jaccard} Jaccard相似度的 LSH \text{LSH} LSH
    • Jaccard \text{Jaccard} Jaccard相似度:两个集合的距离(交集大小 / / /并集大小)作为相似度
    • MinHash \text{MinHash} MinHash原理:
      • 集合的特征:用 k k k个不同哈希函数对集合中所有元素求哈希值,取每个哈希函数的最小哈希值,即为集合的 k k k个特征
      • 集合相似度:两个集合的 Jaccard \text{Jaccard} Jaccard相似度,理论上就是两个集合的重合特征数 / k /k /k

2️⃣本文中对于 LSH \text{LSH} LSH的假设

  1. 假设:存在一个哈希家族 H ⊂ ( R d → Z ) \mathcal{H}\text{⊂}\left({{\mathbb{R}}^{d} \text{→}\mathbb{Z}}\right) H(RdZ)及其分桶哈希函数 ψ \psi ψ,使得 Pr [ ψ ( x ) = ψ ( y ) ] =Sim ( x , y ) \text{Pr}[\psi{(x)}\text{=}\psi{(y)}]\text{=}\text{Sim}(x,y) Pr[ψ(x)=ψ(y)]=Sim(x,y)
  2. 含义:两个向量相似度越高,被分到同一桶内的概率就更高

2.   \textbf{2. } 2. 算法及理论保证

2.1.   \textbf{2.1. } 2.1. 算法的朴素流程

1️⃣索引构建

  1. 输入:若干向量集,如 D = { S 1 , S 2 , . . . , S N } D\text{=}\{S_1,S_2,...,S_N\} D={S1,S2,...,SN}
  2. 构建:对于每个 S i = { x i 1 , x i 2 , . . . , x i m i } S_i\text{=}\{x_{i1},x_{i2},...,x_{im_i}\} Si={xi1,xi2,...,ximi}都执行索引构建操作
    • 索引分配:为 S i S_i Si中每个元素分配一个唯一索引,例如 x i j x_{ij} xij的索引可以为 j j j
    • 哈希分桶:用 L L L LSH \text{LSH} LSH函数 ψ 1 , ψ 2 , . . . , ψ L \psi_1,\psi_2,...,\psi_L ψ1,ψ2,...,ψL S i S_i Si中所有元素进行 L L L次分桶
    • 索引存储:利用 D [ i ] t , h \mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h} D[i]t,h数组结构,对应哈希函数 ψ t \psi_t ψt下哈希值为 h h h的桶,存储存储了 S i S_i Si中落入该桶的所有向量的索引

2️⃣查询阶段

  1. 输入:查询向量集 Q = { q 1 , q 2 , . . . , q m q } Q\text{=}\{q_1,q_2,...,q_{m_q}\} Q={q1,q2,...,qmq},以及上一步构建的 DESSERT \text{DESSERT} DESSERT索引
  2. 编码:照样用那 L L L LSH \text{LSH} LSH函数 ψ 1 , ψ 2 , . . . , ψ L \psi_1,\psi_2,...,\psi_L ψ1,ψ2,...,ψL,对 Q Q Q中所有元素进行 L L L次分桶
  3. 评分:通过检查 q r ∈ Q q_r\text{∈}Q qrQ x i j ∈ S i x_{ij}\text{∈}S_i xijSi的碰撞次数 Count ( q r , x i j ) \text{Count}(q_r,x_{ij}) Count(qr,xij),得到二者相似度的一个近似 Sim ^ ( q r , x i j ) = Count ( q r , x i j ) L \hat{\text{Sim}}(q_r,x_{ij})\text{=}\cfrac{\text{Count}(q_r,x_{ij})}{L} Sim^(qr,xij)=LCount(qr,xij)
    • 原理:为何 Count ( q r , x i j ) L \cfrac{\text{Count}(q_r,x_{ij})}{L} LCount(qr,xij)可作为近似评分
      • q r ∈ Q q_r\text{∈}Q qrQ x i j ∈ S i x_{ij}\text{∈}S_i xijSi各自进行 L L L次分桶后碰撞 Count ( q r , x i j ) \text{Count}(q_r,x_{ij}) Count(qr,xij)次,故估计碰撞率为 Count ( q r , x i j ) L \cfrac{\text{Count}(q_r,x_{ij})}{L} LCount(qr,xij)
      • 鉴于 Pr [ ψ ( x ) = ψ ( y ) ] =Sim ( x , y ) \text{Pr}[\psi{(x)}\text{=}\psi{(y)}]\text{=}\text{Sim}(x,y) Pr[ψ(x)=ψ(y)]=Sim(x,y)的假设,所以碰撞率就是相似度
    • 实现:基于 D [ i ] t , h \mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h} D[i]t,h数组结构(具体优化则见 TinyTable \text{TinyTable} TinyTable)
      • 对于 ∀ q r ∈ Q \forall{}q_{r}\text{∈}Q qrQ用哈希函数 ψ t \psi_t ψt得出其哈希值 h h h,按照 t , h t,h t,h索引直接在找到桶 D [ i ] t , h \mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h} D[i]t,h,如果 x i j x_{ij} xij索引也在这儿就算碰撞一次
      • ψ 1 , ψ 2 , . . . , ψ L \psi_1,\psi_2,...,\psi_L ψ1,ψ2,...,ψL都进行如上操作,得到最终碰撞次数 Count ( q r , x i j ) \text{Count}(q_r,x_{ij}) Count(qr,xij),碰撞率(相似度)为 Count ( q r , x i j ) L \cfrac{\text{Count}(q_r,x_{ij})}{L} LCount(qr,xij)
  4. 聚合:基于相似度 Sim ^ ( q r , x i j ) \hat{\text{Sim}}(q_r,x_{ij}) Sim^(qr,xij),得到最终的相似度估值 F ^ ( Q , S i ) \hat{F}(Q,S_i) F^(Q,Si)
    • 原始输入:由以上 LSH \text{LSH} LSH得到的,每个 q r ∈ Q q_r\text{∈}Q qrQ的近似相似度集 s ^ ( q r , S i ) = { Sim ^ ( q r , x i 1 ) , Sim ^ ( q r , x i 2 ) , . . . , Sim ^ ( q r , x i m i ) } \hat{\mathbf{s}}(q_{r},S_i)\text{=}\{\hat{\text{Sim}}(q_{r},x_{i1}),\hat{\text{Sim}}(q_{r},x_{i2}),...,\hat{\text{Sim}}(q_{r},x_{im_i})\} s^(qr,Si)={Sim^(qr,xi1),Sim^(qr,xi2),...,Sim^(qr,ximi)}
    • 内部聚合: σ ( s ^ ( q r , S i ) ) = σ { Sim ^ ( q r , x i 1 ) , Sim ^ ( q r , x i 2 ) , . . . , Sim ^ ( q r , x i m i ) } \sigma(\hat{\mathbf{s}}(q_{r},S_i))\text{=}\sigma\{\hat{\text{Sim}}(q_{r},x_{i1}),\hat{\text{Sim}}(q_{r},x_{i2}),...,\hat{\text{Sim}}(q_{r},x_{im_i})\} σ(s^(qr,Si))=σ{Sim^(qr,xi1),Sim^(qr,xi2),...,Sim^(qr,ximi)},当 σ \sigma σ max \text{max} max时左式等于 MaxSim ^ ( q r , S i ) \hat{\text{MaxSim}}(q_r,S_i) MaxSim^(qr,Si)
    • 外部聚合: A ( Q , S i ) = A { σ ( s ^ ( q 1 , S i ) ) , σ ( s ^ ( q 2 , S i ) ) , . . . , σ ( s ^ ( q m q , S i ) ) } A(Q,S_i)\text{=}A\{\sigma(\hat{\mathbf{s}}(q_{1},S_i)),\sigma(\hat{\mathbf{s}}(q_{2},S_i)),...,\sigma(\hat{\mathbf{s}}(q_{m_q},S_i))\} A(Q,Si)=A{σ(s^(q1,Si)),σ(s^(q2,Si)),...,σ(s^(qmq,Si))} A A A可以是将所有 q r ∈ Q q_r\text{∈}Q qrQ内部聚合结果相加

2.2.   \textbf{2.2. } 2.2. 算法的理论保证

2.2.1.   \textbf{2.2.1. } 2.2.1. 对于内部聚合过程

1️⃣乘性约束函数及其引理

  1. 定义 4.1 \text{4.1} 4.1 ( α , β ) - (α, β)\text{-} (α,β)-乘性极值约束函数
    • 条件:给定参数 α , β \alpha,\beta α,β满足 0 < β ≤ 1 ≤ α 0\text{<}β\text{≤}1\text{≤}α 0<β1α,给定向量 x x x并用 max ⁡ ( x ) \max{(x)} max(x)表示向量 x x x中最大元素值
    • 定义:函数 σ ( x ) : R m → R σ(x)\text{:}ℝ^m\text{→}ℝ σ(x):RmR U U U上是 ( α , β ) - (α,β)\text{-} (α,β)-极大的,等价于 ∀ x ∈ U \forall{x}\text{∈}U xU β max ⁡ ( x ) ≤ σ ( x ) ≤ α max ⁡ ( x ) \beta\max{(x)}\text{≤}σ(x)\text{≤}\alpha\max{(x)} βmax(x)σ(x)αmax(x)
    • 例如:当内部聚合 σ ( x ) σ(x) σ(x)就是 ColBERT \text{ColBERT} ColBERT MaxSim \text{MaxSim} MaxSim函数时,就有 α = β = 1 α\text{=}β\text{=}1 α=β=1 ( 1 , 1 ) - (1,1)\text{-} (1,1)-极大
  2. 引理 4.1.1 \text{4.1.1} 4.1.1:平均极值下界衰减引理
    • 条件: φ ( x ) : R → R \varphi(x)\text{:}ℝ\text{→}ℝ φ(x):RR在区间 I I I上是 ( α , β ) - (α,β)\text{-} (α,β)-极大的, x x x为标量是 max ⁡ ( x ) \max{(x)} max(x)退化为 x x x本身,即 β x ≤ φ ( x ) ≤ α x \beta{x}\text{≤}\varphi(x)\text{≤}\alpha{x} βxφ(x)αx
    • 结论: σ ( x = { x 1 , x 2 , . . . , x m } ) = 1 m ∑ i = 1 m φ ( x i ) \sigma(\mathbf{x}\text{=}\{x_1,x_2,...,x_m\})\text{=}\displaystyle{}\frac{1}{m}\sum_{i=1}^m\varphi(x_i) σ(x={x1,x2,...,xm})=m1i=1mφ(xi) U = I m U\text{=}I^m U=Im上是 ( α , β m ) - \left(\alpha,\cfrac{\beta}{m}\right)\text{-} (α,mβ)-极大的
    • 示例:满足该引理的实数域函数
      φ ( x ) \boldsymbol{\varphi{(x)}} φ(x) β \boldsymbol{\beta} β α \boldsymbol{\alpha} α
      x x x 1 1 1 1 1 1
      e x – 1 e^x–1 ex–1 1 1 1 e – 1 e–1 e–1
      Sigmid ( x ) = e x 1 + e x – 1 2 \text{Sigmid}(x)\text{=}\cfrac{e^x}{1\text{+}e^x}–\cfrac{1}{2} Sigmid(x)=1+exex21 0.23 0.23 0.23 0.25 0.25 0.25

2️⃣引理 4.1.2/4.1.3 \text{4.1.2/4.1.3} 4.1.2/4.1.3

  1. 输入:对查询向量集 ∀ q r ∈ Q = { q 1 , q 2 , . . . , q m q } \forall{}q_{r}\text{∈}Q\text{=}\{q_1,q_2,...,q_{m_q}\} qrQ={q1,q2,...,qmq}和向量集 S i = { x i 1 , x i 2 , . . . , x i m i } S_i\text{=}\{x_{i1},x_{i2},...,x_{im_i}\} Si={xi1,xi2,...,ximi},考虑真实 / / /(基于碰撞的)近似相似度
    • 每个 q r ∈ Q q_r\text{∈}Q qrQ的真实相似度集: s ( q r , S i ) = { Sim ( q r , x i 1 ) , Sim ( q r , x i 2 ) , . . . , Sim ( q r , x i m i ) } {\mathbf{s}}(q_{r},S_i)\text{=}\{{\text{Sim}}(q_{r},x_{i1}),{\text{Sim}}(q_{r},x_{i2}),...,{\text{Sim}}(q_{r},x_{im_i})\} s(qr,Si)={Sim(qr,xi1),Sim(qr,xi2),...,Sim(qr,ximi)}
    • 每个 q r ∈ Q q_r\text{∈}Q qrQ的近似相似度集: s ^ ( q r , S i ) = { Sim ^ ( q r , x i 1 ) , Sim ^ ( q r , x i 2 ) , . . . , Sim ^ ( q r , x i m i ) } \hat{\mathbf{s}}(q_{r},S_i)\text{=}\{\hat{\text{Sim}}(q_{r},x_{i1}),\hat{\text{Sim}}(q_{r},x_{i2}),...,\hat{\text{Sim}}(q_{r},x_{im_i})\} s^(qr,Si)={Sim^(qr,xi1),Sim^(qr,xi2),...,Sim^(qr,ximi)}
  2. 符号:对真实相似度集 / / /近似相似度集,采取不同聚合方式
    • 真实集:用最值聚合 max ⁡ ( s ( q r , S i ) ) = max ⁡ { Sim ( q r , x i 1 ) , . . . , Sim ( q r , x i m i ) } \max\left(\mathbf{s}(q_{r},S_i)\right)\text{=}\max\{\text{Sim}(q_{r},x_{i1}),...,\text{Sim}(q_{r},x_{im_i})\} max(s(qr,Si))=max{Sim(qr,xi1),...,Sim(qr,ximi)},记作 s max ⁡ s_{\max} smax MaxSim ( q r , S i ) \text{MaxSim}(q_{r},S_i) MaxSim(qr,Si)
    • 近似集:用 σ \sigma σ聚合 σ ( s ^ ( q r , S i ) ) = σ { Sim ^ ( q r , x i 1 ) , . . . , Sim ^ ( q r , x i m i ) } \sigma(\hat{\mathbf{s}}(q_{r},S_i))\text{=}\sigma\{\hat{\text{Sim}}(q_{r},x_{i1}),...,\hat{\text{Sim}}(q_{r},x_{im_i})\} σ(s^(qr,Si))=σ{Sim^(qr,xi1),...,Sim^(qr,ximi)}其中 σ \sigma σ ( α , β ) - (α,β)\text{-} (α,β)-极大,简记作 σ ( s ^ ) \sigma(\hat{\mathbf{s}}) σ(s^)
  3. γ \gamma γ函数:设定 γ = ( α ( 1 – s max ⁡ ) α – τ ) ( s max ⁡ ( α – τ ) τ ( 1 – s max ⁡ ) ) τ / α \displaystyle{}\gamma=\left(\frac{\alpha\left({1–{s_{\max}}}\right)}{\alpha–\tau}\right){\left(\frac{{s_{\max}}\left({\alpha–\tau}\right)}{\tau\left({1–{s_{\max}}}\right)}\right)}^{{\tau}/{\alpha}} γ=(ατα(1–smax))(τ(1–smax)smax(ατ))τ/α
    image-20250401153048807
    • 单调:处于 ( s max ⁡ , 1 ) \left({{s_{\max}},1}\right) (smax,1)区间中,并且随 s max ⁡ s_{\max} smax递增随 τ \tau τ递减
    • 极限: γ \gamma γ存在单侧极限, τ \tau τ从高处接近 α s max ⁡ \alpha{s_{\max}} αsmax lim ⁡ τ ↘ α s max ⁡ γ = 1 \mathop{\lim}\limits_{{\tau\searrow\alpha{s}_{\max}}}\gamma\text{=}1 ταsmaxlimγ=1 τ \tau τ从低处接近 α \alpha α lim ⁡ τ ↗ α γ = s max ⁡ \mathop{\lim}\limits_{{\tau\nearrow\alpha}}\gamma\text{=}{s}_{\max} ταlimγ=smax
  4. 结论:给定一个阈值 τ ∈ [ α s max ⁡ , α ] \tau\text{∈}[\alpha{s_{\max}},\alpha] τ[αsmax,α]并记录差值为 Δ = τ – α s max ⁡ \Delta{=}\tau–\alpha{}s_{\max} Δ=ταsmax,让当内部聚合 σ \sigma σ ( α , β ) - (α,β)\text{-} (α,β)-极大的,则有如下两个引理
    • 引理 4.1.2 \text{4.1.2} 4.1.2(指数上界衰减引理): Pr ⁡ [ σ ( s ^ ) ≥ α s max ⁡ + Δ ] ≤ m γ L \Pr\left\lbrack{\sigma\left(\widehat{\mathbf{s}}\right)\text{≥}\alpha{s}_{\max}\text{+}\Delta}\right\rbrack\text{≤}m{\gamma}^{L} Pr[σ(s )αsmax+Δ]mγL,对近似相似度聚合后,大概率不超过理论上界
    • 引理 4.1.3 \text{4.1.3} 4.1.3(高斯下界集中引理): Pr ⁡ [ σ ( s ^ ) ≤ β s max ⁡ – Δ ] ≤ 2 e – 2 L Δ 2 / β 2 \Pr\left\lbrack{\sigma\left(\widehat{\mathbf{s}}\right)\text{≤}\beta{s}_{\max}\text{–}\Delta}\right\rbrack\text{≤}2{e}^{–{2L}{\Delta}^{2}/{\beta}^{2}} Pr[σ(s )βsmaxΔ]2e2LΔ2/β2,对近似相似度聚合后,大概率不低于理论下界

2.2.2.   \textbf{2.2.2. } 2.2.2. 外部聚合及运行时间

1️⃣一些基本的设置

  1. 近似集的聚合:与之前一样 σ ( s ^ ( q r , S i ) ) = σ { Sim ^ ( q r , x i 1 ) , . . . , Sim ^ ( q r , x i m i ) } \sigma(\hat{\mathbf{s}}(q_{r},S_i))\text{=}\sigma\{\hat{\text{Sim}}(q_{r},x_{i1}),...,\hat{\text{Sim}}(q_{r},x_{im_i})\} σ(s^(qr,Si))=σ{Sim^(qr,xi1),...,Sim^(qr,ximi)},但为区分不同 q r q_r qr就不做简写了
  2. 外部聚合评分:让外部聚合 A A A为带 w r w_r wr权值的加权平均,由此 F ( Q , S i ) = 1 m q ∑ r = 1 m q w r σ ( s ^ ( q r , S i ) ) F\left({Q,S_i}\right)\text{=}\displaystyle{}\frac{1}{m_q}\sum_{r=1}^{m_q}w_r\sigma\left({\widehat{\mathbf{s}}\left({{q}_{r},S_i}\right)}\right) F(Q,Si)=mq1r=1mqwrσ(s (qr,Si))
  3. 最邻近向量集:给定 Q = { q 1 , q 2 , . . . , q m q } Q\text{=}\{q_1,q_2,...,q_{m_q}\} Q={q1,q2,...,qmq} D = { S 1 , S 2 , . . . , S N } D\text{=}\{S_1,S_2,...,S_N\} D={S1,S2,...,SN},设定 S ∗ ∈ D S^*\text{∈}D SD是使得 F ( Q , S i ) F\left({Q,S_i}\right) F(Q,Si)最大的向量集
  4. 分析时的假设:假定所有向量集的向量数都相同,即统一将 m i m_i mi认定为一个常数 m m m,当然也可用 ( m i ) max ⁡ (m_i)_{\max} (mi)max替代所有 m i m_i mi

2️⃣定理 4.2 \text{4.2} 4.2:概率对数近邻保证定理

  1. 设定参数:对于 0 < β ≤ 1 ≤ α 0\text{<}β\text{≤}1\text{≤}α 0<β1α
    • B ∗ = β m q ∑ r = 1 m q w r max ⁡ ( s ( q r , S ∗ ) ) = β m q ∑ r = 1 m q w r MaxSim ( q r , S ∗ ) B^*\text{=}\displaystyle{}\frac{\beta}{m_q}\sum_{r=1}^{m_q}w_r\max{(\mathbf{s}(q_{r},S^*))}\text{=}\frac{\beta}{m_q}\sum_{r=1}^{m_q}w_r\text{MaxSim}(q_r,S^*) B=mqβr=1mqwrmax(s(qr,S))=mqβr=1mqwrMaxSim(qr,S) B ∗ B^* B其实是 F ( Q , S ∗ ) F(Q,S^*) F(Q,S)的一个下界
    • B i = α m q ∑ r = 1 m q w r max ⁡ ( s ( q r , S i ) ) = α m q ∑ r = 1 m q w r MaxSim ( q r , S i ) B_i\text{=}\displaystyle{}\frac{\alpha}{m_q}\sum_{r=1}^{m_q}w_r\max{(\mathbf{s}(q_{r},S_i))}\text{=}\frac{\alpha}{m_q}\sum_{r=1}^{m_q}w_r\text{MaxSim}(q_r,S_i) Bi=mqαr=1mqwrmax(s(qr,Si))=mqαr=1mqwrMaxSim(qr,Si) B i B_i Bi其实是 F ( Q , S i ) F(Q,S_i) F(Q,Si)的一个上界
    • B ′ B^\prime B为在 S i ≠ S ∗ S_i{≠}S^* Si=S条件下, B i B_i Bi能取得的最大值
  2. 结论:只要我们选择足够大的哈希表数量,算法就能以高概率返回正确最邻近向量集
    • 条件:当 Δ = B ∗ – B ′ 3 > 0 \Delta{\text{=}}\cfrac{B^*–B^\prime}{3}\text{>}0 Δ=3BB0时,,设定 L = O ( log ⁡ ( N m q m δ ) ) L\text{=}\displaystyle{}O\left({\log\left(\frac{N{m}_{q}m}{\delta}\right)}\right) L=O(log(δNmqm))
    • 结论: DESSERT \text{DESSERT} DESSERT算法结构能以 1 – δ 1–\delta 1–δ的概率,返回与 Q Q Q相似度最高的 S i S_i Si,即 S ∗ = argmax ⁡ i ∈ { 1 , … N } F ( Q , S i ) S^*\text{=}\mathop{\operatorname{argmax}}\limits_{{i \in \{ 1,\ldots N\} }}F\left( {Q,{S}_{i}}\right) S=i{1,N}argmaxF(Q,Si)

3️⃣运行时间的分析

  1. 一些前提:假设每个哈希函数运行的时间为 O ( d ) O(d) O(d),集合 D [ i ] t , h \mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h} D[i]t,h的元素数存在常数阈值 ∣ D [ i ] t , h ∣ ≤ T |\mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h}|\text{≤}T D[i]t,hT
  2. 运行时间:复杂度为 O ( ( d + N ) m q log ⁡ ( N m q m δ ) ) O\left((d\text{+}N)m_q\log\left(\cfrac{Nm_qm}{\delta}\right)\right) O((d+N)mqlog(δNmqm)),相比之下暴力搜索的复杂度是 O ( m q m N d ) O\left({{m}_{q}{mNd}}\right) O(mqmNd)

3.   \textbf{3. } 3. 实现与优化的细节

3.1.   \textbf{3.1. } 3.1. 过滤操作(类似 PLAID \textbf{PLAID} PLAID)

1️⃣带有预过滤的构建操作

  1. 输入:若干向量集,如 D = { S 1 , S 2 , . . . , S N } D\text{=}\{S_1,S_2,...,S_N\} D={S1,S2,...,SN}
  2. 聚类:对所有向量 { x 11 , . . . , x 1 m 1 ∣ x 21 , . . . , x 2 m 1 ∣ . . . ∣ x N 1 , . . . , x N m 1 } \{x_{11},...,x_{1m_1}|x_{21},...,x_{2m_1}|...|x_{N1},...,x_{Nm_1}\} {x11,...,x1m1x21,...,x2m1∣...∣xN1,...,xNm1}进行 k -Means k\text{-Means} k-Means聚类得质心集 { c k } \{c_k\} {ck}
  3. 倒排:为每个质心 c k c_k ck设置一个桶,完成以下操作以构建倒排索引
    • 对每个 S i = { x i 1 , x i 2 , . . . , x i m i } ∈ D S_i\text{=}\{x_{i1},x_{i2},...,x_{im_i}\}\text{∈}D Si={xi1,xi2,...,ximi}D,确定每个 x i j ∈ S i x_{ij}\text{∈}S_i xijSi所属质心,将 S i S_i Si ID \text{ID} ID分到该质心所属的桶中
    • 遍历完所有 S i S_i Si后提取每个质心的桶,即可得到每个质心 → \text{→} 与该质心有关的向量集 ID \text{ID} ID的倒排索引
  4. 构建:对于每个 S i = { x i 1 , x i 2 , . . . , x i m i } S_i\text{=}\{x_{i1},x_{i2},...,x_{im_i}\} Si={xi1,xi2,...,ximi}都执行索引构建操作,不赘述

2️⃣带有预过滤的查询阶段

  1. 输入:查询向量集 Q = { q 1 , q 2 , . . . , q m q } Q\text{=}\{q_1,q_2,...,q_{m_q}\} Q={q1,q2,...,qmq},以及上一步构建的 DESSERT \text{DESSERT} DESSERT索引 + \text{+} +质心到向量集的倒排索引
  2. 过滤:对于 Q Q Q中的每一个向量 q r q_r qr,获取与每个 q r q_r qr最近的 n probe n_{\text{probe}} nprobe个质心
    • 获得这些质心的倒排索引桶,统计这些桶中每个向量集 ID \text{ID} ID出现的计数
    • 认为出现计数越多的向量集与查询越相关,故将基数最高的 Top- k filter \text{Top-}k_{\text{filter}} Top-kfilter作为候选向量集 D ′ D^\prime D
  3. 编码:照样用那 L L L LSH \text{LSH} LSH函数 ψ 1 , ψ 2 , . . . , ψ L \psi_1,\psi_2,...,\psi_L ψ1,ψ2,...,ψL,对 Q Q Q中所有元素进行 L L L次分桶
  4. 得分:评分和聚合相同不再赘述,不同在于考虑的范围从原来的全部向量集 D D D缩小为了候选向量集 D ′ D^\prime D

3.2.   \textbf{3.2. } 3.2. 哈希拼接

1️⃣动机:为何拼接可以提升分桶效率

  1. 事实上:基于 Transformer \text{Transformer} Transformer的语言模型由于其注意力偏好,会使得嵌入后的向量彼此邻近
  2. 分桶时:以 ColBERT \text{ColBERT} ColBERT为例,其嵌入出来的向量平均余弦相似度为 0.3 \text{0.3} 0.3
    • 假设 x x x落入桶 ψ ( x ) \psi(x) ψ(x),则其它任意 y y y由于 Pr [ ψ ( x ) = ψ ( y ) ] =Sim ( x , y ) ≈ 0.3 \text{Pr}[\psi{(x)}\text{=}\psi{(y)}]\text{=}\text{Sim}(x,y)\text{≈}0.3 Pr[ψ(x)=ψ(y)]=Sim(x,y)0.3也有 30% \text{30\%} 30%左右的概率落入桶 ψ ( x ) \psi(x) ψ(x)
    • 这将导致大量的向量集中于 ψ ( x ) \psi(x) ψ(x)一个桶中,即桶过度填充

2️⃣将拼接应用于分桶

  1. 原有的: ψ t \psi_t ψt x i j x_{ij} xij的分桶结果为 ψ t ( x i j ) \psi{_t(x_{ij})} ψt(xij),即 x i j x_{ij} xij哈希值是一个标量
  2. 拼接后:将 ψ t \psi_t ψt分解为子哈希函数 ψ t , 1 , ψ t , 2 , . . . , ψ t , C \psi_{t,1},\psi_{t,2},...,\psi_{t,C} ψt,1,ψt,2,...,ψt,C,则 x i j x_{ij} xij哈希值为向量 ψ t ( x i j ) = { ψ t , 1 ( x i j ) , ψ t , 2 ( x i j ) , . . . , ψ t , C ( x i j ) } \psi_t(x_{ij})\text{=}\{\psi_{t,1}(x_{ij}),\psi_{t,2}(x_{ij}),...,\psi_{t,C}(x_{ij})\} ψt(xij)={ψt,1(xij),ψt,2(xij),...,ψt,C(xij)}
  3. 碰撞率:拼接后变为原来的 C C C次幂
    • 拼接后要求对于每个 ψ t , i \psi_{t,i} ψt,i都有 Pr [ ψ t , i ( x ) = ψ t , i ( y ) ] =Sim ( x , y ) \text{Pr}[\psi_{t,i}{(x)}\text{=}\psi_{t,i}{(y)}]\text{=}\text{Sim}(x,y) Pr[ψt,i(x)=ψt,i(y)]=Sim(x,y) x y xy xy才算碰撞,即对 ψ t \psi_t ψt才有 Pr [ ψ t ( x ) = ψ t ( y ) ] \text{Pr}[\psi_{t}{(x)}\text{=}\psi_{t}{(y)}] Pr[ψt(x)=ψt(y)]
    • 故对于 ψ t \psi_t ψt Pr [ ψ t ( x ) = ψ t ( y ) ] = ∏ i = 1 C Pr [ ψ t , i ( x ) = ψ t , i ( y ) ] =Sim ( x , y ) C \text{Pr}[\psi_{t}{(x)}\text{=}\psi_{t}{(y)}]\text{=}\displaystyle{\prod_{i=1}^C}\text{Pr}[\psi_{t,i}{(x)}\text{=}\psi_{t,i}{(y)}]\text{=}\text{Sim}(x,y)^C Pr[ψt(x)=ψt(y)]=i=1CPr[ψt,i(x)=ψt,i(y)]=Sim(x,y)C,即 Sim ( x , y ) = exp ⁡ ( ln ⁡ { Pr [ ψ ( x ) = ψ ( y ) ] } C ) \displaystyle\text{Sim}\left({x,y}\right)\text{=}\exp\left(\frac{\ln\{\text{Pr}[\psi(x)\text{=}\psi(y)]\}}{C}\right) Sim(x,y)=exp(Cln{Pr[ψ(x)=ψ(y)]})

3️⃣将拼接应用于评分

  1. 原始的评分机制:
    • 对于 q r ∈ Q q_r\text{∈}Q qrQ x i j ∈ S i x_{ij}\text{∈}S_i xijSi,检查其在 L L L个哈希表中的碰撞次数 Count ( q r , x i j ) \text{Count}(q_r,x_{ij}) Count(qr,xij)
    • 估计碰撞概率为 Pr ^ [ ψ ( q r ) = ψ ( x i j ) ] = Count ( q r , x i j ) L \hat{\text{Pr}}[\psi(q_r)\text{=}\psi(x_{ij})]\text{=}\cfrac{\text{Count}(q_r,x_{ij})}{L} Pr^[ψ(qr)=ψ(xij)]=LCount(qr,xij)
    • 基于 Pr [ ψ ( x ) = ψ ( y ) ] =Sim ( x , y ) \text{Pr}[\psi{(x)}\text{=}\psi{(y)}]\text{=}\text{Sim}(x,y) Pr[ψ(x)=ψ(y)]=Sim(x,y),可得 x i j x_{ij} xij q r q_r qr相似度为 Sim ^ ( q r , x i j ) = Count ( q r , x i j ) L \hat{\text{Sim}}(q_r,x_{ij})\text{=}\cfrac{\text{Count}(q_r,x_{ij})}{L} Sim^(qr,xij)=LCount(qr,xij)
  2. 拼接偶的评分机制:
    • 对于 q r ∈ Q q_r\text{∈}Q qrQ x i j ∈ S i x_{ij}\text{∈}S_i xijSi,检查其在 L L L个哈希表中的碰撞次数 Count ( q r , x i j ) \text{Count}(q_r,x_{ij}) Count(qr,xij)
    • 估计碰撞概率为 Pr ^ [ ψ ( q r ) = ψ ( x i j ) ] = Count ( q r , x i j ) L \hat{\text{Pr}}[\psi(q_r)\text{=}\psi(x_{ij})]\text{=}\cfrac{\text{Count}(q_r,x_{ij})}{L} Pr^[ψ(qr)=ψ(xij)]=LCount(qr,xij)
    • 基于 Sim ( x , y ) = exp ⁡ ( ln ⁡ { Pr [ ψ ( x ) = ψ ( y ) ] } C ) \displaystyle\text{Sim}\left({x,y}\right)\text{=}\exp\left(\frac{\ln\{\text{Pr}[\psi(x)\text{=}\psi(y)]\}}{C}\right) Sim(x,y)=exp(Cln{Pr[ψ(x)=ψ(y)]}),可得 x i j x_{ij} xij q r q_r qr相似度为 Sim ^ ( q r , x i j ) = exp ⁡ ( ln ⁡ { Count ( q r , x i j ) L } C ) \displaystyle{}\hat{\text{Sim}}(q_r,x_{ij})\text{=}\exp\left(\frac{\ln\left\{\frac{\text{Count}(q_r,x_{ij})}{L}\right\}}{C}\right) Sim^(qr,xij)=exp Cln{LCount(qr,xij)}

3.3.   \textbf{3.3. } 3.3. 系统级的优化: TinyTable \textbf{TinyTable} TinyTable

1️⃣动机:对于 D [ i ] t , h \mathcal{D}{\left\lbrack{}i\right\rbrack}_{t,h} D[i]t,h的实现(即每个桶的存储)太烂,以标准的std::vector实现为例

👉假定有三个向量集, ψ1/ψ2两个哈希函数, 每个哈希函数有3个桶
  S1 = {x11, x12, x13}
  S2 = {x21, x22, x23, x24, x25}
  S3 = {x31, x32, x33, x34}
👉对S1/S2/S3中所有的向量, 都分别用ψ1/ψ2处理一遍, 得到分桶结果
  S1的分桶           | S2的分桶           | S3的分桶
   ψ1-1: {x11}      |  ψ1-1: {x21}      |  ψ1-1: {x31}
   ψ1-2: {}         |  ψ1-2: {x25}      |  ψ1-2: {}
   ψ1-3: {}         |  ψ1-3: {x22, x24} |  ψ1-3: {x32}
   ψ2-1: {x12, x13} |  ψ2-1: {}         |  ψ2-1: {}
   ψ2-2: {}         |  ψ2-2: {}         |  ψ2-2: {x33}
   ψ2-3: {}         |  ψ2-3: {x23}      |  ψ2-3: {x34}
👉原始的解决方案会为每个桶创建一个std::vector对象以存储落入该桶的向量索引
  S1的分桶           | S2的分桶           | S3的分桶
   ψ1-1: {11}       |  ψ1-1: {21}       |  ψ1-1: {31}
   ψ1-2: {}         |  ψ1-2: {25}       |  ψ1-2: {}
   ψ1-3: {}         |  ψ1-3: {22, 24}   |  ψ1-3: {32}
   ψ2-1: {12, 13}   |  ψ2-1: {}         |  ψ2-1: {}
   ψ2-2: {}         |  ψ2-2: {}         |  ψ2-2: {33}
   ψ2-3: {}         |  ψ2-3: {23}       |  ψ2-3: {34}
  1. 对于每个桶:
    • 每个哈希桶都需要单独存放一个std::vector对象
    • 因此每个桶至少需要三个指针,分别指向已分配内存起始 / / /已分配内存终点 / / /已使用内存终点
    • 因此即使哈希桶为空,每个桶也必须占三指针共 24 \text{24} 24字节
  2. 总占用空间:
    • 假设有 100w \text{100w} 100w个向量集,每个向量集有 L = 64 L\text{=}64 L=64个哈希函数(哈希表),每个哈希函数有 r = 128 r\text{=}128 r=128个桶
    • 所有空桶就占用了 196GB \text{196GB} 196GB内存,编码 100w \text{100w} 100w个向量集还要超过此

2️⃣ TinyTable \text{TinyTable} TinyTable的优化实现

  1. 每个 S i S_i Si都有一个向量 ID \text{ID} ID向量:相当于把该 S i S_i Si所有的桶拍扁放在一个向量中
    👉原始的分桶实现
      S1的分桶           | S2的分桶           | S3的分桶
       ψ1-1: {11}       |  ψ1-1: {21}       |  ψ1-1: {31}
       ψ1-2: {}         |  ψ1-2: {25}       |  ψ1-2: {}
       ψ1-3: {}         |  ψ1-3: {22, 24}   |  ψ1-3: {32}
       ψ2-1: {12, 13}   |  ψ2-1: {}         |  ψ2-1: {}
       ψ2-2: {}         |  ψ2-2: {}         |  ψ2-2: {33}
       ψ2-3: {}         |  ψ2-3: {23}       |  ψ2-3: {34}
    👉将原来的每个桶按顺序合并, 得到每个向量集的向量ID表
      S1_ID = {11, 12, 13}
      S2_ID = {21, 25, 22, 24, 23}
      S3_ID = {31, 32, 33, 34}
    
  2. 每个 S i S_i Si同时有一个偏移向量:用于对每个 S i S_i Si ID \text{ID} ID列表进行分割,以确定每个桶的边界
    👉偏移向量的范式
      [ψ1-1起, ψ1-2起, ψ1-3起, ψ1-3止, ψ2-1起, ψ2-2起, ψ2-3起, ψ2-3止]
    👉S1_offset = {0, 1, 1, 1, 1, 3, 3, 3}
         11 12 13           ψ1-1 ψ1-2 ψ1-3 ψ2-1 ψ2-2 ψ2-3
       起 0  1  2 ----------> 0    1    1    1    3    3  
       止 1  2  3             1    1    1    3    3    3 
    👉S2_offset = {0, 1, 2, 4, 4, 4, 4, 5}
         21 25 22 24 23     ψ1-1 ψ1-2 ψ1-3 ψ2-1 ψ2-2 ψ2-3
       起 0  1  2  3  4 ----> 0    1    2    4    4    4
       止 1  2  3  4  5       1    2    4    4    4    5
    👉S3_offset = {0, 1, 1, 2, 2, 2, 3, 4}
         31 32 33 34        ψ1-1 ψ1-2 ψ1-3 ψ2-1 ψ2-2 ψ2-3
       起 0  1  2  3 -------> 0    1    1    2    2    3
       止 1  2  3  4          1    1    2    2    3    4
    
  3. 占用内存分析:
    • 同样假设有 100w \text{100w} 100w个向量集,每个向量集有 L = 64 L\text{=}64 L=64个哈希函数(哈希表),每个哈希函数有 r = 128 r\text{=}128 r=128个桶
    • ID \text{ID} ID向量的长度和其对应的向量集 S i S_i Si长度一样(假设平均长 100 \text{100} 100),偏移向量的长度则统一为 L ( r + 1 ) L(r\text{+}1) L(r+1)
    • 假设向量集 S i S_i Si长度都不超过 256 \text{256} 256,则每个 ID \text{ID} ID和每个偏移量都是 1 \text{1} 1字节,则总占用内存大小为 14.7GB \text{14.7GB} 14.7GB

4.   \textbf{4. } 4. 实验结果概述

1️⃣相比暴力搜索的时间优势

  1. 做法:由随机的 Glove \text{Glove} Glove生成一系列"人造"向量,对比 DESSERT \text{DESSERT} DESSERT和暴力搜索的性能
  2. 结果:对比查询时间(而非性能), DESSERT \text{DESSERT} DESSERT比暴力方法快 10-50 \text{10-50} 10-50

2️⃣段落检索的性能优势

  1. 数据集: LoTTe \text{LoTTe} LoTTe Ms-Marco \text{Ms-Marco} Ms-Marco
  2. 对比结果:检索质量(召回率)略微降低,但是检延迟下降为原来的 1/3 \text{1/3} 1/3左右

相关文章:

  • C++中std::priority_queue的使用说明
  • #MySQL 语句大全(完整实用教程)
  • 生成对抗网络(GAN)详解
  • Java代理(四)动态代理之CGLIB
  • 单网卡上绑定多个虚拟IP(AI回答)
  • linux部署成功,但外网无法访问
  • 数据结构与算法:子数组最大累加和问题及扩展
  • 百度查询的ip与命令行输入 ipconfig 显示的IP地址有以下主要区别:
  • 管家婆财贸ERP BB102.采购销售订金管理
  • 快速生成mysql测试数据10w条
  • CSP/信奥赛C++中格式化输入输出scanf和printf的使用详解
  • 快速上手示例(以BEVFormer为例)
  • 【蓝桥杯】考前冲刺!
  • Unity中的静态合批使用整理
  • Oracle 数据库中,并行 DML
  • XSLFO XSLT:深入解析两种强大的XML转换技术
  • leetcode0069. x 的平方根-easy
  • 从零构建大语言模型全栈开发指南:第五部分:行业应用与前沿探索-5.1.2行业落地挑战:算力成本与数据隐私解决方案
  • 操作系统(二):实时系统介绍与实例分析
  • PM2 在 Node.js 项目中的使用与部署指南