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/n/333031.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
VXUUSVXUUS
上一篇 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

发表回复

登录后才能评论