【3】facebook大數據搜索庫faiss使用——選擇Index
選擇Index並不明顯,有幾個問題可以幫助選擇Index。
是否需要精確結果
使用Flat。
IndexFlat2
是唯一能保證精確結果的Index。它為其他Index提供了對比標準。它不會壓縮向量,不支持帶標簽添加,只能順序添加。所以,如果你需要add_with_ids
,使用IDMap,Flat
。
內存是否有限制
請註意Faiss所有的Index都是存儲在RAM裏的,如果不需要精確結果,而同時RAM是有限的,在該限制下,我們在精度-速度中間進行衡量選擇。可以考慮下面的問題:
內存充足無限制:使用HNSWx
如果你有很多RAM或者搜索庫很小,HNSW是最好的選擇。它很快、很精確。4<=x<=64是每個向量的鏈接數,這個值越高越精確,但是使用的RAM越多。而速度-精度衡量則通過efSearch參數調節實現,每個向量占用內存數為(d4+x
HNSW不支持序列添加(not
add_with_ids
),同樣的,如果需要,則使用IDMap
。HNSW不需要訓練,也不支持從index中刪除向量。
內存不關註,使用"...,Flat"
"..."指的是需要進行的數據集聚類操作。聚類之後,“Flat”就把這些向量歸於桶中,所以並沒有亞索,所占的存儲空間大小等於原數據集。速度-精度衡量通過nprobe
參數控制。
內存比較有限,使用“PCARx,...,SQ8”
如果存儲整個向量非常占內存資源,可以通過兩種方法降低占用量:
- PCA降維;
- 每個向量元素進行可計量量化至1字節;
所以,存儲總量是每個向量的x字節。
內存非常有限,使用“OPQx_y, ..., PQx”
PQx使用PQ算法將每個向量進行壓縮輸出x字節的編碼,x一般來說小於等於64,對於大的編碼,SQ通常更精確、快速。OPQ是將向量進行線性轉換,使得其更容易壓縮。y表示的是一個維度,需滿足:
- y是x的因子;
- y<=d,d是輸入向量的維度;
- y <= 4*x
數據集有多大
這個問題就是對上文"..."部分的回答。數據集被聚成多個桶,在搜索時只有一部分桶被遍歷(nprobe個桶)。這個聚類操作只作用於數據集向量的具有代表性的樣例之上,通常是數據集的一個樣本集。我們針對樣本集給出其最優尺寸選擇:
如果低於1M向量:"...,IVFx,..."
其中x是4sqrt(N)~16sqrt(N),N是數據集的大小。這只是使用kmeans將向量聚起來,你需要30x~256x向量訓練(更多越好)。
如果1M-10M:"...,IMI2x10,..."
其中x是符號,不是數字。
IMI也對訓練集進行k-means聚類,聚成2^10中心點,但是在向量的前半部分和後半部分是獨立的。增加聚類數到2(2^10)。你需要大約64(2^10)向量訓練。
如果10M-100M:"...,IMI2x12,..."<千萬級-億級>
同上面的,10用12替換。
如果100M-1B:"...,IMI2X14,..."<億級-十億級>
同上面的,10用14替換。
【3】facebook大數據搜索庫faiss使用——選擇Index