【NLP 30、文本匹配任务 —— 传统机器学习算法】
目录
一、文本匹配任务的定义
1.狭义解释
2.广义解释
二、文本匹配的应用
1.问答对话
2.信息检索
3.文本匹配任务应用
三、智能问答
1.智能问答的基本思路
依照基础资源划分:
依照答案产出方式划分
依照NLP相关技术划分
四、智能问答的价值
1.智能客服
2.Faq知识库问答
总结
3.相关名词
① 问答对
② faq库 / 知识库
③ 标准问
④ 相似问/扩展问
⑤ 用户问
⑥ 知识加工
4.Faq知识库示例
5.运行逻辑
6.算法核心
五、文本匹配算法Ⅰ —— 编辑距离
🚀 代码实现
思路与算法
1.初始化矩阵:
2.填充矩阵:
3.计算相似度:
优缺分析
优点:
缺点:
六、文本匹配算法 Ⅱ —— Jaccard相似度
代码实现
优缺分析
优点:
缺点:
适用场景:
七、文本匹配算法 Ⅲ —— BM25算法
TF·IDF算法
BM25算法
词的重要性(IDF)
词与文档的相关性(TF)
词与查询的相关性(可选)
参数设置
优缺分析
优点:
缺点:
代码实现
Ⅰ、超参数定义
Ⅱ、初始化方法
Ⅲ、根据语料库构建倒排索引并计算每个词的IDF值
Ⅳ、计算文档集合中平均每篇文档的词数
Ⅴ、计算查询query 与 某篇文档的相关性得分
Ⅵ、计算查询与所有文档的相关性得分
Ⅶ、完整的BM25算法实现
八、文本匹配算法 Ⅳ —— word2vec
1.什么是向量
2.什么是词向量
3.词向量的特点
4.词向量是如何寻得到的
5.如何训练/训练目标
6.训练提速技巧
7.如何用于文本匹配
8.优缺分析
优点:
缺点:
后来时间平静又强大,替我揭穿和筛选
—— 25.1.29
一、文本匹配任务的定义
1.狭义解释
给定一组文本,判断其语义是否相似
相似的:今天天气不错 match 今儿个天不错呀
非相似:今天天气不错 match 你的代码有BUG
以分值形式给出相似度
今天天气不错 match 今儿个天不错呀 0.9
今天天气不错 match 这几天天气不错 0.7
今天天气不错 match 你的代码有bug 0.1
2.广义解释
给定一组文本,计算某种自定义的关联度
① Natural Language Inference 自然语言推理
两句话判断是否有关联、矛盾、中立关系
eg:明天要下雨 vs 明天大晴天
② Text Entailment 文本内容
给出一段文本,和一个假设,判断文本是否能支持或反驳这个假设
主题判断、文章标题匹配内容等
二、文本匹配的应用
1.问答对话
智能客服、车载导航、手机助手、聊天机器人、智能音箱

2.信息检索
各种 APP / 网页 的搜索功能

3.文本匹配任务应用
短文本 vs 短文本:知识库问答 ,聊天机器人等
短文本 vs 长文本:文章检索,广告推荐等
长文本 vs 长文本:新闻、文章的关联推荐等
三、智能问答
1.智能问答的基本思路
① 基础资源:包括faq库,书籍文档,网页,知识图谱等等
② 问答系统:对基础资源进行了加工处理,形成问答所需要的索引和模型等
③ 用户输入问题
④ 回答系统给出答案

依照基础资源划分:
1)基于faq(热点问题)知识库的问答【以文本匹配方式为主】
2)基于文档 / 网页 / 书籍的问答【大模型RAG的方式进行问答】
3)基于图像/视频的问答【基于多模态模型的问答】
4)基于知识图谱的问答
5)基于表格的问答
6)基于特定领域知识的问答
7)基于人工规则的问答 …
依照答案产出方式划分
1)检索式的回答
答案原文或答案的多个片段存在于基础资源中(答案是事先准备好的)
2)生成式的问答
答案文本不存在于基础资源,由问答系统来生成答案(由系统模型生成)
3)二者结合
依照NLP相关技术划分
1)单轮问答(一问一答)
2)多轮问答(关联多轮问答信息)
3)多语种问答(多种语言)
4)事实性问答(明确存在唯一正确的答案,用检索式方式回答较多)
5)开放性问答(有不同的看法,用生成式方式回答较多)
6)多模态问答(与图像、视频相结合)
7)选择型问答(在几个答案中选取一个)
8)抽取式问答
9)生成式问答
……
四、智能问答的价值
1.智能客服
人工客服的局限:① 响应慢 ② 服务时间有限 ③ 业务知识有限 ④ 流动性大,培训新人成本高 ⑤ 离职了就带走了业务回答经验 ⑥ 回复内容不一样,容易造成矛盾
智能客服的优势:① 毫秒级响应② 全年24小时在线 ③ 精通所有业务知识 ④ 只需培养管理员 ⑤ 保存所有业务回答数据 ⑥ 回复内容标准

2.Faq知识库问答
Faq = Frequently asked Questions:常见问题 / 热点问题
智能客服通常做一些 Faq 的问答

总结
Faq知识库问答:列表展示所有常见问题,用户需要自己找到对应的问题,对用户不友好
希望的改进:让用户以自然语言描述自己的问题,算法进行 Faq 库的检索,给出对应的答案
3.相关名词
① 问答对
一个(或多个相似的)问题与它对应的答案
② faq库 / 知识库
很多问答对组成的集合
③ 标准问
每组问答对中的问题有多个时,选一对为其中代表
④ 相似问/扩展问
一组问答对中,标准问之外的其他问题,对标准问的扩充
⑤ 用户问
用户真正输入的问题,而不是事先准备的
⑥ 知识加工
人工编辑 faq 库的过程
4.Faq知识库示例


5.运行逻辑
① 对用户问题进行预处理:分词、去停用词、去标点、大小写转换、全半角转换,按需处理
② 使用处理后的问题,与faq库中的问题计算相似度
③ 按照相似度分值排序
④ 返回最相似问题对应的答案

6.算法核心
语义相似度计算 是 faq 问答的核心
一般简称文本匹配 f(x,y) —> Score
相似度分值合理,才可以找到正确的对应问题
计算分值的同时,也要考虑速度

思考:可不可以不通过相似度计算,匹将用户问题配知识库中最相似的问题,再通过知识库中的问题匹配对应的答案,而是直接训练一个模型,匹配用户问题与知识库中答案之间的相似度
事实上,在实际场景中,答案的格式不是固定的,如果直接匹配,如果和知识库中的问题匹配,则问题对应的答案可以是多样、多种渠道的,如果直接用问题与答案匹配,则只需要一个计算文本相似度之间的模型即可
五、文本匹配算法Ⅰ —— 编辑距离
编辑距离:两个字符串之间,由一个转成另一个所需的最少编辑操作次数
许可的编辑操作(替换、插入、删除)包括将一个字符替换成另一个字符,插入一个字符,删除一个字符
例:
相似度计算公式:![]()
ED:编辑距离 L:字符串长度
1 - 两个字符串之间替换、插入、删除的编辑操作次数 / 两字符串的最大长度,得到两个字符串的相似度
两个字符串完全一致:编辑距离 = 0,相似度 = 1
两个字符串完全不一致:编辑距离 = 较长者长度,相似度 = 0
🚀 代码实现
思路与算法
1.初始化矩阵:
1.matrix 是一个二维数组,大小为 (len(string1) + 1) x (len(string2) + 1)
2.第一行和第一列分别初始化为 0 到 len(string1) 和 0 到 len(string2),表示从一个空字符串转换到目标字符串所需的操作次数
2.填充矩阵:
对于每个字符 string1[i - 1] 和 string2[j - 1],如果它们相等,则 d=0,否则 d=1。
matrix[i][j] 的值通过以下公式计算:
matrix[i][j] = min(matrix[i−1][j] + 1, matrix[i][j−1] + 1,matrix[i−1][j−1] + d)
其中,
matrix[i - 1][j - 1] + d 表示 替换操作(如果字符不同,则 d=1)
matrix[i][j - 1] + 1表示插入操作
matrix[i - 1][j] + 1表示删除操作
3.计算相似度:
编辑距离为: matrix[len(string1)][len(string2)]。
相似度为:
,表示两个字符串的相似程度,值越接近 1 表示越相似
np.zeros():用于创建一个指定形状和数据类型的全零数组。
| 参数名 | 类型 | 说明 |
|---|---|---|
shape | int 或 tuple | 数组的形状,可以是一个整数或表示形状的元组。 |
dtype | dtype, 可选 | 数组的数据类型,默认为 float64。 |
order | {'C', 'F'}, 可选 | 数组元素在内存中的排列顺序,'C' 表示按行排列,'F' 表示按列排列。 |
range():生成一个不可变的整数序列,常用于循环控制。
| 参数名 | 类型 | 说明 |
|---|---|---|
start | int, 可选 | 序列的起始值,默认为 0。 |
stop | int | 序列的结束值(不包含)。 |
step | int, 可选 | 步长,默认为 1。 |
len():返回对象的长度(如字符串、列表、元组等)。
| 参数名 | 类型 | 说明 |
|---|---|---|
obj | object | 需要计算长度的对象。 |
min():返回一组数据中的最小值。
| 参数名 | 类型 | 说明 |
|---|---|---|
iterable | iterable | 可迭代对象(如列表、元组等)。 |
*args | 可选 | 多个单独的参数,用于比较。 |
key | function, 可选 | 用于指定比较规则的函数。 |
default | object, 可选 | 当可迭代对象为空时返回的默认值。 |
max():返回一组数据中的最大值。
| 参数名 | 类型 | 说明 |
|---|---|---|
iterable | iterable | 可迭代对象(如列表、元组等)。 |
*args | 可选 | 多个单独的参数,用于比较。 |
key | function, 可选 | 用于指定比较规则的函数。 |
default | object, 可选 | 当可迭代对象为空时返回的默认值。 |
#编辑距离
def editing_distance(string1, string2):matrix = np.zeros((len(string1) + 1, len(string2) + 1))for i in range(len(string1) + 1):matrix[i][0] = ifor j in range(len(string2) + 1):matrix[0][j] = jfor i in range(1, len(string1) + 1):for j in range(1, len(string2) + 1):if string1[i - 1] == string2[j - 1]:d = 0else:d = 1matrix[i][j] = min(matrix[i - 1][j] + 1, matrix[i][j - 1] + 1, matrix[i - 1][j - 1] + d)edit_distance = matrix[len(string1)][len(string2)]return 1 - edit_distance / max(len(string1), len(string2))
优缺分析
优点:
① 可解释性强
② 跨语种(甚至对于非语言序列)有效
③ 不需要训练模型
缺点:
① 字符之间没有语义相似度 eg:str1 = “我没钱”,str2 = "俺没钱",相似度得分:0.66(1 - 1 / 3)
② 受无关词/停用词影响大 eg:str1 = “我要办卡”,str2 = “你好我需要办一张卡”,相似度得分:0.44(1 - 5 / 9)
③ 受语序影响大 eg:str1 = “今天天气不错”,str2 = “天气不错今天”,相似度得分:0.33(1 - 4 / 6)
④ 文本长度对速度影响很大(算法实现中两层for循环速度基于文本长度)
六、文本匹配算法 Ⅱ —— Jaccard相似度
通用表述:根据两个集合中,不同元素所占的比例,来衡量两个样本之间的相似度
用于文本匹配:根据两个文本中,不同的字或词所占的比例,来衡量两个文本之间的相似度
相似度计算公式:

例:str1 = “今天天气真不错”,str2 = “估计明天天气更好”,公共字:天、气
A ∩ B:2(天、气)、A ∪ B:11(今、天、气、真、不、错、估、计、明、更、好)
Jaccard相似度:2 / 11 = 0.18
如果输入字符串,则得到基于字的 jaccard相似度;
如果输入词的列表,则得到基于词的 jaccard相似度;
具体用基于词 还是 用基于字的jaccrad相似度,看场景决定:① 分词是否准确;② 是否有很多类似名词、缩略词;③ 文本长度等因素,都会影响选择
代码实现
set(): Python 中的一个内置函数,用于创建一个无序且不重复的元素集合。它可以将可迭代对象(如字符串、列表、元组等)转换为集合,并自动去除重复元素
| 参数 | 描述 |
|---|---|
iterable | 可选参数,表示一个可迭代对象(如列表、元组、字符串等)。如果不提供此参数,则返回一个空集合。 |
len():返回对象的长度(如字符串、列表、元组等)。
| 参数名 | 类型 | 说明 |
|---|---|---|
obj | object | 需要计算长度的对象。 |
#jaccard距离
def jaccard_distance(string1, string2):words1 = set(string1)words2 = set(string2)distance = len(words1 & words2) / len(words1 | words2)return distance
优缺分析
优点:
① 语序不影响分数(词袋模型)eg:今天天气不错 / 天气不错今天
② 实现简单,速度很快
③ 可跨语种,无需训练等
缺点:
① 语序不影响分数 eg:他打了我 / 我打了他
② 字符之间没有相似度衡量:同编辑距离
③ 受无关词影响
④ 非一致文本可能出现满分 eg:他是不知道 他不是不知道
适用场景:
文本越长,语序对于准确率的影响越低,语序越不重要,更加适合Jaccard距离算法
文本短的话,Jaccard算法缺点会被放大,优点被缩小
七、文本匹配算法 Ⅲ —— BM25算法
常用在搜索引擎框架中,用来做文档和搜索问题的匹配。同样也可以用在问答中,做文本匹配。
核心思想:假如一个词在某类文本(假设为A类)中出现次数很多,而在其他类别文本(非A类)出现很少,那么这个词是A类文本的重要词(高权重词);反之,如果一个词在出现在很多领域,则其对于任意类别的重要性都很差。
BM25算法的基础是:TF · IDF算法
TF·IDF算法
TF:词频,代表这个词在某个类别文本中出现的频率,某个词在某个类别中出现的次数 / 该类别词的总数
公式:某个词在某个类别中出现的次数 / 该类别词的总数
IDF:逆文档频率,代表这个词在其他文本中出现的频率,N代表文本总数,dfi代表包含词qi的文本的总数
公式:IDF(qi) = log[(N - df_i + 0.5) / (df_i + 0.5)]
N:文档集合中的总文档数 df_i:包含词项q_i的文档数
逆文档频率IDF高 ——> 该词很少出现在其他文档
BM25算法
BM25是对TF·IDF的一种改进,优化其表示效果
公式:
词的重要性(IDF)
公式:
其中,N 是文档总数,df_i 是包含词 q_i 的文档数,IDF 值越高,表示该词在文档集合中越稀有,重要性越大
词与文档的相关性(TF)
BM25对词频(TF)进行了优化,引入了饱和函数S(q_i, d),避免词频过高时权重过大。
公式: 
TF(qi, D):词 qi 在文档 D 中的词频
K:一个与文档长度相关的参数,
公式:
L_d:文档 D 的长度,L_ave:所有文档的平均长度,k_1,b:可学习参数
对词频进行调整,考虑了文档长度对词频的影响。较长的文档会受到惩罚,以避免偏向长文档
词与查询的相关性(可选)
当查询较长时,BM25还会考虑词在查询中的频率
公式:
TF(qi, Q):词qi在查询Q中的词频,k_3:可学习参数。
参数设置
k_1:控制词频的重要性,通常取值为 1.2。
b:控制文档长度的影响,通常取值为 0.75。
k_3:控制查询中词频的影响,通常取值为 1.2。
这些参数和改动的意义在于控制文本长度对分值的影响
优缺分析
优点:
① 通过使用TF·IDF弱化了无关词的影响,强化了重要词的影响,使得效果大幅提升
② 统计模型计算快(时间消耗主要是分词),不需要多轮迭代
③ 词袋模型(双刃剑)、跨语种等
缺点:
① 依然没有考虑词与词之间的相似性(字符之间没有相似度衡量)
② 需要一定量的训练(统计)样本(faq库本身)
③ 对于新增类别,需要重新计算统计模型
④ 分值不是一个总在0,1之间的数
代码实现
Ⅰ、超参数定义
ESPION:处理逆文档频率(IDF)计算中可能出现的负值的参数,确保IDF值始终为正,从而避免算法在计算相关性得分时出现异常。
PARAM_K1:超参数K_1,默认值为1.5,控制词频饱和度的上升速度。值越大,词频对得分的影响越大
PARAM_B:超参数B,默认值为0.6,控制文档长度归一化的影响。值越大,文档长度对得分的影响越大
typing:用于类型注解的库
import json
import math
import os
import pickle
import sys
from typing import Dict, Listclass BM25:EPSILON = 0.25PARAM_K1 = 1.5 # BM25算法中超参数PARAM_B = 0.6 # BM25算法中超参数
Ⅱ、初始化方法
def __init__(self, corpus: Dict):"""初始化BM25模型:param corpus: 文档集, 文档集合应该是字典形式,key为文档的唯一标识,val对应其文本内容,文本内容需要分词成列表"""self.corpus_size = 0 # 文档数量self.wordNumsOfAllDoc = 0 # 用于计算文档集合中平均每篇文档的词数 -> wordNumsOfAllDoc / corpus_sizeself.doc_freqs = {} # 记录每篇文档中查询词的词频self.idf = {} # 记录查询词的 IDFself.doc_len = {} # 记录每篇文档的单词数self.docContainedWord = {} # 包含单词 word 的文档集合self._initialize(corpus)
Ⅲ、根据语料库构建倒排索引并计算每个词的IDF值
len():返回对象的长度或元素个数。
| 参数名 | 类型 | 描述 |
|---|---|---|
obj | 对象 | 要计算长度的对象,如字符串、列表、元组、字典等。 |
set():创建一个无序且不重复元素的集合。
| 参数名 | 类型 | 描述 |
|---|---|---|
iterable | 可迭代对象(如列表、元组等) | 可选参数,用于创建集合。如果未提供,则创建一个空集合。 |
集合.add():向集合中添加一个元素。如果元素已存在,则不会重复添加。
| 参数名 | 类型 | 描述 |
|---|---|---|
element | 任意类型 | 要添加到集合中的元素。如果元素已存在,则不会重复添加。 |
float():将字符串或数字转换为浮点数。
| 参数名 | 类型 | 描述 |
|---|---|---|
x | 字符串或数字 | 要转换为浮点数的字符串或数字。如果未提供参数,则返回0.0。 |
字典.keys():返回字典中所有键的视图对象。
math.log():计算自然对数(以e为底的对数)。可以指定第二个参数作为对数的底数。
| 参数名 | 类型 | 描述 |
|---|---|---|
x | 数字 | 要计算对数的数值。 |
base | 数字 | 可选参数,指定对数的底数。默认为自然对数(以e为底)。 |
列表.append():在列表末尾添加一个元素。
| 参数名 | 类型 | 描述 |
|---|---|---|
object | 任意类型 | 要添加到列表末尾的元素。 |
float():将字符串或数字转换为浮点数。
| 参数名 | 类型 | 描述 |
|---|---|---|
x | 字符串或数字 | 要转换为浮点数的字符串或数字。如果未提供参数,则返回0.0。 |
公式:
,N是文档总数,n(q_i)是包含词q_i的文档数
def _initialize(self, corpus: Dict):"""根据语料库构建倒排索引"""# nd = {} # word -> number of documents containing the wordfor index, document in corpus.items():self.corpus_size += 1self.doc_len[index] = len(document) # 文档的单词数self.wordNumsOfAllDoc += len(document)frequencies = {} # 一篇文档中单词出现的频率for word in document:if word not in frequencies:frequencies[word] = 0frequencies[word] += 1self.doc_freqs[index] = frequencies# 构建词到文档的倒排索引,将包含单词的和文档和包含关系进行反向映射for word in frequencies.keys():if word not in self.docContainedWord:self.docContainedWord[word] = set()self.docContainedWord[word].add(index)# 计算 idfidf_sum = 0 # collect idf sum to calculate an average idf for epsilon valuenegative_idfs = []for word in self.docContainedWord.keys():doc_nums_contained_word = len(self.docContainedWord[word])idf = math.log(self.corpus_size - doc_nums_contained_word +0.5) - math.log(doc_nums_contained_word + 0.5)self.idf[word] = idfidf_sum += idfif idf < 0:negative_idfs.append(word)average_idf = float(idf_sum) / len(self.idf)eps = BM25.EPSILON * average_idffor word in negative_idfs:self.idf[word] = eps
Ⅳ、计算文档集合中平均每篇文档的词数
@property: Python 中的一个内置装饰器,用于将类的方法转换为属性,使得可以像访问普通属性一样访问这些方法。它主要用于封装类的属性,提供更简洁和直观的接口,同时允许在访问或修改属性时执行额外的逻辑,如数据验证或计算。
float():将字符串或数字转换为浮点数。
| 参数名 | 类型 | 描述 |
|---|---|---|
x | 字符串或数字 | 要转换为浮点数的字符串或数字。如果未提供参数,则返回0.0。 |
@propertydef avgdl(self):return float(self.wordNumsOfAllDoc) / self.corpus_size
Ⅴ、计算查询query 与 某篇文档的相关性得分
公式:![]()
其中,f(qi, D) 是词 qi 在文档D中的词频,∣D∣是文档D的长度,avgdl 是文档集合的平均长度。
self.avgdl:文档集合中平均每篇文档的词数
def get_score(self, query: List, doc_index):k1 = BM25.PARAM_K1b = BM25.PARAM_Bscore = 0doc_freqs = self.doc_freqs[doc_index]for word in query:if word not in doc_freqs:continuescore += self.idf[word] * doc_freqs[word] * (k1 + 1) / (doc_freqs[word] + k1 * (1 - b + b * self.doc_len[doc_index] / self.avgdl))return [doc_index, score]
Ⅵ、计算查询与所有文档的相关性得分
遍历返回一个包含文档索引和得分的列表
列表推导式(List Comprehension)是 Python 中一种简洁且高效的方式来创建列表。它允许你在一行代码中从现有的可迭代对象(如列表、元组、字符串等)生成新的列表。列表推导式的基本语法如下:
new_list = [expression for item in iterable if condition]
expression是对item的操作或表达式,用于定义新列表中的每个元素。item是可迭代对象中的每个元素。iterable是包含要迭代的元素的可迭代对象。condition是一个可选的条件,用于筛选要包含在新列表中的元素。
字典.keys():返回字典中所有键的视图对象。
def get_scores(self, query):scores = [self.get_score(query, index) for index in self.doc_len.keys()]return scores
Ⅶ、完整的BM25算法实现
import json
import math
import os
import pickle
import sys
from typing import Dict, Listclass BM25:EPSILON = 0.25PARAM_K1 = 1.5 # BM25算法中超参数PARAM_B = 0.6 # BM25算法中超参数def __init__(self, corpus: Dict):"""初始化BM25模型:param corpus: 文档集, 文档集合应该是字典形式,key为文档的唯一标识,val对应其文本内容,文本内容需要分词成列表"""self.corpus_size = 0 # 文档数量self.wordNumsOfAllDoc = 0 # 用于计算文档集合中平均每篇文档的词数 -> wordNumsOfAllDoc / corpus_sizeself.doc_freqs = {} # 记录每篇文档中查询词的词频self.idf = {} # 记录查询词的 IDFself.doc_len = {} # 记录每篇文档的单词数self.docContainedWord = {} # 包含单词 word 的文档集合self._initialize(corpus)def _initialize(self, corpus: Dict):"""根据语料库构建倒排索引"""# nd = {} # word -> number of documents containing the wordfor index, document in corpus.items():self.corpus_size += 1self.doc_len[index] = len(document) # 文档的单词数self.wordNumsOfAllDoc += len(document)frequencies = {} # 一篇文档中单词出现的频率for word in document:if word not in frequencies:frequencies[word] = 0frequencies[word] += 1self.doc_freqs[index] = frequencies# 构建词到文档的倒排索引,将包含单词的和文档和包含关系进行反向映射for word in frequencies.keys():if word not in self.docContainedWord:self.docContainedWord[word] = set()self.docContainedWord[word].add(index)# 计算 idfidf_sum = 0 # collect idf sum to calculate an average idf for epsilon valuenegative_idfs = []for word in self.docContainedWord.keys():doc_nums_contained_word = len(self.docContainedWord[word])idf = math.log(self.corpus_size - doc_nums_contained_word +0.5) - math.log(doc_nums_contained_word + 0.5)self.idf[word] = idfidf_sum += idfif idf < 0:negative_idfs.append(word)average_idf = float(idf_sum) / len(self.idf)eps = BM25.EPSILON * average_idffor word in negative_idfs:self.idf[word] = eps@propertydef avgdl(self):return float(self.wordNumsOfAllDoc) / self.corpus_sizedef get_score(self, query: List, doc_index):"""计算查询 q 和文档 d 的相关性分数:param query: 查询词列表:param doc_index: 为语料库中某篇文档对应的索引"""k1 = BM25.PARAM_K1b = BM25.PARAM_Bscore = 0doc_freqs = self.doc_freqs[doc_index]for word in query:if word not in doc_freqs:continuescore += self.idf[word] * doc_freqs[word] * (k1 + 1) / (doc_freqs[word] + k1 * (1 - b + b * self.doc_len[doc_index] / self.avgdl))return [doc_index, score]def get_scores(self, query):scores = [self.get_score(query, index) for index in self.doc_len.keys()]return scores
八、文本匹配算法 Ⅳ —— word2vec
1.什么是向量
指在坐标系(空间)内具有大小和方向的量
2维向量 [0.1, 2.9] 5维向量 [3, 1, 4, 2, 5]
2.什么是词向量
将每个词或字转换成同一向量空间内的一个向量
3.词向量的特点
两个词如果语义相近,则在空间中的向量接近
4.词向量是如何寻得到的
随机初始化,之后通过文本语料进行训练调整
5.如何训练/训练目标
① 基于窗口
② 基于语言模型
③ 基于共现矩阵

6.训练提速技巧
① 层次softmax/Huffman树
② 负采样
7.如何用于文本匹配
将文本中的所有词的词向量相加取平均
文本 ——> 句向量
公式:![]()
句向量维度 = 词向量维度,不论文本长度
文本相似度 = 向量相似度 = 向量夹角余弦值
向量夹角为0,余弦值为1

8.优缺分析
优点:
① 两个文本包含语义相似的词,会提高相似度
② 训练需要的数据简单(纯文本语料即可)
③ 计算速度快,可以对知识库内问题预先计算向量
④ 将文本转化为数字,使后续复杂模型成为可能
缺点:
① 词向量的效果决定句向量效果(语料数量、领域适配、分词结果、未登录词)
② 一词多意的情况难以处理 eg:梨 —— 苹果 —— 华为
③ 受停用词(无效词)和文本长度影响很大(也是词袋模型)
④ 更换语种,甚至更换领域,都需要重新训练
相关文章:
【NLP 30、文本匹配任务 —— 传统机器学习算法】
目录 一、文本匹配任务的定义 1.狭义解释 2.广义解释 二、文本匹配的应用 1.问答对话 2.信息检索 3.文本匹配任务应用 三、智能问答 1.智能问答的基本思路 依照基础资源划分: 依照答案产出方式划分 依照NLP相关技术划分 四、智能问答的价值 1.智能客服 2.Faq知识库问…...
爬虫Incapsula reese84加密案例:Etihad航空
声明: 该文章为学习使用,严禁用于商业用途和非法用途,违者后果自负,由此产生的一切后果均与作者无关 一、找出需要加密的参数 1.js运行 atob(‘aHR0cHM6Ly93d3cuZXRpaGFkLmNvbS96aC1jbi8=’) 拿到网址,F12打开调试工具,随便搜索航班,切换到network搜索一个时间点可以找…...
【Vue教程】使用Vite快速搭建前端工程化项目 Vue3 Vite Node.js
??大家好!我是毛毛张! ??个人首页: ??今天毛毛张分享的是关于如何快速??♂搭建一个前端工程化的项目的环境搭建以及流程?? 文章目录 1.前端工程化环境搭建?? 1.1 什么是前端工程化1.2 nodejs的简介和安装 1.2.1 什么是Nodejs1.2.2 如何安装…...
如何将飞书多维表格与DeepSeek R1结合使用:效率提升的完美搭档
将飞书的多维表格与DeepSeek R1结合使用,就像为你的数据管理和分析之旅装上一台涡轮增压器。两者的合作,不仅仅在速度上让人耳目一新,更是将智能化分析带入了日常的工作场景。以下是它们如何相辅相成并改变我们工作方式的一些分享。 --- 在…...
算数操作符、赋值操作符、单目操作符、强制类型转换
一、算术操作符(、 -、 *、 /、 %) • - * / %操作符都是双⽬操作符,有**两个操作数**的符号就叫做双目操作符 10 4| || | 操作数1 操作数2// - % / * 以此类推•操作符也被叫做:运算符 1. 符号、符号 - 和 符号* •…...
为AI聊天工具添加一个知识系统 之133 详细设计之74通用编程语言 之4 架构及其核心
本篇继续讨论 通用编程语言。 说明:本阶段的所有讨论都是围绕这一主题展开的,但前面的讨论分成了三个大部分(后面列出了这一段的讨论题目的归属关系)-区别distinguish(各别): 文化和习俗。知识…...
RNN实现精神分裂症患者诊断(pytorch)
RNN理论知识 RNN(Recurrent Neural Network,循环神经网络) 是一种 专门用于处理序列数据(如时间序列、文本、语音、视频等)的神经网络。与普通的前馈神经网络(如 MLP、CNN)不同,RNN…...
私有云基础架构
基础配置 使用 VMWare Workstation 创建三台 2 CPU、8G内存、100 GB硬盘 的虚拟机 主机 IP 安装服务 web01 192.168.184.110 Apache、PHP database 192.168.184.111 MariaDB web02 192.168.184.112 Apache、PHP 由于 openEuler 22.09 系统已经停止维护了ÿ…...
rust学习笔记11-集合349. 两个数组的交集
rust除了结构体,还有集合类型,同样也很重要,常见的有数组(Array)、向量(Vector)、哈希表(HashMap) 和 集合(HashSet)字符串等,好意外呀…...
全栈(Java+vue)实习面试题(含答案)
在广州一个小公司(BOSS标注是0-20人,薪资2-3k),直接面试没有笔试,一开始就直接拿着简历问,也没有自我介绍,问题是结合场景题和八股文、基础。废话不多说,直接分享面试题目个大家做参考。 1、能…...
SQL经典常用查询语句
1. 基础查询语句 1.1 查询表中所有数据 在SQL中,查询表中所有数据是最基本的操作之一。通过使用SELECT * FROM table_name;语句,可以获取指定表中的所有记录和列。例如,假设有一个名为employees的表,包含员工的基本信息…...
超详细:数据库的基本架构
MySQL基础架构 下面这个图是我给出的一个MySQL基础架构图,可以清楚的了解到SQL语句在MySQL的各个模块进行执行过程。 然后MySQL可以分为两个部分,一个是server层,另一个是存储引擎。 server层 Server层涵盖了MySQL的大多数核心服务功能&am…...
AI催化新一轮创业潮与创富潮:深圳在抢跑
作者:尺度商业大掌柜黄利明 2025年春节伊始至今,从DeepSeek R1开源模型持续引发全球围观,到腾讯混元Turbo S模型发布秀出了"秒回"绝活,再到国务院发布《新一代人工智能发展规划(2025-2030)》重磅…...
Docker 深度解析:适合零基础用户的详解
此博客涵盖 Docker 的基本概念和作用、架构和核心组件、与传统虚拟机的对比、安装与基本操作,以及在实际开发和运维中的应用场景。 首先,详细解释了 Docker 的基本概念,包括它的诞生背景、作用及其如何解决传统应用部署中的问题。然后&#…...
SpringBoot生成唯一ID的方式
1.为什么要生成唯一ID? 数据唯一性:每个记录都需要有一个独一无二的标识符来确保数据的唯一性。这可以避免重复的数据行,并有助于准确地查询、更新或删除特定的记录。 数据完整性:通过使用唯一ID,可以保证数据库中的数…...
FastGPT 源码:RRF、Rerank 相关代码
文章目录 FastGPT 源码:RRF、Rerank 相关代码1. RRF (Reciprocal Rank Fusion) 合并实现2. Rerank 二次排序实现3. 重排序的主要特点4. 整个搜索流程5. 这种方式的优势 FastGPT 源码:RRF、Rerank 相关代码 下边介绍 RRF 合并和 Rerank 二次排序的相关实…...
Android视频流畅播放要素
要让 Android 设备流畅播放视频,需根据设备性能(低端、中端、高端)和播放场景(本地播放、在线流媒体)动态调整视频参数。以下是针对不同设备的推荐配置方案: 一、通用推荐配置(平衡兼容性与流畅…...
Python:类型转换和深浅拷贝,可变与不可变对象
int():转换为一个整数,只能转换由纯数字组成的字符串 浮点型强转整型会去掉小数点及后面的数,只保留整数部分 #如果字符串中有数字和正负号以外的字符就会报错 float():整形转换为浮点型会自动添加一位小数 .0 如果字符串中有…...
vcredist_x64 资源文件分享
vcredist_x64 是 Microsoft Visual C Redistributable 的 64 位版本,用于在 64 位 Windows 系统上运行使用 Visual C 开发的应用程序。它包含了运行这些应用程序所需的运行时组件。 vcredist_x64 资源工具网盘下载链接:https://pan.quark.cn/s/ef56f838f…...
Linux:vim快捷键
Linux打开vim默认第一个模式是:命令模式! 命令模式快捷键操作: gg:光标快速定位到最开始 shift g G:光标快速定位到最结尾 n shift g n G:光标快速定位到第n行 shift 6 ^:当前行开始 …...
DeepSeek在MATLAB上的部署与应用
在科技飞速发展的当下,人工智能与编程语言的融合不断拓展着创新边界。DeepSeek作为一款备受瞩目的大语言模型,其在自然语言处理领域展现出强大的能力。而MATLAB,作为科学计算和工程领域广泛应用的专业软件,拥有丰富的工具包和高效…...
NAT 代理服务 内网穿透
🌈 个人主页:Zfox_ 🔥 系列专栏:Linux 目录 一:🔥 NAT 技术背景二:🔥 NAT IP 转换过程三:🔥 NAPT四:🔥 代理服务器🦋 正向…...
高级课第五次作业
首先配置交换机,路由器 LSW1配置 [SW1]vlan batch 10 20 30 40 [SW1]int g0/0/2 [SW1-GigabitEthernet0/0/2]port link-type access [SW1-GigabitEthernet0/0/2]port default vlan 10 [SW1]int g0/0/3 [SW1-GigabitEthernet0/0/3]port link-type access […...
51单片机编程学习笔记——动态数码管显示多个数字
大纲 视觉残留原理生理基础神经传导与处理 应用与视觉暂留相关的现象 频闪融合不好的实现好的效果 延伸 在《51单片机编程学习笔记——动态数码管》一文中,我们看到如何使用动态数码管显示数字。但是基于动态数码管设计的特点,每次只能显示1个数字。这就…...
金蝶ERP星空对接流程
1.金蝶ERP星空OPENAPI地址: 金蝶云星空开放平台 2.下载金蝶云星空的对应SDK包 金蝶云星空开放平台 3.引入SDK流程步骤 引入Kingdee.CDP.WebApi.SDK 右键项目添加引用,在打开的引用管理器中选择浏览页签,点击浏览按钮,找到从官…...
【随手笔记】利尔达NB模组
1.名称 移芯EC6263GPP 参数 指令备注 利尔达上电输出 [2025-03-04 10:24:21.379] I_AT_WAIT:i_len2 [2025-03-04 10:24:21.724] LI_AT_WAIT:i_len16 [2025-03-04 10:24:21.724] [2025-03-04 10:24:21.733] Lierda [2025-03-04 10:24:21.733] [2025-03-04 10:24:21.745] OK移…...
Vue3的核心语法【未完】
Vue3的核心语法 OptionsAPI与CompositionAPI Options API(选项式) 和 Composition API (组合式)是 Vue.js 中用于构建组件的两种不同方式。Options API Options API Options API 是 Vue 2 中的传统模式,并在 Vue 3…...
解决redis lettuce连接池经常出现连接拒绝(Connection refused)问题
一.软件环境 windows10、11系统、springboot2.x、redis 6 7 linux(centos)系统没有出现这问题,如果你是linux系统碰到的,本文也有一定大参考价值。 根本思路就是:tcp/ip连接的保活(keepalive)。 二.问题描述 在spr…...
C#进阶指南
C# 是一种功能强大的编程语言,其高级语法特性为开发者提供了更灵活、高效和简洁的编程方式。以下是一些常见的 C# 高级语法特性: 1. 委托(Delegate) 委托是一种类型安全的函数指针,用于封装方法的引用。它可以将方法作为参数传递,实现回调机制。 定义委托: csharp复制 …...
从DNS到TCP:DNS解析流程和浏览器输入域名访问流程
1 DNS 解析流程 1.1 什么是DNS域名解析 在生活中我们会经常遇到域名,比如说CSDN的域名www.csdn.net,百度的域名www.baidu.com,我们也会碰到IP,现在目前有的是IPV4,IPV6。那这两个有什么区别呢?IP地址是互联网上计算机…...
