一、WMD流程简述
WMD为衡量文本相似度的方法。使用WMD来计算两个文本D1,D2之间的相似度,计算流程如下:
- 首先对两个文本去除停用词
- 使用归一化BOW(词袋模型)方法来分别表示D1,D2
- 使用word2vec embedding来表示D1,D2中的每个词
- 在D1中所有词travel到D2中所有词,对于每一个D1中的词,它与D2中的词语义比较相近的,那么可以全部移动或移动距离多一些(权重值);对于语义差异较大,则移动距离少一点或者不移动。用词向量距离乘以移动距离就是两个词的转移代价。
- 求全局的转移代价累加和最小值(D1中所有词全部转移到D2,D2中的所有词也全部转移到D1中)。
- 这个全局转移代价累加和的最小值就是D1,D2的相似度。
如下图所示,4个词对之间的词向量欧式距离的累加值就是document1和document2的相似度:
二、算法的数学描述
假设有一个预训练好的word2vec词向量矩阵
X
∈
R
d
✖
n
X∈R^{d✖n}
X∈Rd✖n,表示词典大小为n,词向量维度为d。
如果词
i
i
i在文本中出现的次数为
c
i
c_i
ci ,那么我们定义词
i
i
i的归一化词频为:
d
i
=
c
i
∑
j
=
1
n
c
j
d_i=\frac{c_i}{\sum_{j=1}^nc_j}
di=∑j=1ncjci
另外词语距离的定义:词
i
i
i与词
j
j
j的欧式距离为:
c
(
i
,
j
)
=
∣
∣
x
i
−
x
j
∣
∣
2
c(i,j)=||x_i-x_j||_2
c(i,j)=∣∣xi−xj∣∣2
令
d
d
d和
d
′
d^′
d′表示分别表示D1,D2两个文本的归一化词袋表示,
d
d
d中的每个词
i
i
i都可以全部或者部分转移到
d
′
d^′
d′的每个词。因此,定义一个稀疏的转移矩阵
T
∈
R
n
×
n
T∈R^{n×n}
T∈Rn×n,
T
i
j
T_{ij}
Tij 表示d中的词
i
i
i到
d
′
d^′
d′中的词
j
j
j的转移距离。
T
i
j
≥
0
T_{ij}≥0
Tij≥0。那么,从
d
d
d到
d
′
d^′
d′的全局转移代价累加和表示为:
∑
i
j
T
i
j
c
(
i
,
j
)
∑_{ij}T_{ij}c(i,j)
ij∑Tijc(i,j)
这里需要求出最小的全局转移代价累加和,所以把求最小化问题建模成线性规划问题:
WMD的计算过程可视化如下图所示:
以上问题的线性规划问题是EMD算法中的一种特殊情况,具体求解过程可参考EMD算法。本论文采用了Fast-EMD论文中提出的求解方法,时间复杂度为
O
(
p
3
l
o
g
p
)
O(p^3logp)
O(p3logp),其中
p
p
p为两个文本移除停用词和去重后词表的大小。
三、算法优化
如果字典非常大,那么上述的求解方法的计算复杂度太高,我们可以通过使用low bound来减少问题的求解空间。从而提升计算效率。
1.WCD low bound(词心距离)
根据三角不等式可得 :
WCD对应的式子为:
∥
X
d
−
X
d
′
∥
2
∥Xd−Xd^′∥_2
∥Xd−Xd′∥2,
X
∈
R
d
×
n
X∈R^{d×n}
X∈Rd×n,因此对应的时间复杂度为
O
(
d
p
)
O(dp)
O(dp),
d
d
d为词向量的维度。
2. RWMD low bound(松弛WMD距离)
尽管WCD的时间复杂度很低,但是边界过于宽松,无法很好的近似WMD。因此,这里使用更加tight的下界RWMD。RWMD需要计算两次,基于WMD目标函数,分别去掉两个约束条件中的一个,然后求解最小值,使用两个最小值中的最大值作为WMD的近似值。
比如,去掉第二个约束条件,可得
这个问题的最优解是,对于文本D1中的一个词,找到另一文本D2中与之最相近的一个词,全部转移到这个词。
即:
使用
l
1
(
d
,
d
′
)
l_1(d,d^{'})
l1(d,d′)和
l
2
(
d
,
d
′
)
l_2(d,d^{'})
l2(d,d′)分别表示,去掉不同约束条件所计算得到的最小值,RWMD最终的最小值为:
这个的时间复杂度为
O
(
p
2
)
O(p^2)
O(p2)。
3.剪枝
如何使用上面的两种下界对WMD进行剪枝。
- 利用WCD计算出所有的距离,取topK
- 计算topK文本的WMD值
- 对于剩下的文本,计算RWMD值,如果RWMD比topK中的WMD最大的小,则替换topK中的WMD最大的文本,并计算它的WMD值,否则,剪枝。
由于RWMD值与WMD值非常接近,因此对于剩下文本,几乎95%都是可以被剪枝的。
在twitter/amazon这两个数据集上,随机抽取一些文本组成句对,将这些句对按WMD值进行升序排列,横坐标为句对编号,纵坐标为WCD,RWMD,WMD的值。从图中可以看出,WCD是非常宽松的下界,而RWMD则与WMD非常接近:
四、优缺点
优点:
- 不需要设置超参数
- 无监督,不依赖标注数据,没有冷启动问题
- 有全局最优解
- 可人为干预词的重要性
缺点:
- 词袋模型,没有保留语序信息(ngram)
- 不能处理OOV问题(因为word2vec导致的,这里可以使用fasttext)
- 处理否定词能力差(加入情感极性信息)
- 处理领域同义词互斥词的能力偏差
五、代码实现
使用时,可以直接调用gensim中封装好的
from gensim.models import Word2Vec
from gensim.similarities import WmdSimilarity
import numpy as np
class WMDRetrievalModel:
def __init__(self, corpus, gensim_model_path):
word2Vec_model = Word2Vec.load(gensim_model_path)
self.wmd_similarity = WmdSimilarity(corpus, word2Vec_model)
def get_top_similarities(self, query, topk=10):
sims = self.wmd_similarity[query]
# 我安装的gensim版本这一步返回的是数组,但也有版本返回https://blog.csdn.net/weixin_40547993/article/details/89475630
sort = np.argsort(sims, axis=0)
return sort[-1], sort[-2]
def predict(model, query):
"""
预测
:param model: 模型
:param query: 输入文本
:return: topK
"""
# 对输入文本分词
query = word_tokenize(query)
# 返回最相似两个问题的索引
top_1, top_2 = model.get_top_similarities(query, topk=2)
return questions_src[top_1], answers[top_1], questions_src[top_2], answers[top_2]
wmd_model = WMDRetrievalModel(questions, args.gensim_model_path)
res = predict(wmd_model, query)
即可返回最相似的两个文本
Query: 如何申请假期
Question 1: 出公差如何申请
Answer 1: 登陆 HR 系统,进入“考勤管理 →考勤管理”界面,填写需请假的内容。
注意: 申请时段中应不包含节假 日,按工作日分开填写
Question 2: 工伤如何申请假期?
Answer 2: 登陆 HR 系统,进入“考勤管理 →考勤管理”界面,填写需请假的内容。
注意: 申请时段中应不包含节假 日,按工作日分开填写
六、应用场景
什么场景下运用WMD呢?注重两两之间一一对应的关系,不仅语义一样,而且指代也类似,同时,也期望以最小的状态转移到另一个状态下,会使用WMD来衡量两两之间的距离。
参考:
如果对您有帮助,麻烦点赞关注,这真的对我很重要!!!如果需要互关,请评论或者私信!