当前位置: 首页 > news >正文

学习笔记-相似度匹配改进2

1. 任务

由于上周找的方法不是开源的,所以本周的主要任务如下:找近1-2年的其他相似问题匹配方法开源方法,尝试是否可以运行。

2. 不足

关于《中华心法问答系统》中,对于相似度匹配使用的方法是:70%语义相似度+30%关键词增强。考虑以下几点需要改进的地方:

(1)关于权重问题:70%和30%过于死板了,是否有比较灵活的方式。(动态分配...)

(2)语义部分:当前使用最后4层CLS向量的加权平均可能丢失细粒度信息。(动态分配...)

                            当前Sigmoid校准(1/(1+exp(-25*(x-0.88))))可能过于激进。

(3)关键词部分:当前仅用Jieba分词后的词频匹配过于简单。(TF-IDF加权、BM25算法...)

(4)对于混合检索:除了语义和关键词,是否可以加上其他的(句法...)。

3. 改进方法

3.1 关于计算相似度的方法

计算相似度的方法,包括余弦相似度、欧式距离、点积相似度(若向量已归一化则等价于余弦相似度)等方法。对于语义相似度这一块,比较常用的的还是余弦相似度,且比较简单。

3.2 BM25混合检索方法

介绍:

BM25是用来进行关键词提取的。

BM25混合检索的步骤:

BM25提取有关文档(基于关键词),过滤无关关键词文档(例如从一百万中提取TOK-1000)→ 语义精排(计算余弦相似度)/语义+关键词(还是用BM25)精排。

对比:

关于上面的这个方法,对比原方法,主要提升在BM25比jieba对于关键词这一方面更加准确,而且对于百万级别的数据集,可以比较快的搜索出来(因为先经过BM25的粗排)。

但是对于本次的问答系统,并没有很大的数据集,且关键词的性能提升不在这一部分,对于BM25的实现也比较复杂,所以就不采用此方法。

3.3 相似度融合方法

3.3.1 动态权重学习(Dynamic Weighting)

动态权重学习是用来提升原方法里面语义最终的相似度采取的是:70%语义+30%关键词。这个固定的权重可能比较死板,可以根据一些下面的方法来动态的设置一些权重。

方法:

(1)根据查询长度的动态权重

逻辑:长文本更加依赖语义,短文本更加依赖关键词。

理解:

对于短文本来说,例如就一两个词,就可以依赖关键词直接匹配,语义分析容易过拟合。此时可以适当提高关键词的权重。例如:“实现欲望”,就两个关键词,就可以依赖关键词进行匹配。

对于长文本来说,可能会提取出特别多不是重点的关键词,此时就可以提高语义的权重。

(2)基于关键词匹配

(3)注意力机制加权

(4)神经网络融合器(Neural Reranker)

核心思想:用小型神经网络学习语义和关键词信号的最优组合。

训练数据:需标注样本(问题对,人工打分)。

3.4 句法

3.4.1 句法的了解

除了语义和关键词,或许可以再加上句法来进行提高相似度匹配。

  • 语义向量的局限:无法捕捉句子结构(如“猫追狗”和“狗追猫”的向量可能相似)。

  • 关键词的局限:忽略词序和语法关系(如“不喜欢的电影”和“电影不喜欢”关键词相同但含义相反)。

句法分析(Syntactic Analysis)是自然语言处理中的重要技术,用于分析句子的语法结构,揭示词语之间的依存关系。在这个系统里,句法分析可以帮助系统更好地理解问题结构,提高匹配准确率。

关于句法价值的思考:

句法是用于用于分析句子的语法结构,但是当两句话的意思相同,仅仅是语序的不同(例如被动句和主动句),那么他们用语义+关键词可以的到一个特别高的相似度,但是加入句法反而会降低相似度,这样做的意义在哪里?

上面的问题是当我们输入两个意思完全一样的句子时,但是当我们输入的句子是由相同词语组合表达完全不同意图时,句法可以解决语义和关键词无法处理的"结构歧义"。对于上面提到的两个完全一样意思的句子是,可以采取动态分配权重的方法。(例如当语义相似度特别大,而句法相似度比较小时,可以降低句法的权重,而提高语义的权重)

下面是当相同词语组合表达完全不同意图时的例子:

问题语义相似度关键词匹配句法分析关键特征
"领导激励员工是欲吗?"高(关键词全命中)激励(员工)作为核心动作,疑问指向"行为性质"
"员工想被领导激励是欲吗?"高(相同关键词)想(被激励)作为心理状态,疑问指向"心理动机"

下面是一些句法降低相似度的例子

示例1:处理同义不同结构的问题

问题A:"如何区分欲望和目标?"

  • 依存分析:区分(核心动词) -> 欲望(宾语1), 目标(宾语2)

问题B:"目标和欲望有什么不同?"

  • 依存分析:不同(核心形容词) -> 目标(主语), 欲望(比较对象)

虽然语义相似,但句法结构不同。通过句法分析可以识别这种差异,避免过度匹配。

过度匹配:防止系统将表面相似但实际询问重点不同的问题错误地匹配在一起。在您的例子中:

  • 问题A:"如何区分欲望和目标?" → 询问的是区分方法

  • 问题B:"目标和欲望有什么不同?" → 询问的是差异点

如果不做句法分析,仅靠关键词匹配("目标"+"欲望")可能会返回相同的答案,这就是"过度匹配"。

示例2:句法捕捉语义模型忽略的"功能词信号"

BERT的局限性:预训练模型对虚词(如疑问词、否定词)敏感度不足,但是句法分析会明确捕获。

(1)处理否定结构

问题:"不社交是否是欲?"

  • 依存分析:是(核心动词) -> 不社交(主语), 欲(宾语)

  • 特殊标记:否定词"不"修饰"社交"

这种否定结构通过句法分析可以准确捕捉,避免与肯定形式混淆。

(2)处理疑问结构

问题:"追求感官享乐是欲还是焦虑问题?"

  • 依存分析:是(核心动词) -> 追求感官享乐(主语), 欲(宾语1), 焦虑问题(宾语2)

  • 特殊标记:选择疑问"还是"

识别疑问结构有助于理解用户真实询问意图。

句法精准识别否定()、情态()、疑问()等功能词对句子意义的根本性改变,这些是纯语义模型容易弱化处理的特征。

句法还有一些其他的价值,例如增强对"长尾结构"的鲁棒性(识别到“比如”这一部分非核心成分)等,就不做介绍了。

关于句法相似度计算的主要方法:树编辑距离、匹配规则(提取核心句法模式(如“主语-动词-宾语”是否一致)。)

3.4.2 实现

工具:在这里选择哈工大开发的中文NLP工具包LTP,支持依存句法分析。

下面是在源代码里修改,验证句法。

1. 环境准备

(1)安装LTP

注意需要在虚拟环境里安装。

# 安装LTP Python SDK
pip install ltp# 下载LTP基础模型(约500MB)
wget http://39.96.43.154/ltp/v3.4.0/ltp_model.zip
unzip ltp_model.zip -d ./ltp_model

注意上面直接安装LTP Python SDK时,下载torch包时超时导致的安装失败。由于LTP依赖PyTorch,而PyTorch的包体积较大(216MB),在国内网络环境下容易下载失败。下面是解决方案。

# 设置清华镜像源加速
pip config set global.index-url https://pypi.tuna.tsinghua.edu.cn/simple# 安装huggingface-hub的完整依赖
pip install packaging pyyaml requests tqdm transformers# 分步安装(避免超时)
pip install torch==2.7.1 --index-url https://pypi.tuna.tsinghua.edu.cn/simple
pip install ltp --index-url https://pypi.tuna.tsinghua.edu.cn/simple# 1. 下载模型(约500MB)
(venv) wget http://39.96.43.154/ltp/v3.4.0/ltp_model.zip# 2. 解压到项目目录下的 ltp_model 文件夹
(venv) unzip ltp_model.zip -d ./ltp_model

2. 代码修改

(1)修改Config

class Config:# 原有配置保持不变...LTP_MODEL_DIR = "./ltp_model"  # 模型存储路径(可自定义)LTP_DEVICE = "cuda" if torch.cuda.is_available() else "cpu"  # 自动选择设备SYNTAX_WEIGHT = 0.2  # 句法相似度权重(建议0.2-0.4)

(2)修改QASystem

①添加初始化

class QASystem:def __init__(self, config: Config):# 原有初始化代码...# 新增LTP初始化from ltp import LTPself.ltp = LTP(path=config.LTP_MODEL_DIR)self.ltp.to(config.LTP_DEVICE)  # 分配到GPU/CPUself._prepare_syntax_features()  # 预处理句法特征

②句法特征预处理

def _prepare_syntax_features(self):"""预计算所有问题的句法特征"""questions = [q["cleaned_question"] for q in self.qa_pairs]# 批量处理(效率提升5倍+)outputs = self.ltp.pipeline(questions, tasks=["cws", "dep"],max_length=512  # 限制最大长度)# 存储核心特征self.dep_trees = outputs.dep  # 依存树列表self.core_verbs = [next((word for word, arc in zip(output.cws, output.dep) if arc.relation == "HED", None)for output in outputs]

③句法相似度计算

def _calculate_syntax_sim(self, query_dep, idx):"""计算查询与库中问题的句法相似度"""# 1. 核心动词匹配query_verb = next((word for word, arc in zip(query_dep.cws, query_dep.dep) if arc.relation == "HED", None)db_verb = self.core_verbs[idx]verb_sim = 1.0 if query_verb == db_verb else 0.3# 2. 依存关系匹配(优化版)def get_relations(tree):return {(arc.head, arc.relation, arc.tail) for arc in tree}rel_sim = len(get_relations(query_dep) & get_relations(self.dep_trees[idx])) / max(len(query_dep.dep), len(self.dep_trees[idx].dep))return 0.6 * verb_sim + 0.4 * rel_sim

④改造search

def search(self, query: str):# 原有语义和关键词计算...# ===== 新增句法分析 =====query_out = self.ltp.pipeline([cleaned_query], tasks=["dep"])syntax_sims = np.array([self._calculate_syntax_sim(query_out.dep[0], i)for i in range(len(self.qa_pairs))])# ===== 相似度融合 =====similarities = (0.6 * semantic_sim +    # 语义相似度0.1 * keyword_sim +     # 关键词相似度 0.3 * syntax_sims       # 句法相似度)# 后续排序和过滤逻辑保持不变...

但是由于上面的LTP模型一直下载不下来,好像是更新过后,之前的都不能用了,所以导致不能够验证句法的作用。

3.5 细节补充

(1)层次化相似度加权

问题:BERT不同维度可能携带不同级别的语义信息。
改进:将768维分为若干组(如128维一组),分别计算子空间相似度后加权融合。

公式:最终相似度 = 加权平均(子空间1相似度, 子空间2相似度, ...)

(2)PCA降维优化余弦相似度

问题:BERT生成的768维向量可能存在冗余信息(某些维度对区分语义无用)或噪声(随机波动),直接计算余弦相似度时,这些冗余维度会干扰结果。

PCA作用

  • 通过主成分分析(PCA)保留方差最大的前128维(核心特征),剔除次要维度。

  • 数学上:对向量矩阵进行奇异值分解(SVD),选取最大特征值对应的特征向量作为新基。

(3)动态Sigmoid校准相似度

问题:固定参数25*(x-0.88)的Sigmoid校准可能过拟合。(若数据分布偏移(如平均相似度变为0.7),原参数会失效。)

改进:根据当前查询与文档库的相似度分布动态调整Sigmoid:

  • mean_sim + 0.5*std_sim作为阈值,高于阈值的相似度被放大,低于的被抑制。

作用
  • 自适应数据分布

    • 若文档库相似度普遍较低(如均值0.6),自动降低阈值,避免所有分数被压缩到低值。

  • 增强区分度
    将相似度分布非线性映射到[0,1]区间,拉开相关与不相关文档的差距。

公式对比
原始校准动态校准
1 / (1 + exp(-25*(x-0.88)))1 / (1 + exp(-10*(x - (mean+0.5*std))))

(4)对比学习增强(Contrastive Learning)

问题:直接余弦相似度可能忽略困难负样本。
改进:在相似度计算后加入 对比损失微调

# 假设已有正样本对(vec1, vec2)和负样本对(vec1, vec_neg)
pos_sim = np.dot(vec1, vec2)
neg_sim = np.dot(vec1, vec_neg)# 对比损失(温度系数τ控制区分度)
tau = 0.05
contrastive_sim = np.exp(pos_sim / tau) / (np.exp(pos_sim / tau) + np.exp(neg_sim / tau))


4. 总结

本周主要是寻找了关于提高相似度匹配的方法,还有一些没有写进来。主要了解了一些基础的知识和方法,但是由于时间关系,没有仔细地了解背后地原理。经过一些筛选,决定目前先加入句法和动态权重部分。因为句法的工具模型没有下载成功,所以打算下次换一个工具实现;对于动态权重部分,这一部分的方法有特别多,但是不知道哪一个是比较适合这个系统的,所以打算再找找文献吧。如果这两个完成好了的话,就试一试一些细节,如语义相似度方面的。

http://www.dtcms.com/a/316830.html

相关文章:

  • 机器学习——随机森林
  • Python高级编程与实践:Python高级数据结构与编程技巧
  • 【C++】Stack and Queue and Functor
  • C++二级考试核心知识点【内附操作题真题及解析】
  • Juc高级篇:可见性,有序性,cas,不可变,设计模式
  • SpringMVC(一)
  • Design Compiler:布图规划探索(ICC)
  • 《失落王国》v1.2.8中文版,单人或联机冒险的低多边形迷宫寻宝游戏
  • Modbus tcp 批量写线圈状态
  • centos7上如何安装Mysql5.5数据库?
  • 跨域场景下的Iframe事件监听
  • 【机器学习深度学习】模型量化
  • OSPF作业
  • Linux 基础
  • vue3 计算方式
  • GPS信号捕获尝试(上)
  • 【android bluetooth 协议分析 01】【HCI 层介绍 30】【hci_event和le_meta_event如何上报到btu层】
  • 【三个数公因数】2022-10-7
  • MySQL CONV()函数
  • 永磁同步电机无速度算法--基于二自由度结构的反推观测器TSBO
  • JAVA学习笔记 自增与自减的使用-006
  • 哲学中的主体性:历史演进、理论范式与当代重构
  • 【Unity】背包系统 + 物品窗口管理系统(中)
  • RC和RR的区别
  • Pytorch实现婴儿哭声检测和识别
  • 【web自动化测试】实战
  • Coze Studio开源,企业用户多了一种选择,也需多几分考量
  • 如何通过 5 种方式将照片从 iPad 传输到电脑
  • 埋点技术进阶:如何构建高效的数据采集架构
  • 默认二级路由(React-Router 6)