【annoy】高維空間求近似最近鄰


介紹騰訊詞向量時,用到了annoy,這里對annoy的用法詳細做一下介紹。

GitHub地址:https://github.com/spotify/annoy

Annoy是Erik Bernhardsson在Hack Week期間花了幾個下午寫的(github原話),全稱Approximate Nearest Neighbors Oh Yeah(這個Oh Yeah真是亮瞎眼)。這個包的優點就是快,內存占用也小,還可以靜態存儲索引用於更多任務。目前已經在音樂推薦系統Spotify中應用。

這個工具可以用來計算空間中點的距離,輸入某個點,返回最近的若干點。

這個包直接pip install annoy就可以安裝,C++版本的直接下載后#include "annoylib.h"

使用方法:

from annoy import AnnoyIndex
import random

f = 40
t = AnnoyIndex(f, 'angular')  # Length of item vector that will be indexed
for i in range(1000):
    v = [random.gauss(0, 1) for z in range(f)]
    t.add_item(i, v)

t.build(10) # 10 trees
t.save('test.ann')

# ...

u = AnnoyIndex(f, 'angular')
u.load('test.ann') # super fast, will just mmap the file
print(u.get_nns_by_item(0, 1000)) # will find the 1000 nearest neighbors

默認的索引是從0到n-1。

API:

AnnoyIndex(f, metric) f 向量維度,metric 距離度量方式,取值 "angular", "euclidean", "manhattan", "hamming", or "dot". 計算angular是使用的sqrt(2(1-cos(u,v)))這個公式,用的歐幾里得距離。euc = sqrt(2(1-cos))。

a.add_item(i, v) 添加元素 i 和向量 v

a.build(n_trees, n_jobs=-1) n_trees是森林的樹數目,值越大結果越精確,n_jobs 進程數,默認-1使用所有的CPU。build調用之后,就不能再添加元素了。

a.save(fn, prefault=False) 保存到本地

a.load(fn, prefault=False) 從本地讀取,prefault是預先讀入內存,默認為False.

a.unload() 清除加載內容

a.get_nns_by_item(i, n, search_k=-1, include_distances=False) 返回n個最近元素。在查詢過程中,它將檢查search_k個節點,如果沒有提供,默認為n_trees * n。search_k給了一個速度和准確率的折中。include_distances設為True,會提供一個由兩個列表組成的二元組,第二個列表包含所有相關的距離。

a.get_nns_by_vector(v, n, search_k=-1, include_distances=False)結果一樣,不過是通過向量v來查詢。

a.get_item_vector(i) 返回索引i對應的向量

a.get_distance(i, j) 返回元素i和j的距離,squared distance

a.get_n_items() 返回元素數量

a.get_n_trees() 返回樹數目

a.on_disk_build(fn) 指定在除了RAM之外的其他文件上構建索引(在添加元素之前執行)

a.set_seed(seed) 在構建樹之前可以指定隨機數

這里面主要有兩個參數需要調,n_trees和search_k,一個是構建時的參數,一個是搜索時的參數。

下面這是qps和recall值之間的trade-off,使用時要綜合考慮准確率和速度。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM