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

基于Doc2vec的跨文档段落语义匹配及相似度百分比换算问题

基于Gensim Doc2Vec的语义相似文档/段落查找方案

参考实现代码

目标是从候选文档列表中匹配与目标段落语义最接近的内容,基于Gensim Doc2Vec的实现如下:

import os
import sys
import gensim
import smart_open
import random
from nltk.tokenize import word_tokenize
# 配置文件路径
test_data_dir =('C:\\Users\\hamza\\Desktop\\')
train_file = os.path.join(test_data_dir, 'read-me.txt')
target_file = os.path.join(test_data_dir, 'read-me2.txt')

def read_file(filename):
    try:
        with open(filename, 'r') as f:
            data = f.read()
        return data
    except IOError:
        print("Error opening or reading input file: ", filename)
        sys.exit()

def read_corpus(fname, tokens_only=False):
    with smart_open.open(fname, encoding="iso-8859-1") as f:
        for i, line in enumerate(f):
            tokens = gensim.utils.simple_preprocess(line)
            if tokens_only:
                yield tokens
            else:
                # 训练数据需要附加唯一标签,这里用行号作为标签
                yield gensim.models.doc2vec.TaggedDocument(tokens, [i])

train_data = list(read_corpus(train_file))
target_data = word_tokenize(read_file(target_file))

# 初始化并训练模型
model = gensim.models.doc2vec.Doc2Vec(vector_size=50, min_count=2, epochs=40)
model.build_vocab(train_data)
model.train(train_data, total_examples=model.corpus_count, epochs=model.epochs)

# 推理目标文本向量,计算相似度
inferred_vector = model.infer_vector(target_data)
sims = model.dv.most_similar([inferred_vector], topn=len(model.dv))
print(sims)

注:原代码缺少sys模块导入,上述代码已补全,避免运行时报错。

示例运行输出

[(1, 0.20419511198997498),
(2, 0.1924923211336136),
(0, 0.10696495324373245)]

核心问题解答

1. 目标数据与训练数据的匹配方法

现有代码已经实现了完整匹配逻辑,匹配结果的映射规则非常直接:

  • 训练阶段给read-me.txt的每一行都分配了从0开始的整数标签(行号),模型训练完成后会存储每个标签对应的段落向量
  • most_similar返回的元组第一个元素就是匹配到的段落标签,直接用标签索引train_data就能拿到对应的原始段落内容
  • 以上述输出为例,排名第一的结果标签为1,对应read-me.txt中第2行(行号从0开始计数)的内容,就是和目标文本语义最接近的候选段落。

如果要做文档级而非段落级匹配,只需要在读取语料时把整篇文档作为一个TaggedDocument单元,给每个文档分配唯一ID标签即可。

2. 相似程度的判定规则

Doc2Vec默认采用余弦相似度计算向量间的匹配程度,原始取值范围为[-1, 1]:

  • 数值越接近1,两段文本的语义相似度越高
  • 数值为0代表两段文本语义无关联
  • 数值为负代表两段文本语义倾向相反
    这个相似度是相对值而非绝对值,判定阈值需要结合自己的语料场景调整:通用场景下一般认为相似度高于0.6属于高度语义相关,0.3~0.6属于弱相关,低于0.3基本可以判定为不相关。当前输出的最高相似度仅0.2左右,通常是训练语料量过少、目标文本和候选语料重合度低导致的,可以通过扩充训练语料、调整模型参数优化效果。

3. 相似度缩放为百分比的可行方法

余弦相似度的取值范围包含负数,不能直接乘以100作为百分比,需要先做值域映射,把原始分数线性转换到[0,1]区间后再转百分比,参考实现如下:

def sim2percent(sim_score):
    # 将[-1,1]的余弦值线性映射到[0,1]区间
    scaled_score = (sim_score + 1) / 2
    return round(scaled_score * 100, 2)

# 批量转换相似度结果
percent_sims = [(doc_tag, sim2percent(score)) for doc_tag, score in sims]
print(percent_sims)

转换后当前的运行结果会输出:

[(1, 60.21), (2, 59.62), (0, 55.35)]

注意:转换后的百分比仅代表当前模型、当前候选集范围内的相对匹配程度,不是绝对语义重合度,不能跨模型、跨候选集直接对比数值高低。


内容的提问来源于stack exchange,提问作者Hamza Dabeer khan

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.28 05:39:19