標籤:art match 多模組 官方 tor 數學計算 fill cto enc
關於局部敏感雜湊演算法。之前用R語言實現過,可是由於在R中效能太低。於是放棄用LSH來做類似性檢索。學了python發現非常多模組都能實現,並且通過隨機投影森林讓查詢資料更快。覺得能夠試試大規模應用在資料類似性檢索+去重的情境。
私覺得,文本的類似效能夠分為兩類:一類是機械類似性;一類是語義類似性。
機械類似性代表著,兩個常值內容上的相關程度。比方“你好嗎”和“你好”的類似性。純粹代表著內容上字元是否全然共現,應用情境在:文章去重;
語義類似性代表著,兩個文本語義上的類似程度。比方“蘋果”和“公司”的類似性。本篇不做這一討論
之前寫關於R語言實現的部落格:
R語言實現︱局部敏感雜湊演算法(LSH)解決文本機械類似性的問題(一,基本原理)
R語言實現︱局部敏感雜湊演算法(LSH)解決文本機械類似性的問題(二。textreuse介紹)
機械類似性python版的四部曲:
LSH︱python實現局部敏感隨機投影森林——LSHForest/sklearn(一)
LSH︱python實現局部敏感雜湊——LSHash(二)
類似性︱python+opencv實現pHash演算法+hamming距離(simhash)(三)
LSH︱python實現MinHash-LSH及MinHash LSH Forest——datasketch(四)
.
一、隨機投影森林
本節參考:論文《基於隨機投影的情境文本映像聚類方法研究》與部落格 隨機投影森林-一種近似近期鄰方法(ANN)
1、隨機投影森林理論與實現虛擬碼
當資料個數比較大的時候,線性搜尋尋找KNN的時間開銷太大,並且須要讀取全部的資料在記憶體中,這是不現實的。因此,實際project上,使用近似近期鄰也就是ANN問題。
當中一種方法是利用隨機投影樹,對全部的資料進行劃分,將每次搜尋與計算的點的數目減小到一個可接受的範圍,然後建立多個隨機投影樹構成隨機投影森林,將森林的綜合結果作為終於的結果。
?建立一棵隨機投影樹的過程大致例如以下(以二維空間為例):
- 隨機選取一個從原點出發的向量
- 與這個向量垂直的直線將平面內的點劃分為了兩部分
- 將屬於這兩部分的點分別劃分給左子樹和右子樹
在數學計算上。是通過計算各個點與垂直向量的點積完畢這一步驟的,點積大於零的點劃分到左子樹,點積小於零的點劃分到右子樹。
注意一點。圖中不帶箭頭的直線是用於劃分左右子樹的根據,帶箭頭的向量是用於計算點積的。這樣,原有的點就劃分為了兩部分,圖比例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjY5MTczODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="這裡寫圖片描寫敘述" title="">
可是此時一個劃分結果內的點的數目還是比較多。因此繼續劃分。再次隨機選取一個向量。與該向量垂直的直線將全部點進行了劃分。圖比例如以下:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvc2luYXRfMjY5MTczODM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/SouthEast" alt="這裡寫圖片描寫敘述" title="">
注意一點,此時的劃分是在上一次劃分的基礎上進行的。
?也就是說如今圖中的點已經被劃分成了四部分,相應於一棵深度為2。有四個分葉節點的樹。
以此類推繼續劃分下去,直到每一個分葉節點中點的數目都達到一個足夠小的數目。
注意這棵樹並非全然樹。
隨機投影森林的建立須要兩個參數。即單棵樹的深度 + 森林數量。
這兩個參數決定了資料集的分散程度以及隨機投影后得到的向量維數。
利用這棵樹對新的點進行近期鄰計算時,首先通過計算該點與每次劃分所用向量的點積。來找到其所屬於的分葉節點,然後利用這個分葉節點內的??這些點進行近期鄰演算法的計算。
這個過程是一棵隨機投影樹的計算過程。利用相同的方法。建立多個隨機投影樹構成隨機森林,將森林的總和結果作為終於的結果。
.
2、相應拓展
Wright等人 已將隨機投影的方法應用於視角變化的Face Service,Nowak等人 採用隨機投影的方法學習視覺詞的類似度度量。Freund等人將隨機投影應用於手寫體識別上,取得了非常好的效果。
.
3、隨機投影森林構造向量+聚類
論文《基於隨機投影的情境文本映像聚類方法研究》中,將每一個葉子節點當成一維特徵,用葉子節點的特徵點個數作為葉子節點的描寫敘述,最後得到測試映像的特徵向量。
有點類似word2vec之中的霍夫曼樹。
論文中的實驗結果:
當中。森林規模10棵。
- 第三組實驗實驗資料是google圖片集。聚類演算法使用AP聚類,用不同的局部特徵描寫敘述法(ASIFT與SIFT)得到的聚類結果ASIFT局部特徵描寫敘述得到的結果比SIFT方法在各項指標上都高10%以上。
由此可見。ASIFT比SIFT對自然情境下的文本地區映像的局部特徵描寫敘述更好更準確。這是由於SIFT僅僅是具有尺度和旋轉不變性。對於具有視角變化的相同文字卻無法得到匹配描寫敘述。而ASIFT不僅對映像具有尺度旋轉不變性,還具有仿射不變性,這樣的特性對自然情境下的文本處理有更好的有用性。
具體的ASIFT與SIFT對照可見論文。
.
二、LSHForest/sklearn
LSHforest=LSH+隨機投影樹
在python的sklearn中有LSHForest能夠實現。
官方文檔在:sklearn.neighbors.LSHForest
1、主函數LSHForest
class sklearn.neighbors.LSHForest(n_estimators=10, radius=1.0, n_candidates=50, n_neighbors=5, min_hash_match=4, radius_cutoff_ratio=0.9, random_state=None)
隨機投影森林是近期鄰搜尋方法的一種替代方法。
LSH森林資料結構使用已排序數組、二進位搜尋和32位固定長度的雜湊表達。
隨機投影計算距離是使用近似餘弦距離。
n_estimators : int (default = 10)樹的數量min_hash_match : int (default = 4)最小雜湊搜尋長度/個數。小於則停止n_candidates : int (default = 10)每一顆樹評估數量的最小值。反正至少每棵樹要評估幾次,雨露均沾n_neighbors : int (default = 5)檢索時。最小近鄰個數,就怕你忘記忘了設定檢索數量了 radius : float, optinal (default = 1.0)檢索時。近鄰個體的距離半徑radius_cutoff_ratio : float, optional (default = 0.9)檢索時,半徑的下限,相當於類似性機率小於某閾值時,停止搜尋,或者最小雜湊搜尋長度小於4也停止random_state : int, RandomState instance or None, optional (default=None)隨機數產生器使用種子。預設沒有
附帶屬性:
hash_functions_ : list of GaussianRandomProjectionHash objects雜湊函數g(p,x),每一個樣本一個雜湊化內容trees_ : array, shape (n_estimators, n_samples)Each tree (corresponding to a hash function) 每棵樹相應一個雜湊散列。且這個雜湊散列是經過排序的。顯示的是雜湊值。n_estimators棵樹。n_samples個散列。
original_indices_ : array, shape (n_estimators, n_samples)每棵樹相應一個雜湊散列,雜湊散列是經過排序的。顯示的是原資料序號index.
trees_ 和original_indices_ 就是兩種狀態,trees_ 是每棵經過排序樹的散列,original_indices_ 是每棵經過排序樹的序號Index.
.
2、LSHForeast相關函數
Fit the LSH forest on the data.
資料載入投影樹
Get parameters for this estimator.
擷取樹裡面的相關參數
- kneighbors(X, n_neighbors=None, return_distance=True)
檢索函數,n_neighbors代表所需近鄰數。 不設定的話則返回初始化設定的數量。return_distance,是否列印/返回特定cos距離的樣本。
返回兩個array。一個是距離array。一個是機率array
- kneighbors_graph([X, n_neighbors, mode])
Computes the (weighted) graph of k-Neighbors for points in X
數量檢索圖,n_neighbors代表所需近鄰數, 不設定的話則返回初始化設定的數量,mode=’connectivity’預設
加入資料到樹裡面,最好是大量匯入。
- radius_neighbors(X[, radius, return_distance])
Finds the neighbors within a given radius of a point or points.
半徑檢索。在給定的區間半徑內尋找近鄰,radius為半徑長度。return_distance代表是否列印出內容。
- radius_neighbors_graph([X, radius, mode])
Computes the (weighted) graph of Neighbors for points in X
半徑檢索圖
Set the parameters of this estimator.
重設部分參數
.
3、案例一則
>>> from sklearn.neighbors import LSHForest>>> X_train = [[5, 5, 2], [21, 5, 5], [1, 1, 1], [8, 9, 1], [6, 10, 2]]>>> X_test = [[9, 1, 6], [3, 1, 10], [7, 10, 3]]>>> lshf = LSHForest(random_state=42)>>> lshf.fit(X_train) LSHForest(min_hash_match=4, n_candidates=50, n_estimators=10, n_neighbors=5, radius=1.0, radius_cutoff_ratio=0.9, random_state=42)>>> distances, indices = lshf.kneighbors(X_test, n_neighbors=2)>>> distances array([[ 0.069..., 0.149...], [ 0.229..., 0.481...], [ 0.004..., 0.014...]])>>> indicesarray([[1, 2], [2, 0], [4, 0]])
LSHForest(random_state=42)樹的初始化,
lshf.fit(X_train)開始把資料載入初始化的樹;
lshf.kneighbors(X_test, n_neighbors=2)。找出X_test每一個元素的前2個(n_neighbors)類似內容。
當中。這個是cos距離,不是類似性,假設要直觀,能夠被1減。
.
4、案例二則
來源於:用docsim/doc2vec/LSH比較兩個文檔之間的類似度
# 使用lsh來處理 tfidf_vectorizer = TfidfVectorizer(min_df=3, max_features=None, ngram_range=(1, 2), use_idf=1, smooth_idf=1,sublinear_tf=1) train_documents = [] for item_text in raw_documents: item_str = util_words_cut.get_class_words_with_space(item_text) train_documents.append(item_str) x_train = tfidf_vectorizer.fit_transform(train_documents) test_data_1 = ‘你好。我想問一下我想離婚他不想離,孩子他說不要,是六個月就自己主動生效離婚‘ test_cut_raw_1 = util_words_cut.get_class_words_with_space(test_data_1) x_test = tfidf_vectorizer.transform([test_cut_raw_1]) lshf = LSHForest(random_state=42) lshf.fit(x_train.toarray()) distances, indices = lshf.kneighbors(x_test.toarray(), n_neighbors=3) print(distances) print(indices)
一般lsh比較適合做短文本的比較
.
相關拓展:
相關屬性獲得
# 屬性lshf.trees_ # 每棵樹,排序散列的雜湊值lshf.hash_functions_ # 每棵樹的hash公式lshf.original_indices_# 每棵樹,排序散列的序號index
近期鄰檢索的圖:kneighbors_graph
lshf.kneighbors_graph(X_test, n_neighbors=5, mode=‘connectivity‘)
新增資料到樹裡面:
partial_fit(X_test)
LSH︱python實現局部敏感隨機投影森林——LSHForest/sklearn(一)