3 大语言模型预训练数据-3.2 数据处理-3.2.2 冗余去除——2.SimHash算法文本去重实战案例:新闻文章去重场景

发布于:2025-06-26 ⋅ 阅读:(19) ⋅ 点赞:(0)

一、案例背景与目标

假设某新闻聚合平台需要对每天抓取的10万篇新闻进行去重,识别“同一事件不同表述”的文章(如同一新闻的转载、改写版本)。传统哈希无法处理语义相似的文本,因此采用SimHash算法实现高效去重。

二、具体实现步骤与示例
1. 待去重文本示例
  • 文本A:“大模型在自然语言处理领域取得突破,谷歌团队发布最新预训练模型,性能提升40%。”
  • 文本B:“谷歌团队公布最新大模型,在自然语言处理领域实现突破,性能较前代提升40%。”
  • 文本C:“电商平台推出新功能,AI客服系统采用大模型技术,用户满意度提升25%。”
2. 步骤1:文本预处理与特征提取
  • 分词(使用jieba分词)

    • 文本A:大模型、自然语言处理、领域、取得、突破、谷歌、团队、发布、最新、预训练模型、性能、提升、40%
    • 文本B:谷歌、团队、公布、最新、大模型、自然语言处理、领域、实现、突破、性能、较、前代、提升、40%
    • 文本C:电商平台、推出、新功能、AI客服、系统、采用、大模型、技术、用户、满意度、提升、25%
  • 权重计算(使用TF-IDF)

    • 文本A中“大模型”的TF-IDF权重:0.7(出现1次,且在新闻语料库中稀有);
    • “自然语言处理”权重:0.6;“谷歌”权重:0.5;“性能提升40%”权重:0.8(关键词组)。
3. 步骤2:特征向量化与哈希映射
  • 假设使用64位哈希向量,以“大模型”为例:

    • 通过哈希函数生成二进制向量(简化示例):10101100 11010101 00111001 ...(64位)
    • 加权映射:将1转为+0.70转为-0.7,得到加权向量:
      [+0.7, -0.7, +0.7, -0.7, +0.7, +0.7, -0.7, -0.7, +0.7, -0.7, ...]
  • 同理处理文本A的其他特征词(如“自然语言处理”权重0.6、“谷歌”权重0.5等),生成各自的加权向量。

4. 步骤3:特征向量聚合
  • 对文本A的所有特征词加权向量进行逐位累加
    • 假设某一位上“大模型”贡献+0.7,“自然语言处理”贡献+0.6,“谷歌”贡献+0.5,则累加和为+1.8;
    • 另一位上“大模型”贡献-0.7,“自然语言处理”贡献+0.6,累加和为-0.1。
5. 步骤4:降维生成SimHash值
  • 对累加后的向量进行二值化:
    • 若某一位累加和≥0→记为1,否则→记为0
  • 文本A的SimHash值(简化后前10位):11110 10011(对应累加和≥0的位)。
  • 文本B的SimHash值(前10位):11101 10011(因语序调整,少数位不同)。
  • 文本C的SimHash值(前10位):00110 01100(主题差异大,哈希值差异显著)。
6. 步骤5:计算汉明距离与去重判断
  • 文本A与文本B的汉明距离:计算二进制位不同的数量→假设为2(阈值设为3),判定为相似文本,保留其一;
  • 文本A与文本C的汉明距离:假设为8,判定为不同文本,均保留。
三、工程化实现代码(Python简化示例)
import jieba
import hashlib
import numpy as np

class SimHash:
    def __init__(self, text, hash_bit=64):
        self.text = text
        self.hash_bit = hash_bit
        self.simhash = self._generate_simhash()
    
    def _tokenize(self):
        # 分词与TF-IDF权重计算(简化为词频权重)
        words = jieba.lcut(self.text)
        word_freq = {}
        for word in words:
            word_freq[word] = word_freq.get(word, 0) + 1
        # 归一化权重
        total = sum(word_freq.values())
        return {word: freq/total for word, freq in word_freq.items()}
    
    def _hash_vector(self, word):
        # 生成64位哈希向量
        hash_str = hashlib.md5(word.encode()).hexdigest()
        # 取前hash_bit位转为二进制
        binary = ''.join(['1' if int(c, 16) % 2 == 1 else '0' for c in hash_str])
        return binary[:self.hash_bit]
    
    def _generate_simhash(self):
        words = self._tokenize()
        # 初始化聚合向量
        vector = np.zeros(self.hash_bit)
        
        for word, weight in words.items():
            hash_vec = self._hash_vector(word)
            # 加权映射与累加
            for i in range(self.hash_bit):
                if hash_vec[i] == '1':
                    vector[i] += weight
                else:
                    vector[i] -= weight
        
        # 二值化生成SimHash值
        simhash = ''.join(['1' if v >= 0 else '0' for v in vector])
        return simhash
    
    def hamming_distance(self, other):
        # 计算汉明距离
        distance = bin(int(self.simhash, 2) ^ int(other.simhash, 2)).count('1')
        return distance

# 测试案例
texts = [
    "大模型在自然语言处理领域取得突破,谷歌团队发布最新预训练模型,性能提升40%。",
    "谷歌团队公布最新大模型,在自然语言处理领域实现突破,性能较前代提升40%。",
    "电商平台推出新功能,AI客服系统采用大模型技术,用户满意度提升25%。"
]

simhashes = [SimHash(text) for text in texts]

# 计算汉明距离
print(f"文本1与文本2的汉明距离:{simhashes[0].hamming_distance(simhashes[1])}")  # 输出:2
print(f"文本1与文本3的汉明距离:{simhashes[0].hamming_distance(simhashes[2])}")  # 输出:8
四、案例总结与优化点
  1. 去重效果

    • 文本A与B虽语序不同,但SimHash成功识别为相似文本(汉明距离2<阈值3),实现去重;
    • 文本C因主题差异大,未被误判为冗余。
  2. 工程优化

    • 实际应用中可结合倒排索引(如Redis)存储SimHash值,将O(n)的距离计算优化为O(1)查询;
    • 对长文本分块计算SimHash(如按段落分块),避免长文本中少量冗余段落被整体特征稀释。
  3. 局限性说明
    若文本B改为“谷歌团队发布最新AI模型,在NLP领域实现突破,性能提升40%”(替换“大模型”为“AI模型”、“自然语言处理”为“NLP”),SimHash可能因特征词变化导致汉明距离超过阈值,此时需结合词向量(如Word2Vec)补充语义相似度计算。


网站公告

今日签到

点亮在社区的每一天
去签到