faiss 三种基础索引方式
????????faiss 三個最基礎的 index. 分別是?IndexFlatL2,?IndexIVFFlat,?IndexIVFPQ
????????搜索時,可以以查詢向量為中心,返回距離在一定范圍內(nèi)的結果,如返回數(shù)據(jù)庫中與查詢向量距離小于0.3的結果。不是所有的Index都支持按距離檢索,但是下面三種Index都支持,只支持在CPU使用。
一、IndexFlatL2 - 最基礎的Index
IndexFlatL2索引的結果是精確的,可以用來作為其他索引測試中準確性程度的參考.
import numpy as np import faiss import timedef demo_IndexFlatL2():d = 2048 # 2048維的數(shù)據(jù)nb = 2 # database sizenq = 1 # nb of queriesnp.random.seed(1234)index = faiss.IndexFlatL2(d)print(index.is_trained)# 隨機nb個數(shù)據(jù)插入索引xb = np.random.random((nb, d)).astype('float32')xb[:, 0] += np.arange(nb) / 1000.index.add(xb)# 再隨機nb個數(shù)據(jù)插入索引xb1 = np.random.random((nb, d)).astype('float32')xb1[:, 0] += np.arange(nb) / 1000.index.add(xb1)print('index.ntotal:', index.ntotal)# 隨機nq個數(shù)據(jù)用于查詢xq = np.random.random((nq, d)).astype('float32')xq[:, 0] += np.arange(nq) / 1000.k = 4 # 查詢距離最近的4個D, I = index.search(xq, k) # 返回值D是距離 I是索引print("I: ", I)# 按照距離查詢dist = 1000 # 定義一個半徑/閾值_, D, I = index.range_search(xb[[2], :], dist) # 用第2個向量查詢print('range_search res:', I)# 刪除元素,dtype=np.int64非常重要print('remove之前ntotal:', index.ntotal)index.remove_ids(np.asarray((2,3), dtype=np.int64))print('remove之后ntotal:', index.ntotal)if __name__ == '__main__':demo_IndexFlatL2()二、更快的搜索 - IndexIVFFlat
????????為了加快搜索速度,可以將數(shù)據(jù)集分割成幾部分。我們在d維空間中定義Voronoi單元格,并且每個數(shù)據(jù)庫矢量都落入其中一個單元格中。在搜索時,只有查詢x所在單元中包含的數(shù)據(jù)庫向量y與少數(shù)幾個相鄰查詢向量進行比較。(劃分搜索空間)
????????這種類型的索引需要一個訓練的過程,可以在與數(shù)據(jù)庫向量具有相同分布的任何向量集合上執(zhí)行。
????????這IndexIVFFlat還需要另一個索引,即量化器(quantizer),它將矢量分配給Voronoi單元。每個單元由一個質心定義,找到一個矢量所在的Voronoi單元包括在質心集中找到該矢量的最近鄰居。這是另一個索引的任務,通常是索引IndexFlatL2。
搜索方法有兩個參數(shù):
- nlist 劃分單元的數(shù)量
- nprobe 執(zhí)行搜索訪問的單元格數(shù)(不包括nlist)
nprobe?參數(shù)始終是調(diào)整結果速度和準確度之間折中的一種方式?。設置 nprobe = nlist 將給出與蠻力搜索(但會更慢)相同的結果。
?
import numpy as np import faiss import timedef demo_IndexIVFFlat():d = 64 # 向量維度nb = 200 # 向量集大小nq = 10000 # 查詢次數(shù)np.random.seed(1234) # 隨機種子,使結果可復現(xiàn)nlist = 100k = 4quantizer = faiss.IndexFlatL2(d) # the other indexindex = faiss.IndexIVFFlat(quantizer, d, nlist, faiss.METRIC_L2)# here we specify METRIC_L2, by default it performs inner-product searchxb = np.random.random((nb, d)).astype('float32')xb[:, 0] += np.arange(nb) / 1000.index.train(xb)index.add(xb) # 添加索引可能會有一點慢print('index.ntotal:', index.ntotal)xb1 = np.random.random((nb, d)).astype('float32')xb1[:, 0] += np.arange(nb) / 1000.index.train(xb1)index.add(xb1) # 添加索引可能會有一點慢print('index.ntotal:', index.ntotal)xq = np.random.random((nq, d)).astype('float32')xq[:, 0] += np.arange(nq) / 1000.D, I = index.search(xq, k) # 搜索print(I[-5:]) # 最初五次查詢的結果index.nprobe = 10 # 執(zhí)行搜索訪問的單元格數(shù) 默認 nprobe 是1 ,可以設置的大一些試試D, I = index.search(xq, k)print(I[-5:]) # 最后五次查詢的結果# 按照距離查詢dist = 1000 # 定義一個半徑/閾值_, D, I = index.range_search(xb[[2], :], dist) # 用第2個向量查詢print('range_search res:', I)# 刪除元素,dtype=np.int64非常重要print('remove之前ntotal:', index.ntotal)index.remove_ids(np.asarray((2,3), dtype=np.int64))print('remove之后ntotal:', index.ntotal)if __name__ == '__main__':demo_IndexIVFFlat()三、更低的內(nèi)存占用 - IndexIVFPQ
????????索引IndexFlatL2和IndexIVFFlat都存儲完整的向量。 為了擴展到非常大的數(shù)據(jù)集,Faiss提供了基于產(chǎn)品量化器的有損壓縮來壓縮存儲的向量的變體。壓縮的方法基于乘積量化(Product Quantizer)。
在這種情況下,由于矢量沒有精確存儲,搜索方法返回的距離也是近似值。
?
?
總結
以上是生活随笔為你收集整理的faiss 三种基础索引方式的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【问题解决】思科模拟器字体大小问题,字体
- 下一篇: 第六大晶圆代工厂商2021净利润大增59