一、什麼是MinHash
MinHash是一種用於近似相等度量的技術,它被廣泛應用於文本比較、網頁去重、音樂相似度分析等領域。
在使用MinHash之前,先來了解一下Jaccard相似度。
Jaccard相似度是用來衡量兩個集合相似度的指標,計算公式為:
J(A,B) = |A∩B| / |A∪B|
其中,A和B為兩個集合,|A∩B|為兩個集合的交集的元素個數,|A∪B|為兩個集合的並集的元素個數。
二、MinHash的原理
MinHash是基於Locality Sensitive Hashing(局部敏感哈希LSH)的一種技術,它可以近似計算出兩個集合的Jaccard相似度,且時間和空間複雜度都較小。
MinHash需要將集合中元素的哈希值分成多個小組,每組取一個最小的哈希值,將這些哈希值組成一個簽名(簽名的長度一般是一個固定值k),兩個集合的相似度就可以通過它們的簽名的相似度來近似計算。
通俗來講,就是將兩個集合的哈希值進行比較,如果兩個哈希值相同,那麼就把這個位置上的1替換成0,並記錄這個位置,那麼最後的結果就是兩個集合在所有位置上相同的數量,除以簽名的長度k即為它們的相似度近似值。
三、如何實現MinHash
Step1:生成哈希函數
MinHash需要用到多個哈希函數,每個哈希函數都可以將一個元素映射到0到1之間的一個隨機值,可以採用MurMurHash、SHA-1等哈希函數。在這裡,我們使用Python的hashlib庫來生成哈希函數。
import hashlib
class MinHash(object):
def __init__(self, k):
self.k = k
self.hashes = self._create_hashes()
def _create_hashes(self):
hashes = []
for i in range(self.k):
hashes.append(hashlib.sha1(str(i).encode('utf-8')))
return hashes
Step2:生成簽名
生成簽名需要先將集合里的元素用哈希函數生成一個哈希值,然後選取一個最小的哈希值作為這個元素的簽名,將所有元素的簽名組成一個簽名矩陣,每行代表一個元素的簽名,每列代表一個哈希函數的結果。
def _sig(self, element):
# 將元素用哈希函數映射為k個隨機值,選取一個最小的值作為這個元素的簽名
sig = []
for h in self.hashes:
h.update(str(element).encode('utf-8'))
sig.append(h.hexdigest())
return min(sig)
def generate_signature_matrix(self, elements):
# 生成元素的簽名矩陣
signature_matrix = []
for element in elements:
signature = [int(bit, 16) for bit in self._sig(element)]
signature_matrix.append(signature)
return signature_matrix
Step3:計算相似度
計算相似度需要先比較兩個集合每個元素的簽名,然後計算它們相同的元素數量,最後除以簽名的長度即可得到相似度的近似值。
def jaccard_similarity(self, signature1, signature2):
# 計算簽名的Jaccard相似度
count_same = sum([1 for i in range(len(signature1)) if signature1[i] == signature2[i]])
count_all = len(signature1)
return float(count_same) / float(count_all)
def minhash_similarity(self, set1, set2):
# 計算集合的MinHash相似度
signature_matrix1 = self.generate_signature_matrix(set1)
signature_matrix2 = self.generate_signature_matrix(set2)
similarities = []
for i in range(len(signature_matrix1)):
for j in range(len(signature_matrix2)):
similarity = self.jaccard_similarity(signature_matrix1[i], signature_matrix2[j])
similarities.append(similarity)
return sum(similarities) / len(similarities)
四、應用案例
MinHash最初是用於文本去重的,現在被廣泛應用於音樂相似度分析、推薦系統、網頁去重等領域。
Case1:文本去重
文本去重是指在一定的數據範圍內,將相似的文本取出來,一般是用於搜索引擎等領域。
假設有10000篇文章需要去重,要求相同文章不超過100篇,不同的文章要被歸為不同的組別。那麼可以使用MinHash對文章進行去重。首先,將每篇文章轉換成set格式,然後利用MinHash計算集合的相似度,找出相似度大於等於0.8的文章,它們就歸為同一組別。
import time
class Article(object):
def __init__(self, id, title, content):
self.id = id
self.title = title
self.content = content
self.words = set(self.title.split() + self.content.split())
def read_data():
# 讀取數據,返迴文章列表
articles = []
with open('articles.txt', 'r') as f:
for line in f:
id, title, content = line.strip().split('\t')
article = Article(id, title, content)
articles.append(article)
return articles
def deduplication(articles):
# 對文章進行去重
minhash = MinHash(10)
doc_signatures = []
for article in articles:
doc_signature = minhash.generate_signature_matrix(article.words)
doc_signatures.append((article.id, doc_signature))
groups = {}
for i in range(len(doc_signatures)):
id1, sig1 = doc_signatures[i]
for j in range(i+1, len(doc_signatures)):
id2, sig2 = doc_signatures[j]
similarity = minhash.minhash_similarity(sig1, sig2)
if similarity >= 0.8:
group_i = groups.get(id1, set([id1]))
group_i.add(id2)
groups[id1] = group_i
group_j = groups.get(id2, set([id2]))
group_j.add(id1)
groups[id2] = group_j
deduplicated_articles = []
for group in groups.values():
if len(group) = 0.8:
sub_group.add(id)
is_in_sub_group = True
break
if not is_in_sub_group:
sub_groups.append(set([id]))
for sub_group in sub_groups:
articles_in_group = [article for article in articles if article.id in sub_group]
deduplicated_articles.extend(articles_in_group)
return deduplicated_articles
if __name__ == '__main__':
start_time = time.time()
articles = read_data()
deduplicated_articles = deduplication(articles)
print('文章數量:{}'.format(len(deduplicated_articles)))
print('用時:{}s'.format(time.time() - start_time))
Case2:音樂相似度分析
音樂相似度分析是指在海量音樂數據中,根據用戶的聽歌記錄或者上傳音樂的音頻特徵提取,找出相似的音樂,用於音樂推薦、音樂搜索等領域。
首先,使用spectral clustering或者kmeans等聚類演算法將相似的音樂聚到一起,然後針對每個聚類,使用MinHash計算相似度,將相似度大於等於0.8的音樂歸為同一組別。
五、總結
MinHash是一種高效的近似相等度量技術,它可以廣泛用於文本去重、音樂相似度分析、推薦系統等領域。在使用MinHash時,需要先生成哈希函數、計算元素的簽名、比較簽名、計算相似度。通過應用案例,可以看到MinHash在實際場景中有著廣泛的應用。
原創文章,作者:VXUUS,如若轉載,請註明出處:https://www.506064.com/zh-tw/n/333031.html