掘金 人工智能 06月02日 11:43
文本相似度识别的“利器”:揭秘 Simhash 算法及其应用
index_new5.html
../../../zaker_core/zaker_tpl_static/wap/tpl_guoji1.html

 

Simhash 是一种用于快速识别文本相似度的算法,它将文本转化为短小的数字签名,通过比较签名来判断文本的相似程度。文章介绍了Simhash的原理,包括分词、哈希、加权叠加和签名生成。通过Python代码示例和实验结果分析,展示了Simhash在文本去重、垃圾邮件过滤等领域的应用。Simhash算法因其高效和鲁棒性,在搜索引擎、推荐系统等领域有广泛应用。

🔑Simhash算法通过分词、哈希和加权叠加,将文本转化为固定长度的二进制签名,用于快速判断文本的相似度。

💡Simhash算法的核心在于,相似的文本会生成相似的哈希签名,无需逐字逐句比较,只需对比短小的数字签名即可判断相似程度。

💻文章提供了Python代码示例,演示了Simhash算法的实现过程,包括分词、哈希、加权叠加和汉明距离计算,帮助读者理解算法的原理。

🔍Simhash算法在搜索引擎去重、垃圾邮件过滤、短文本相似度分析和抄袭检测等领域有广泛应用,展现了其高效和鲁棒性。

文本相似度识别的“利器”:揭秘 Simhash 算法及其应用

在信息爆炸的时代,我们每天都被海量的文本数据所包围:网页、新闻、论文、邮件,甚至社交媒体上的只言片语。如何在这些数据中快速找出相似或重复的内容?这不仅是搜索引擎、推荐系统面临的巨大挑战,也是我们有效管理信息、避免信息过载的关键。今天,我们就来揭秘一个强大的“利器”——Simhash 算法,它能将看似复杂的文本相似度计算,转化为高效的数字签名比较。

什么是 Simhash 算法?

想象一下,你有一张照片,你想知道另一张照片是不是它的“双胞胎”或者“近亲”。Simhash 算法就像是给每张照片拍一张“指纹”,而且这种指纹有个神奇的特性:如果两张照片很像,它们的指纹也会很像。

具体来说,Simhash 是一种局部敏感哈希(Locality Sensitive Hashing, LSH)算法的实现。它不再追求传统哈希算法那种“一点改动,结果大不同”的雪崩效应,而是恰恰相反:相似的输入文本会产生相似的哈希签名。这意味着,我们不需要逐字逐句地比较长篇大论,只需对比它们生成的一串短小的数字签名(通常是64位或128位),就能快速判断它们的相似程度。


Simhash 如何“压缩”文本指纹?

Simhash 算法的核心思想是将文本的特征(词语)通过哈希和加权聚合,最终生成一个固定长度的二进制签名。让我们用一个简化的过程来理解它:

    分词(Tokenization) :首先,把文本分解成一个个有意义的词语或短语。比如,“我爱北京天安门”会被分成“我”、“爱”、“北京”、“天安门”。

    词语哈希(Word Hashing) :给每个词语生成一个固定长度的二进制哈希值。这个哈希值代表了词语的“身份”。

    加权叠加(Weighted Summation) :初始化一个与最终 Simhash 签名长度相同的向量(比如64位全0的向量)。然后,遍历每个词语的哈希值:

      如果某个哈希位是1,就把这个词语的权重(通常越重要的词权重越大,但这里可以简化为1)加到向量对应位上。如果某个哈希位是0,就把这个词语的权重从向量对应位上减去。 经过所有词语的处理,这个向量会累积文本中所有词语的哈希信息和权重信息。

    生成 Simhash 签名(Signature Generation) :最后一步是“拍板定案”。遍历累加后的向量,如果向量的某个位大于0,最终的 Simhash 签名对应位就设为1;如果小于或等于0,就设为0。这样,一个精炼的二进制“指纹”就诞生了。


示例代码解析:从原理到实践

下面提供的 Python 代码很好地演示了 Simhash 的核心流程:

import jiebaimport hashlibdef get_tokens(text):    """    分词函数,这里使用jieba进行中文分词。    您可以根据需要替换为其他分词器或针对英文的分词方法。    """    return list(jieba.cut(text))def get_hash_value(word):    """    对词语进行哈希,生成固定长度的二进制串。    这里使用MD5哈希,并取其前64位作为示例。    """    # MD5生成的是128位的哈希值,我们取前64位    md5_hash = hashlib.md5(word.encode('utf-8')).hexdigest()    # 将十六进制转换为二进制,并确保至少有64位    binary_hash = bin(int(md5_hash, 16))[2:].zfill(128)    return binary_hash[:64# 取前64位def calculate_simhash(text):    """    计算给定文本的Simhash值。    """    tokens = get_tokens(text)    if not tokens:        return "0" * 64 # 空文本返回全0 Simhash    # 初始化一个64位的向量    v = [0] * 64    for token in tokens:        # 简化处理:这里不对词语进行加权,所有词语权重视为1        # 实际应用中,可以用TF-IDF等方法计算词语权重        weight = 1                token_hash = get_hash_value(token)        for i in range(64):            if token_hash[i] == '1':                v[i] += weight            else:                v[i] -= weight        # 生成最终的Simhash签名    simhash_bits = ['1' if x > 0 else '0' for x in v]    return "".join(simhash_bits)def hamming_distance(hash1, hash2):    """    计算两个Simhash值之间的汉明距离。    """    if len(hash1) != len(hash2):        raise ValueError("Simhash values must have the same length.")        distance = 0    for i in range(len(hash1)):        if hash1[i] != hash2[i]:            distance += 1    return distanceif __name__ == "__main__":    text1 = "请输入自己的数据"    text2 = "请输入自己的数据"    text3 = "世界卫生组织"    text4 = "世界组织"    simhash1 = calculate_simhash(text1)    simhash2 = calculate_simhash(text2)    print(f"文本1: '{text1}'")    print(f"Simhash1: {simhash1}")    print(f"文本2: '{text2}'")    print(f"Simhash2: {simhash2}")    print(f"Simhash1 vs Simhash2 (相似): {hamming_distance(simhash1, simhash2)}"# 应该很小    # 输出相似度    similarity = 1 - hamming_distance(simhash1, simhash2) / 64 # 64位Simhash    print(f"文本1和文本2的相似度: {similarity:.2f}"# 应该接近1

实验结果分析

我们通过一个实际案例来观察Simhash算法的表现:

测试文本1的Simhash1: 1000001110010001110011110000110000001000101000110100111111111000

测试文本2的Simhash2: 1011000100011001010111110010110000000000001000111110111111110000

汉明距离: 13
相似度: 0.80

结果分析

    两个文本的Simhash值有13位不同,这表明它们在语义上存在较小差异。相似度计算结果为0.80,这表明文本1和文本2在语义上有80%的相似性。

测试文本1的Simhash1: 1000001110010001110011110000110000001000101000110100111111111000

测试文本3的Simhash3: 0000000001010000000100101011010110110101010101011010001110010010

汉明距离: 38 相似度: 0.41

结果分析

    两个文本的Simhash值有38位不同,这表明它们在语义上存在较小差异。

    相似度计算结果为0.41,这表明文本1和文本2在语义上有41%的相似性。

    虽然两个文本在语义上差异巨大,但Simhash仍给出了41%的相似度

    这种现象揭示了Simhash算法的几个重要特性:

      对文本长度敏感:长文本包含更多词汇特征,容易与短文本产生部分匹配权重分配影响:当前实现对所有词语赋予相同权重,导致低频词稀释了核心语义哈希碰撞可能:短文本的哈希特征可能被长文本中的某些词汇特征覆盖

改进方向

// 改进的权重计算方式weight = jieba.analyse.tfidf(token, withWeight=True)[1if len(tokens)>10 else 0

测试文本3的Simhash3: 0000000001010000000100101011010110110101010101011010001110010010

测试文本4的Simhash4: 0100000010000110000100110000000010001000110010000000010010010000

汉明距离: 28
相似度: 0.56

结果分析

    两个文本的Simhash值有28位不同,这表明它们在语义上存在较小差异。相似度计算结果为0.56,这表明文本1和文本2在语义上有56%的相似性。

在尝试了 TF-IDF 后,发现效果并不理想,所以最终还是采用了简单的加权聚合方式。

代码分析


Simhash 的应用场景

Simhash 算法因其高效和鲁棒性,在许多领域都大放异彩:


总结

Simhash 算法提供了一种巧妙且高效的方式来衡量文本相似度。它将复杂的文本转化为简洁的数字签名,并通过简单的汉明距离计算,实现了在大规模数据中快速去重和查找相似内容的能力。

Fish AI Reader

Fish AI Reader

AI辅助创作,多种专业模板,深度分析,高质量内容生成。从观点提取到深度思考,FishAI为您提供全方位的创作支持。新版本引入自定义参数,让您的创作更加个性化和精准。

FishAI

FishAI

鱼阅,AI 时代的下一个智能信息助手,助你摆脱信息焦虑

联系邮箱 441953276@qq.com

相关标签

Simhash 文本相似度 算法 去重
相关文章