文献分享: DESSERT基于LSH的多向量检索(Part1——原理与实现)
原论文
文章目录
1. \textbf{1. } 1. 背景与导论
1.1. \textbf{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
- 输出:用 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)的定义
- 子相似度:衡量每个 q r ∈ Q q_r\text{∈}Q qr∈Q和 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si时间的相似度
👉举个例子,对于查询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)
- 内部聚合 σ \sigma σ:让每个 q r ∈ Q q_r\text{∈}Q qr∈Q得到一共聚合后的相似度,类似于 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)}
- 外部聚合 A A A:将每个 q r ∈ Q q_r\text{∈}Q qr∈Q内部聚合的结果进行处理,得到最后评分 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️⃣向量集搜索:基于单向量最邻近的方案
- 输入:给定查询 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}
- 检索:让每个 q r ∈ Q q_r\text{∈}Q qr∈Q在所有 S 1 ∪ S 2 ∪ … ∪ S N S_1\text{∪}S_2\text{∪}\ldots\text{∪}S_N S1∪S2∪…∪SN中执行 MIPS \text{MIPS} MIPS(最大内积搜索),得到其 Top- K \text{Top-}K Top-K的向量
- 候选:一共得到了 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),...}
- 重排:计算 Q Q Q与候选集中向量集的精确距离 F ( Q , S ( i ) ) F\left(Q,S_{(i)}\right) F(Q,S(i)),以对候选向量集进行重排
2️⃣存在的问题
- 检索效果上:假设某个 q r ∈ Q q_r\text{∈}Q qr∈Q的最邻近是 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si,二者各自的向量邻近和 F ( Q , S i ) F(Q,S_i) F(Q,Si)会很大没有半毛钱关系
- 检索成本上: S 1 ∪ S 2 ∪ … ∪ S N S_1\text{∪}S_2\text{∪}\ldots\text{∪}S_N S1∪S2∪…∪SN中但向量规模是巨大的,成本会爆掉
1.3. \textbf{1.3. } 1.3. 关于 LSH \textbf{LSH} LSH
1️⃣几种不同的 LSH \text{LSH} LSH回顾
- 基于余弦相似度的 LSH \text{LSH} LSH:
- 原理:一般用随机超平面对分割空间,一个子空间就是一个桶,两向量内积越大越可能落入同一桶
- 例如: Muvera \text{Muvera} Muvera中用到的 SimHash \text{SimHash} SimHash
- 基于欧几里得距离的 LSH \text{LSH} LSH
- 原理:一般将所有向量投影到随机方向的直线上,直线上每 w w w步长就是一个桶,两向量欧式距离近者更可能落入同一桶
- 例如:经典的如 E2LSH \text{E2LSH} E2LSH,其基于动态分桶的改进 QALSH \text{QALSH} QALSH
- 基于 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的假设
- 假设:存在一个哈希家族 H ⊂ ( R d → Z ) \mathcal{H}\text{⊂}\left({{\mathbb{R}}^{d} \text{→}\mathbb{Z}}\right) H⊂(Rd→Z)及其分桶哈希函数 ψ \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. \textbf{2. } 2. 算法及理论保证
2.1. \textbf{2.1. } 2.1. 算法的朴素流程
1️⃣索引构建
- 输入:若干向量集,如 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}都执行索引构建操作
- 索引分配:为 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️⃣查询阶段
- 输入:查询向量集 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索引
- 编码:照样用那 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次分桶
- 评分:通过检查 q r ∈ Q q_r\text{∈}Q qr∈Q和 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si的碰撞次数 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 qr∈Q和 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si各自进行 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 ∀qr∈Q用哈希函数 ψ 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)
- 聚合:基于相似度 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 qr∈Q的近似相似度集 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 qr∈Q内部聚合结果相加
2.2. \textbf{2.2. } 2.2. 算法的理论保证
2.2.1. \textbf{2.2.1. } 2.2.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):Rm→R在 U U U上是 ( α , β ) - (α,β)\text{-} (α,β)-极大的,等价于 ∀ x ∈ U \forall{x}\text{∈}U ∀x∈U有 β 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)-极大
- 引理 4.1.1 \text{4.1.1} 4.1.1:平均极值下界衰减引理
- 条件: φ ( x ) : R → R \varphi(x)\text{:}ℝ\text{→}ℝ φ(x):R→R在区间 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=1∑mφ(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+exex–21 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
- 输入:对查询向量集 ∀ q r ∈ Q = { q 1 , q 2 , . . . , q m q } \forall{}q_{r}\text{∈}Q\text{=}\{q_1,q_2,...,q_{m_q}\} ∀qr∈Q={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 qr∈Q的真实相似度集: 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 qr∈Q的近似相似度集: 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)}
- 符号:对真实相似度集 / / /近似相似度集,采取不同聚合方式
- 真实集:用最值聚合 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^)
- γ \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(α–τ))τ/α
![]()
- 单调:处于 ( 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
- 结论:给定一个阈值 τ ∈ [ α 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–Δ]≤2e–2LΔ2/β2,对近似相似度聚合后,大概率不低于理论下界
2.2.2. \textbf{2.2.2. } 2.2.2. 外部聚合及运行时间
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就不做简写了
- 外部聚合评分:让外部聚合 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=1∑mqwrσ(s (qr,Si))
- 最邻近向量集:给定 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 S∗∈D是使得 F ( Q , S i ) F\left({Q,S_i}\right) F(Q,Si)最大的向量集
- 分析时的假设:假定所有向量集的向量数都相同,即统一将 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:概率对数近邻保证定理
- 设定参数:对于 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=1∑mqwrmax(s(qr,S∗))=mqβr=1∑mqwrMaxSim(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=1∑mqwrmax(s(qr,Si))=mqαr=1∑mqwrMaxSim(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能取得的最大值
- 结论:只要我们选择足够大的哈希表数量,算法就能以高概率返回正确最邻近向量集
- 条件:当 Δ = B ∗ – B ′ 3 > 0 \Delta{\text{=}}\cfrac{B^*–B^\prime}{3}\text{>}0 Δ=3B∗–B′>0时,,设定 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️⃣运行时间的分析
- 一些前提:假设每个哈希函数运行的时间为 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,h∣≤T
- 运行时间:复杂度为 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️⃣带有预过滤的构建操作
- 输入:若干向量集,如 D = { S 1 , S 2 , . . . , S N } D\text{=}\{S_1,S_2,...,S_N\} D={S1,S2,...,SN}
- 聚类:对所有向量 { 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,...,x1m1∣x21,...,x2m1∣...∣xN1,...,xNm1}进行 k -Means k\text{-Means} k-Means聚类得质心集 { c k } \{c_k\} {ck}
- 倒排:为每个质心 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 xij∈Si所属质心,将 S i S_i Si的 ID \text{ID} ID分到该质心所属的桶中
- 遍历完所有 S i S_i Si后提取每个质心的桶,即可得到每个质心 → \text{→} →与该质心有关的向量集 ID \text{ID} ID的倒排索引
- 构建:对于每个 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 = { 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{+} +质心到向量集的倒排索引
- 过滤:对于 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′
- 编码:照样用那 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次分桶
- 得分:评分和聚合相同不再赘述,不同在于考虑的范围从原来的全部向量集 D D D缩小为了候选向量集 D ′ D^\prime D′
3.2. \textbf{3.2. } 3.2. 哈希拼接
1️⃣动机:为何拼接可以提升分桶效率
- 事实上:基于 Transformer \text{Transformer} Transformer的语言模型由于其注意力偏好,会使得嵌入后的向量彼此邻近
- 分桶时:以 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️⃣将拼接应用于分桶
- 原有的: ψ 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哈希值是一个标量
- 拼接后:将 ψ 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)}
- 碰撞率:拼接后变为原来的 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=1∏CPr[ψ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️⃣将拼接应用于评分
- 原始的评分机制:
- 对于 q r ∈ Q q_r\text{∈}Q qr∈Q和 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si,检查其在 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)
- 拼接偶的评分机制:
- 对于 q r ∈ Q q_r\text{∈}Q qr∈Q和 x i j ∈ S i x_{ij}\text{∈}S_i xij∈Si,检查其在 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}
- 对于每个桶:
- 每个哈希桶都需要单独存放一个
std::vector
对象- 因此每个桶至少需要三个指针,分别指向已分配内存起始 / / /已分配内存终点 / / /已使用内存终点
- 因此即使哈希桶为空,每个桶也必须占三指针共 24 \text{24} 24字节
- 总占用空间:
- 假设有 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的优化实现
- 每个 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}
- 每个 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
- 占用内存分析:
- 同样假设有 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️⃣相比暴力搜索的时间优势
- 做法:由随机的 Glove \text{Glove} Glove生成一系列"人造"向量,对比 DESSERT \text{DESSERT} DESSERT和暴力搜索的性能
- 结果:对比查询时间(而非性能), DESSERT \text{DESSERT} DESSERT比暴力方法快 10-50 \text{10-50} 10-50倍
2️⃣段落检索的性能优势
- 数据集: LoTTe \text{LoTTe} LoTTe和 Ms-Marco \text{Ms-Marco} Ms-Marco
- 对比结果:检索质量(召回率)略微降低,但是检延迟下降为原来的 1/3 \text{1/3} 1/3左右