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

信息检索系统TFIDF得分计算效率低及运行报错问题咨询

信息检索TF-IDF系统问题修复与优化方案

1 现有bug修复

1.1 数组长度不匹配问题

该错误由两个低级错误共同触发:

  • 计算查询词IDF时传参错误:原代码中inverse_document_frequency(word, new_list)的第二个参数传入了当前查询的切词列表,而非全量摘要列表,部分不存在于全量摘要的词会触发逻辑异常
  • 查询词未做去重处理:过滤后的new_list保留了重复词,但vector_dict的key会自动去重,导致查询向量长度和字典key长度不一致,到第6个查询刚好触发长度校验失败
    修复代码:
for query in query_array:
    query_words = query.split(" ")
    # 先对查询词去重+过滤停用词和非字母字符
    new_list = list({word for word in query_words if word not in closed_class_stop_words and word.isalpha()})
    vector = []
    vector_dict = {}
    for word in new_list:
        tf = term_frequency(word, Counter(new_list))
        # 计算IDF传入全量摘要列表
        idf = inverse_document_frequency(word, abstract_word_list)
        tfidf = tf * idf
        vector.append(tfidf)
        vector_dict[word] = tfidf
    query_vectors.append(vector)
    query_dict.append(vector_dict)

1.2 排序结果异常问题

该问题完全由余弦相似度公式写错导致:
原代码cos = dot(query_vector, abstract_vector) / (np.sqrt(dot(query_vector, abstract_vector)) * np.sqrt(dot(query_vector, abstract_vector)))的分母两次使用了两个向量的点积,计算结果恒等于1,排序时只能默认按第二个字段(摘要索引)升序排列,所以呈现为原有数字顺序。
同时默认升序排序会把相关性最低的结果放在前面,需要改为降序。
修复代码:

for i in range(len(query_vectors)):
    rank = []
    query_vector = query_vectors[i]
    # 提前计算查询向量模长,避免重复计算
    q_norm = np.linalg.norm(query_vector)
    for j in range(len(all_vector_list[i])):
        abstract_vector = all_vector_list[i][j]
        a_norm = np.linalg.norm(abstract_vector)
        # 分母为0的边界处理
        if q_norm == 0 or a_norm ==0:
            cos = 0
        else:
            cos = np.dot(query_vector, abstract_vector) / (q_norm * a_norm)
        rank.append((cos, j))
    # 改为降序排序,相关性高的在前
    rank.sort(reverse=True)
    for k in range(len(rank)):
        print(i, rank[k][1])

2 运行效率优化方案

原有算法时间复杂度为O(查询数*查询词数*摘要总数),优化后可降至O(查询数*平均查询词数*平均词出现次数):

  • 提前构建倒排索引:存储每个词对应的摘要索引和该词在摘要中的TF-IDF值,不需要每次遍历全量摘要匹配查询词
  • 提前预计算所有摘要的向量模长,不需要每次查询重复计算
    优化核心逻辑示例:
# 提前构建倒排索引
inverted_index = {}
abs_norm_list = []
for abs_idx, tf_dict in enumerate(abstract_tf_dict):
    abs_vec = []
    for word, tf in tf_dict.items():
        tfidf = tf * abstract_idf_dict[word]
        abs_vec.append(tfidf)
        if word not in inverted_index:
            inverted_index[word] = []
        inverted_index[word].append((abs_idx, tfidf))
    # 预存摘要模长
    abs_norm_list.append(np.linalg.norm(abs_vec))

# 直接用倒排索引计算相似度,不需要生成全量摘要向量
for q_idx, q_dict in enumerate(query_dict):
    dot_product = np.zeros(len(abstract_word_list))
    q_vec = list(q_dict.values())
    q_norm = np.linalg.norm(q_vec)
    for word, q_tfidf in q_dict.items():
        if word in inverted_index:
            for abs_idx, a_tfidf in inverted_index[word]:
                dot_product[abs_idx] += q_tfidf * a_tfidf
    # 计算相似度并排序
    cos_sim = dot_product / (q_norm * np.array(abs_norm_list) + 1e-8) # 加极小值避免分母为0
    rank = sorted([(cos_sim[j], j) for j in range(len(abstract_word_list))], reverse=True)
    for k in range(len(rank)):
        print(q_idx, rank[k][1])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.25 22:06:06