MinHash入門指南

一、什麼是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

(0)
打賞 微信掃一掃 微信掃一掃 支付寶掃一掃 支付寶掃一掃
VXUUS的頭像VXUUS
上一篇 2025-01-27 13:34
下一篇 2025-01-27 13:34

相關推薦

  • Java JsonPath 效率優化指南

    本篇文章將深入探討Java JsonPath的效率問題,並提供一些優化方案。 一、JsonPath 簡介 JsonPath是一個可用於從JSON數據中獲取信息的庫。它提供了一種DS…

    編程 2025-04-29
  • 運維Python和GO應用實踐指南

    本文將從多個角度詳細闡述運維Python和GO的實際應用,包括監控、管理、自動化、部署、持續集成等方面。 一、監控 運維中的監控是保證系統穩定性的重要手段。Python和GO都有強…

    編程 2025-04-29
  • Python wordcloud入門指南

    如何在Python中使用wordcloud庫生成文字雲? 一、安裝和導入wordcloud庫 在使用wordcloud前,需要保證庫已經安裝並導入: !pip install wo…

    編程 2025-04-29
  • Python應用程序的全面指南

    Python是一種功能強大而簡單易學的編程語言,適用於多種應用場景。本篇文章將從多個方面介紹Python如何應用於開發應用程序。 一、Web應用程序 目前,基於Python的Web…

    編程 2025-04-29
  • Python小波分解入門指南

    本文將介紹Python小波分解的概念、基本原理和實現方法,幫助初學者掌握相關技能。 一、小波變換概述 小波分解是一種廣泛應用於數字信號處理和圖像處理的方法,可以將信號分解成多個具有…

    編程 2025-04-29
  • Python字元轉列表指南

    Python是一個極為流行的腳本語言,在數據處理、數據分析、人工智慧等領域廣泛應用。在很多場景下需要將字元串轉換為列表,以便於操作和處理,本篇文章將從多個方面對Python字元轉列…

    編程 2025-04-29
  • Python初學者指南:第一個Python程序安裝步驟

    在本篇指南中,我們將通過以下方式來詳細講解第一個Python程序安裝步驟: Python的安裝和環境配置 在命令行中編寫和運行第一個Python程序 使用IDE編寫和運行第一個Py…

    編程 2025-04-29
  • Python起筆落筆全能開發指南

    Python起筆落筆是指在編寫Python代碼時的編寫習慣。一個好的起筆落筆習慣可以提高代碼的可讀性、可維護性和可擴展性,本文將從多個方面進行詳細闡述。 一、變數命名 變數命名是起…

    編程 2025-04-29
  • FusionMaps應用指南

    FusionMaps是一款基於JavaScript和Flash的互動式地圖可視化工具。它提供了一種簡單易用的方式,將複雜的數據可視化為地圖。本文將從基礎的配置開始講解,到如何定製和…

    編程 2025-04-29
  • Python中文版下載官網的完整指南

    Python是一種廣泛使用的編程語言,具有簡潔、易讀易寫等特點。Python中文版下載官網是Python學習和使用過程中的重要資源,本文將從多個方面對Python中文版下載官網進行…

    編程 2025-04-29

發表回復

登錄後才能評論