You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

优化基于itertools.combinations的文本相似度比对脚本性能

性能优化方案

你的脚本核心瓶颈不是循环写法、也不是fuzz计算本身,是做了海量完全无效的O(n²)全量比对,12万条数据全量两两组合共72亿次遍历,哪怕循环体只写pass,Python解释器跑72亿次迭代本身就需要数分钟,靠换filter/map这类表层写法根本不可能解决问题,按以下优先级优化即可:

  • 第一优先级:按compare_string分桶,砍掉99.9%以上的无效遍历
    你的逻辑里只有compare_string相等的两个条目才需要后续比对,根本不需要生成全量两两组合。预处理阶段直接把所有条目按compare_string分到不同桶里,仅在桶内做两两比对,跨桶条目直接跳过。如果你的compare_string区分度正常,这一步就能把总遍历量从72亿降到几万到几十万级别,空循环的2分钟耗时会直接压缩到毫秒级。
  • 第二优先级:调整判断顺序,轻量过滤前置,最重的计算放最后
    把判断按执行成本从低到高排序,提前排除不满足条件的对,不要上来就跑重计算:
    1. 先判断文本长度差:fuzz.ratio基于编辑距离计算,两个文本长度差超过5%时,相似度不可能达到95;长度不相等时相似度不可能到100,这类情况直接跳过,不需要做后续判断
    2. 再判断token集合是否有交集,无交集直接跳过
    3. 最后才计算fuzz相似度,这是整个循环里最重的操作
  • 第三优先级:替换纯Python实现的fuzz库
    把你现在用的fuzzywuzzy换成RapidFuzz,接口100%兼容,底层是C++实现带SIMD指令优化,相同的fuzz.ratio计算速度是原版fuzzywuzzy的10~100倍,不需要额外安装Levenshtein依赖,替换成本为0。
  • 第四优先级:预处理阶段存好所有需要的字段,避免循环内重复计算
    提前把文本长度、token集合等字段在遍历dataframe的时候就算好存起来,不要在循环里反复调用len()、反复做对象属性/索引取值,减少单次循环的额外开销。

优化后参考代码

import itertools
from collections import defaultdict
from rapidfuzz import fuzz

# 预处理:按compare_string分桶,提前计算所有复用字段
bucket_map = defaultdict(list)
for t in dataframe.itertuples():
    text = t.text
    bucket_map[t.compare_string].append(
        (t.id, text, t.set, len(text))
    )

highly_similar = []
for bucket in bucket_map.values():
    # 单条目桶没有比对必要,直接跳过
    if len(bucket) < 2:
        continue
    for a, b in itertools.combinations(bucket, 2):
        a_id, a_text, a_tokens, a_len = a
        b_id, b_text, b_tokens, b_len = b

        # 1. 最轻量判断:长度差不满足要求直接跳过
        max_len = max(a_len, b_len)
        min_len = min(a_len, b_len)
        if (min_len / max_len) * 100 < 95:
            continue
        
        # 2. 次轻量判断:token无交集直接跳过
        if a_tokens.isdisjoint(b_tokens):
            continue

        # 3. 最后执行最重的相似度计算
        score = fuzz.ratio(a_text, b_text)
        if (score >= 95 and a_len >= 10) or score == 100:
            highly_similar.append([a_id, b_id, a_text, b_text, score])

补充说明

如果后续数据量上涨到百万级,可以再加MinHash+LSH局部敏感哈希做近邻预筛选,进一步缩小候选比对范围。针对你当前12万条数据的规模,做完上面几步优化后,总耗时可以从15分钟压缩到10秒以内。

你之前测试filter/map性能更差是正常现象:这类内置函数如果包裹的还是Python层面的判断逻辑,只会额外增加函数调用开销,不会带来速度提升,在总计算量没减少的前提下,换任何循环写法都没有实质作用。

内容的提问来源于stack exchange,提问作者Pedro Daumas

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.28 14:45:28