写点什么

特定领域知识图谱 (DKG) 融合方案:技术知识前置【一】- 文本匹配算法、知识融合学术界方案、知识融合业界落地方案、算法测评 KG 生产质量保障

作者:汀丶
  • 2023-01-18
    浙江
  • 本文字数:16878 字

    阅读完需:约 55 分钟

特定领域知识图谱(Domain-specific KnowledgeGraph:DKG)融合方案:技术知识前置【一】-文本匹配算法、知识融合学术界方案、知识融合业界落地方案、算法测评 KG 生产质量保障

0.前言

本项目主要围绕着特定领域知识图谱(Domain-specific KnowledgeGraph:DKG)融合方案:技术知识前置【一】-文本匹配算法、知识融合学术界方案、知识融合业界落地方案、算法测评 KG 生产质量保障讲解了文本匹配算法的综述,从经典的传统模型到孪生神经网络“双塔模型”再到预训练模型以及有监督无监督联合模型,期间也涉及了近几年前沿的对比学习模型,之后提出了文本匹配技巧提升方案,最终给出了 DKG 的落地方案。这边主要以原理讲解和技术方案阐述为主,之后会慢慢把项目开源出来,一起共建 KG,从知识抽取到知识融合、知识推理、质量评估等争取走通完整的流程。

1.文本匹配算法综述(短文本匹配)

文本匹配任务在自然语言处理中是非常重要的基础任务之一,一般研究两段文本之间的关系。有很多应用场景;如信息检索、问答系统、智能对话、文本鉴别、智能推荐、文本数据去重、文本相似度计算、自然语言推理、问答系统、信息检索等,但文本匹配或者说自然语言处理仍然存在很多难点。这些自然语言处理任务在很大程度上都可以抽象成文本匹配问题,比如信息检索可以归结为搜索词和文档资源的匹配,问答系统可以归结为问题和候选答案的匹配,复述问题可以归结为两个同义句的匹配。


  1. 如语言不规范,同一句话可以有多种表达方式;如“股市跳水、股市大跌、股市一片绿”

  2. 歧义,同一个词语或句子在不同语境可能表达不同意思;如“割韭菜”,“领盒饭”,“苹果”“小米”等在不同语境下语义完全不同

  3. 不规范或错误的输入;如 “ yyds”,“绝绝子”“夺笋”“耗子尾汁”

  4. 需要知识依赖;如奥运冠军张怡宁绰号“乒乓大魔王”等。


短文本匹配即计算两个短文本的相似度,通常分成无监督方式、有监督方式、有监督+无监督方式


常见的文本匹配算法如下表(简单罗列),按传统模型和深度模型简单的分为两类:


1.1 文本匹配传统模型(无监督方式)

文本表征:词袋模型(one-hot 、TF)、词向量预训练(word2vector、fasttext、glove)相似度计算:余弦相似度、曼哈顿距离、欧氏距离、jaccard 距离等

1.1.1 Jaccord 杰卡德相似系数

jaccard 相似度是一种非常直观的相似度计算方式,即两句子分词后词语的交集中词语数与并集中词语数之比。



def jaccard(list1, list2):    """    jaccard相似系数    :param list1:第一句话的词列表     :param list2: 第二句话的词列表    :return:相似度,float值     """    list1, list2 = set(list1), set(list2) #去重    intersection = list1.intersection(list2) # 交集    union = list1.union(list2)  # 并集    Similarity = 1.0 * len(intersection) / len(union) #交集比并集    return Similarity
复制代码


a.分词


    内蒙古 锡林郭勒盟 多伦县 县医院    /    多伦县 医院
绵阳市 四 零 四 医院 / 四川 绵阳 404 医院
邓州市 人民 医院 / 南召县 人民 医院
复制代码


b.去重求交集--并集


    多伦县(交集)    --      内蒙古、锡林郭勒盟、多伦县、县医院、医院(并集)
医院(交集) -- 绵阳市、四、零、医院、四川、绵阳、404(并集)
人民、医院(交集) -- 邓州市、人民、医院、南召县(并集)
复制代码


c.相似度


1.1.2.Levenshtein 编辑距离

一个句子转换为另一个句子需要的编辑次数,编辑包括删除、替换、添加,然后使用最长句子的长度归一化得相似度。


def Levenshtein(text1, text2):    """    Levenshtein编辑距离    :param text1:字符串1    :param text2:字符串2    :return:相似度,float值    """    import Levenshtein    distance = Levenshtein.distance(text1, text2)    Similarity = 1 - distance * 1.0 / max(len(text1), len(text2))    return Similarity
复制代码


a.分词-计字数


    内 蒙 古 锡 林 郭 勒 盟 多 伦 县 县 医 院 (14)   /    多 伦 县 医 院(5)
绵 阳 市 四 零 四 医 院(8) / 四 川 绵 阳 4 0 4 医 院(9)
邓 州 市 人 民 医 院 (7) / 南 召 县 人 民 医 院(7)
复制代码


b.计算编辑距离


   内 蒙 古 锡 林 郭 勒 盟 多 伦 县 县 医 院 ------->删除内、蒙、古、锡、林、郭、勒、盟、县
绵 阳 市 四 零 四 医 院 ------->加 四、川
------->删除 市
------->替换 四(4)、零(0)、四(4)
邓 州 市 人 民 医 院 ------->替换邓(南)、 州(召)、 市(县)
复制代码


1.1.3 simhash 相似度

先计算两句子的 simhash 二进制编码,然后使用海明距离计算,最后使用两句的最大 simhash 值归一化得相似度。


def simhash_(text1, text2):    """    simhash相似度    :param s1: 字符串1    :param s2: 字符串2    :return: 相似度,float值    """    from simhash import Simhash    text1_simhash = Simhash(text1, f=64)  #计算simhash向量    text2_simhash = Simhash(text2, f=64)  #计算simhash向量    distance = text1_simhash.distance(text2_simhash)  #汉明距离    Similarity = 1 - distance / max(len(bin(text1_simhash.value)), len(bin(text2_simhash.value))) #相似度    return Similarity
复制代码


a.分词


    内蒙古 锡林郭勒盟 多伦县 县医院    /    多伦县 医院
绵阳市 四 零 四 医院 / 四川 绵阳 404 医院
邓州市 人民 医院 / 南召县 人民 医院
复制代码


b.计算词权重(此处用 tfidf 计算,其他方法也可以)


| Text | Text | Text |



c.hash 函数映射词向量


  • 先将词映射到二进制编码,

  • 然后用 b 步骤中的权重值替换 1,

  • b 步骤中权重值的负数替换 0



d.合并(将一段文本内的词向量进行累加)



e 海明距离判断相似度


海明距离可以理解为:两个二进制串之间相同位置不同的个数。举个例子,[1,1,1,0,0,0]和[1,1,1,1,1,1]的海明距离就是 3。


1.1.4 Bm25 相似度

一句话概况其主要思想:对 Query(待查询语句)进行语素解析,生成语素 qi;然后,对于每个搜索结果 D,计算每个语素 qi 与 D 的相关性得分,最后,将 qi 相对于 D 的相关性得分进行加权求和,从而得到 Query 与 D 的相关性得分。公式如下:


Q 表示 Query,qi 即 Q 分词后的每一个解析语素(对中文而言,我们可以把对 Query 的分词作为语素分析,每个词看成语素 qi)。d 表示一个搜索结果文档,Wi 表示语素 qi 的权重,R(qi,d)表示语素 qi 与文档 d 的相关性得分。判断一个词与一个文档的相关性的权重定义 Wi 方法有多种,较常用的是 IDF。公式如下:


  • N 为索引中的全部文档数,

  • n(qi)为包含了 qi 的文档数。


根据 IDF 的定义可以看出当很多文档都包含了 qi 时,qi 的区分度就不高,因此使用 qi 来判断相关性时的重要度就较低。


求 Score(qi,d)具体的公式可以参考文本相似度-BM25 算法其中


  • f(qi, D)为单词在当前候选文档中的词频

  • k1、b 为调节因子,通常设为 k1=2,b=0.75

  • |D|为当前候选文本数(与目标文本匹配的总条数)

  • avgdl 为语料库中所有文档的平均长度。


在做文本匹配的时候(如重复问题检测)可以尝试 BM25 的方法,但在搜索领域中,有时候搜索 query 和候选文档的长度是不一样甚至差距很大,所以 BM25 在计算相似性的时候需要对文档长度做一定的处理。


文本相似度-BM25算法


#Bm25import mathimport jiebaclass BM25(object):    def __init__(self, docs):#docs是一个包含所有文本的列表,每个元素是一个文本        self.D = len(docs)  #总文本数        self.avgdl = sum([len(doc)+0.0 for doc in docs]) / self.D   #平均文本长度        self.docs = docs #文本库列表        self.f = []  # 列表的每一个元素是一个dict,dict存储着一个文档中每个词的出现次数        self.df = {} # 存储每个词及出现了该词的文档数量        self.idf = {} # 存储每个词的idf值        self.k1 = 1.5        self.b = 0.75        self.init()     def init(self):        for doc in self.docs:  #对每个文本            tmp = {}   #定义一个字典存储词出现频次            for word in doc:                tmp[word] = tmp.get(word, 0) + 1  # 存储每个文档中每个词的出现次数            self.f.append(tmp)            for k in tmp.keys():                self.df[k] = self.df.get(k, 0) + 1        for k, v in self.df.items():            self.idf[k] = math.log(self.D-v+0.5)-math.log(v+0.5) #计算idf     def sim(self, doc, index):        score = 0        for word in doc:            if word not in self.f[index]:                continue            d = len(self.docs[index])            score += (self.idf[word]*self.f[index][word]*(self.k1+1)                      / (self.f[index][word]+self.k1*(1-self.b+self.b*d                                                      / self.avgdl)))        return score     def simall(self, doc):        scores = []        for index in range(self.D):            score = self.sim(doc, index)            scores.append(score)        return scores if __name__ == '__main__':    sents1 = ["多伦县医院",  #数据库                "四川绵阳404医院",               "南召县人民医院"]    sents2 = ["内蒙古锡林郭勒盟多伦县县医院","绵阳市四零四医院","邓州市人民医院"]#待匹配文本    doc = []    for sent in sents1:        words = list(jieba.cut(sent))        doc.append(words)    print(doc)    s = BM25(doc)    print(s.f)    print(s.idf)    for k in sents2:        print(s.simall(jieba.lcut(k))) #打印相似度匹配结果                
复制代码


1.1.5 VSM(向量空间模型)算法

VSM 算法的思路主要分为两步:


(1) 用向量表示句子,用向量表示句子的方法很多,简单的有 onehot,词频法,基于语义的有 word2vec/fastText/glove/bert/elmo 等,本例中使用基于简单的词频的向量化方式。


(2)计算两向量的余弦距离(曼哈顿距离、欧几里得距离、明式距离、切比雪夫距离)得相似度。


#tfidf_余弦def sim_vecidf(self, s1, s2):    """词向量通过idf加权平均后计算余弦距离"""    v1, v2 = [], []    # 1. 词向量idf加权平均    for s in jieba.cut(s1):        idf_v = idf.get(s, 1)        if s in voc:            v1.append(1.0 * idf_v * voc[s])    v1 = np.array(v1).mean(axis=0)    for s in jieba.lcut(s2):        idf_v = idf.get(s, 1)        if s in voc:            v2.append(1.0 * idf_v * voc[s])    v2 = np.array(v2).mean(axis=0)    # 2. 计算cosine    sim = self.cosine(v1, v2)    return sim
复制代码


a.句子向量化


a1.取句子对的唯一词元组


set(内蒙古 锡林郭勒盟 多伦县 县医院 / 多伦县 医院) = (内蒙古 锡林郭勒盟 多伦县 县医院 医院)


set(绵阳市 四 零 四 医院 / 四川 绵阳 404 医院) = (绵阳市 四 零 医院 四川 绵阳 404 )


set(邓州市 人民 医院 / 南召县 人民 医院) = (邓州市 人民 医院 南召县)


a2.根据每个句子在元组中的词频建立向量表示



b.计算余弦距离


1.1.6 word2vector + 相似度计算(BERT 模型+余弦相似度为例)

常用做法是通过 word2vec 等预训练模型得到词向量,然后对文本做分词,通过 embedding_lookup 得到每个 token 对应的词向量,然后得到短文本的句向量。对两个文本的句子向量采用相似度计算方法如余弦相似度、曼哈顿距离、欧氏距离等。无监督方式取得的结果取决于预训练词向量的效果


BERT 是谷歌在 2018 年推出的深度语言表示模型,是关于语言理解的深度双向 transformers 的预训练模型,开启了预训练模型的新篇章。它可以学习文本的语义信息,通过向量形式的输出可以用于下游任务。也就说,它自己已经在大规模预料上训练好的参数,我们在用的时候只需要在这个基础上训练更新参数。bert 模型可以解决多种自然语言处理问题,如单文本分类、语句对分类、序列标注等。在解决文本匹配任务时,有两种思路,第一种直接把文本匹配任务作为语句对分类任务,模型输入语句对,输出是否匹配的标签;第二种利用 bert 模型预训练文本对的上下文嵌入向量,再通过余弦相似度等相似度计算方法验证文本对是否匹配,在此基础上还有很多基于 bert 模型的变种,篇幅有限不做一一讲述。接下来简单介绍一下 bert 预训练文本嵌入+余弦相似度的算法框架。




a.首先使用大量公域文本数据对 BERT 模型进行预训练(或直接用谷歌预训练好的模型)


b.将文本直接输入模型


c.对模型输出的语义向量 C,或中间隐层向量,计算余弦相似度,得到匹配结果。


基于深度学习的匹配算法种类繁多,如基于 CNN 网络、RNN 网络、LSTM 网络等及各种变种层出不穷,在此不一一列举实现。


传统的文本匹配方法主要关注文本间字与字,词与词的匹配关系,无法准确识别不同表达方式下不同文本的同一指向关系,即语义关系。因此在这一背景下,要对多源异构的海量地址数据进行匹配,传统的文本匹配方法已不再适用,深度学习方法大行其道。但深度学习方法也有自身的局限性,比如对海量文本和算力的高要求等,都使得深度学习方法的普适性大打折扣,因此没有最好的文本匹配算法,只有当前条件下最适合的文本匹配算法。

2.有监督方式

2.1 孪生神经网络(Siamese Network)

原文:《Learning a Similarity Metric Discriminatively, with Application to Face Verification》


  1. 要解决什么问题?

  2. 用于解决类别很多(或者说不确定),然而训练样本的类别数较少的分类任务(比如人脸识别、人脸认证)

  3. 通常的分类任务中,类别数目固定,且每类下的样本数也较多(比如 ImageNet)

  4. 用了什么方法解决?


提出了一种思路:将输入映射为一个特征向量,使用两个向量之间的“距离”(L1 Norm)来表示输入之间的差异(图像语义上的差距)。基于上述思路设计了 Siamese Network。每次需要输入两个样本作为一个样本对计算损失函数。


  • 常用的 softmax 只需要输入一个样本。

  • FaceNet 中的 Triplet Loss 需要输入三个样本。

  • 提出了 Contrastive Loss 用于训练。


  1. 效果如何?


文中进行了一个衡量两张人脸的相似度的实验,使用了多个数据库,较复杂。siamese network 现在依然有很多地方使用,可以取得 state-of-the-art 的效果。


  1. 还存在什么问题?


  • contrastive loss 的训练样本的选择需要注意,论文中都是尽量保证了 50%的正样本对和 50%的负样本对。


分类问题:


  • 第一类,分类数量较少,每一类的数据量较多,比如 ImageNet、VOC 等。这种分类问题可以使用神经网络或者 SVM 解决,只要事先知道了所有的类。

  • 第二类,分类数量较多(或者说无法确认具体数量),每一类的数据量较少,比如人脸识别、人脸验证任务。


文中提出的解决方案:


learn a similar metric from data。核心思想是,寻找一个映射函数,能够将输入图像转换到一个特征空间,每幅图像对应一个特征向量,通过一些简单的“距离度量”(比如欧式距离)来表示向量之间的差异,最后通过这个距离来拟合输入图像的相似度差异(语义差异)。

2.1.1 简介

  • Siamese Network 是一种神经网络的框架,而不是具体的某种网络,就像 seq2seq 一样,具体实现上可以使用 RNN 也可以使用 CNN。

  • Siamese network 就是“连体的神经网络”,神经网络的“连体”是通过共享权值来实现的。(共享权值即左右两个神经网络的权重一模一样)

  • siamese network 的作用是衡量两个输入的相似程度。孪生神经网络有两个输入(Input1 and Input2),将两个输入 feed 进入两个神经网络(Network1 and Network2),这两个神经网络分别将输入映射到新的空间,形成输入在新的空间中的表示。通过 Loss 的计算,评价两个输入的相似度。



Siamese Network 有两个结构相同,且共享权值的子网络。分别接收两个输入 X1 与 X2,将其转换为向量 Gw(X1)与 Gw(X2),再通过某种距离度量的方式计算两个输出向量的距离 Ew。


训练 Siamese Network 采用的训练样本是一个 tuple (X1,X2,y)(X1,X2,y),标签 y=0 表示 X1 与 X2 属于不同类型(不相似、不重复、根据应用场景而定)。y=1 则表示 X2 与 X2 属于相同类型(相似)。


LOSS 函数的设计应该是


  1. 当两个输入样本不相似(y=0)时,距离 Ew 越大,损失越小,即关于 Ew 的单调递减函数。

  2. 当两个输入样本相似(y=1)时,距离 Ew 越大,损失越大,即关于 Ew 的单调递增函数。


用 L+(X1,X2)表示 y=1 时的 LOSS,L−(X1,X2)表示 y=0 时的 LOSS,则 LOSS 函数可以写成如下形式:


Lw(X1,X2)=(1−y)L−(X1,X2)+yL+(X1,X2)



简单来说:孪生体现在使用相同的编码器(sentence encoder),将文本转为高维向量。具体步骤为,有文本 A 和文本 B 分别输入 sentence encoder 进行特征提取和编码,将输入映射到新的空间得到特征向量 u 和 v;最终通过 u、v 的拼接组合,经过下游网络来计算文本 A 和 B 的相似性


  • 在训练和测试中,模型的编码器是权重共享的,编码器可以选择 CNN、RNN、LSTM 等

  • 提取到特征 u、v 后,可以使用余弦距离、欧氏距离等得到两个文本的相似度。

  • 缺点是两个文本在编码时候没有交互,缺乏交互的结构没有充分利用到两个文本相互影响的信息

2.2 匹配聚合网络(ESIM,BIMPM)

在上述孪生网络的基础上,得到特征 u、v 但是不直接计算向量相似度,而是通过注意力机制将两个文本进行信息交互,最后通过全连接层得到相似度。


代表的模型有 ESIM,BIMPM 等


以 ESIM 为例


  • 首先是对两个文本的初期编码,就是对两个文本做分词、文本表征,即对句子进行信息的提取。如果使用 LSTM 作为 encoder,可以得到每个时刻(每个单词)的输出,通常维度为[batch_size, seq_len, embedding_dim]。举例子为,句子 A 长度 10,句子 B 长度也为 10,那么进过编码以后句子 A 的维度[1,10,300],句子 B[1,10,300],这里就得到了上述所提到的 u、v

  • 接下来是交互操作,为了操作简单忽略 batchsize 维度,交互即矩阵相乘得到[10,10],矩阵需要对句子 A 做横向概率归一,对句子 B 做纵向概率归一。上面这句话其实就是 ESIM 的核心要点。它是一个两个 item 之间互相做 attention,简单称之为 both attention。

  • 对 attention 后得到的向量做拼接后输出编码器,输出再接到全连接层、softmax 就可以得到结果,即两个文本相似(label 1)或不相似(label 0)

3.预训练语言模型

  1. 第一阶段,使用通用的预料库训练语言模型,

  2. 第二阶段预训练的语言模型(BERT 相关衍生的模型)做相似度任务,得到信息交互后的向量,

  3. 连接全连接层,输出概率。即将两个短文本拼接(CLS A1 A2 … A 10 SEP B1 B2 … B10 SEP),然后 CLS 向量连接全连接层,判断相似与否。


这种模型参数多,并且使用了通用的语料库,能够获取到短文本之间隐藏的交互信息,效果较好。


简单来说用拼接的方法类似“单塔”,孪生网络的方法类似“双塔”,不完全准确后续会详细说明,预训练模型就不展开讲了,大家去官网或者多看几篇学术论文吧,BERT ERNIE。

4.有监督方式 + 无监督方式

无监督:直接相加得到句向量,不能很好的表达语义信息,并且词的位置信息没有得到体现,也不包含上下文的语义信息。


有监督学习:时间复杂度太高。可以将标准库中的句向量计算完成并存储。新的文本来临时,只需要解决用户问题即可,然后与存储在库中的标准问句进行距离度量。


可以使用 BERT 代替孪生网络的 CNN 或 LSTM 结构,获取更多语义信息的句向量,还可以通过蒸馏降低 BERT 模型的参数,节约时间成本。

4.1 Sentence-BERT

文章链接:https://arxiv.org/pdf/1908.10084.pdf


论文代码:https://github.com/UKPLab/


为了让 BERT 更好地利用文本信息,作者们在论文中提出了如下的 SBERT 模型。SBERT 沿用了孪生网络的结构,文本 Encoder 部分用同一个 BERT 来处理。之后,作者分别实验了 CLS-token 和 2 种池化策略(Avg-Pooling、Mean-Pooling),对 Bert 输出的字向量进一步特征提取、压缩,得到 u、v。



关于 u、v 整合,作者提供了 3 种策略:


  1. 将 u、v 拼接,接入全连接网络,经过 softmax 输出,损失函数用交叉熵损失

  2. 直接计算两个文本的余弦相似度,损失函数用均方根误差



  1. 如果输入的是三元组


SBERT 直接用 BERT 的原始权重初始化,在具体数据集微调,训练过程和传统 Siamese Network 类似。但是这种训练方式能让 Bert 更好的捕捉句子之间的关系,生成更优质的句向量。在测试阶段,SBERT 直接使用余弦相似度来衡量两个句向量之间的相似度,极大提升了推理速度。


使用 NLI 和 STS 为代表的匹配数据集,在分类目标函数训练时,作者测试了不同的整合策略,结果显示“(u, v, |u-v|)”的组合效果最好。最重要的部分是元素差:(|u - v|)。句向量之间的差异度量了两个句子嵌入维度间的距离,确保相似的 pair 更近,不同的 pair 更远。

4.2 对比学习

深度学习的本质是做两件事情:①表示学习 ②归纳偏好学习。对比学习(ContrastiveLearning)则是属于表示学习的范畴,它并不需要关注样本的每一个细节,但是学到的特征要使其能够和其他样本区分开。对比学习作为一种无监督表示学习方法,最开始也是在 CV 领域掀起浪潮,之后 NLP 跟进,在文本相似度匹配等任务上超过 SOTASOTA。该任务主要是对文本进行表征,使相近的文本距离更近,差别大的文本距离更远。


NLP 的对比学习算法下文将不详细讲述简单展示更多内容参考链接。

4.2.1 BERT-Flow 2020.11

很多研究发现 BERT 表示存在问题:未经微调的 BERT 模型在文本相似度匹配任务上表现不好,甚至不如 Glove?作者通过分析 BERT 的性质,如图:



在理论上 BERT 确实提取到了足够的语义信息,只是这些信息无法通过简单的 consine 直接利用。主要是因为:


  • ①BERT 的词向量在空间中不是均匀分布,而是呈锥形。高频词都靠近原点,而低频词远离原点,相当于这两种词处于了空间中不同的区域,那高频词和低频词之间的相似度就不再适用;

  • ②低频词的分布很稀疏。低频词表示得到的训练不充分,分布稀疏,导致该区域存在语义定义不完整的地方(poorly defined),这样算出来的相似度存在问题。


针对以上问题,提出了 BERT-Flow,基于流式生成模型,将 BERT 的输出空间由一个锥形可逆地映射为标准的高斯分布空间。


4.2.2 BERT-Whitening 2021.03

BERT-Whitening 首先分析了余弦相似度为什么可以衡量向量的相似度:向量 A 与 B 的乘积等于 A AA 在 B BB 所在直线上投影的长度。将两个向量扩展到 d 维


上述等式的成立,都是在标准正交基(忘了的同学可以自行复习一下)的条件下,也就是说向量依赖我们选择的坐标基,基底不同,内积对应的坐标公式就不一样,从而余弦值的坐标公式也不一样。所以,BERT 的句向量虽然包含了足够的语义,但有可能是因为此时句向量所属的坐标系并非标准正交基,而导致用基于标准正交基的余弦相似度公式计算时效果不好。那么怎么知道具体用了何种基底呢?可以依据统计学去判断,在给向量集合选择基底时,尽量平均地用好每一个基向量,这就体现为每个分量的使用都是独立的、均匀的,如果这组基是标准正交基,那么对应的向量集应该表现出“各向同性”来,如果不是,可以想办法让它变得更加各向同性一写,然后再用余弦公式计算,BERT-Flow 正是想到了“flow 模型”的办法,而作者则找到了一种更简单的线性变换的方法。


标准化协方差矩阵


BERT-Whitening 还支持降维操作,能达到提速和提效的效果。


★PCA 和 SVD 差异分析:PCA 可以将方阵分解为特征值和特征向量,SVD 则可以分解任意形状的矩阵。

4.2.3 ConSERT 2021.05

https://arxiv.org/pdf/2105.11741.pdf


美团技术团队提出了基于对比学习的句子表示迁移方法——ConSERT,主要证实了以下两点:


①BERT 对所有的句子都倾向于编码到一个较小的空间区域内,这使得大多数的句子对都具有较高的相似度分数,即使是那些语义上完全无关的句子对。我们将此称为 BERT 句子表示的“坍缩(Collapse)”现象。



②BERT 句向量表示的坍缩和句子中的高频词有关。当通过平均词向量的方式计算句向量时,高频词的词向量将会主导句向量,使之难以体现其原本的语义。当计算句向量时去除若干高频词时,坍缩现象可以在一定程度上得到缓解。



为了解决 BERT 存在的坍缩问题,作者提出了句子表示迁移框架:



对 BERT encoder 做了改进,主要包括三个部分:


*①数据增强模块,作用于 embedding 层,为同一文本生成不同的编码。



  1. shuffle:更换 position id 的顺序

  2. token cutoff:在某个 token 维度把 embedding 置为 0

  3. feature cutoff:在 embedding 矩阵中,有 768 个维度,把某个维度的 feature 置为 0

  4. dropout:embedding 中每个元素都有一定概率为 0,没有行或列的约束


数据增强效果:Token Shuffle > Token Cutoff >> Feature Cutoff ≈ Dropout >> None


  • ②共享的 Bert encoder,生成句向量。

  • ③一个对比损失层,在一个 Batch 内计算损失,拉近同一样本不同句向量的相似度,使不同样本之间相互远离。损失函数:


N:Batchsize,2N 表示 2 种数据增强方式,sim():余弦相似度函数,r:句向量,τ:实验 0.08−0.12 最优


除了无监督训练之外,作者还提出了三种进一步融合监督信号的策略:


  • ①联合训练(joint):有监督的损失和无监督的损失通过加权联合训练模型。

  • ②先有监督再无监督(sup-unsup):先使用有监督损失训练模型,再使用无监督的方法进行表示迁移。

  • ③联合训练再无监督(joint-unsup):先使用联合损失训练模型,再使用无监督的方法进行表示迁移。


参考链接:https://blog.csdn.net/PX2012007/article/details/127614565

4.2.4 SimCSE:2021.04

前几节讲述了对比学习的原理和几种基于 Bert 的方式获取句子向量,例如 BERT-flow 和 BERT-whitening 等,对预训练 Bert 的输出进行变换从而得到更好的句子向量。后面将通过 ①构造目标函数 ②构建正负例 的对比学习方法训练模型,取得 SOTA 的效果。


SimCSE 是有大神陈丹琦发表的《Simple Contrastive Learning of Sentence Embeddings》,简单高效



SimCSE 包含无监督(图左部分)和有监督(图右部分)两种方法。实线箭头代表正例,虚线代表负例。


  • Unsupervised


创新点在于使用 Dropout 对文本增加噪音。


1.正例构造:利用 Bert 的随机 Dropout,同一文本经过两次 Bert enconder 得到不同的句向量构成相似文本。


2.负例构造:同一个 Batch 中的其他样本作为负例被随机采样。


  • Supervised


1.正例:标注数据 2.负例:同 Batch 内的其他样本

4.2.5 R-Drop(Supervised):2021.06

https://arxiv.org/abs/2106.14448


Dropout 虽然可以防止模型训练中的过拟合并增强鲁棒性,但是其操作在一定程度上会使训练后的模型成为一种多个子模型的组合约束。SimCSE 就是希望 Dropout 对模型结果不会有太大影响,也就是模型输出对 Dropout 是鲁棒的。所以,“Dropout 两次”这种思想是可以推广到一般任务的,这就是 R-Drop(Regularized Dropout),由微软亚洲研究院和苏州大学提出的更加简单有效的正则方法。


  • R-Drop 与传统作用于神经元或模型参数的约束方法不同,而是作用于输出层,弥补了 Dropout 在训练和测试时的不一致性。在每个 mini-batch 中,每个数据样本过两次带有 Dropout 的同一个模型,R-Drop 再使用 KL-divergence(KL 散度)约束两次的输出一致。所以,R-Drop 约束了由于 Dropout 带来的两个随机子模型的输出一致性。

  • R-Drop 只是简单增加了一个 KL-散度损失函数项,并没有其他任何改动。虽然该方法看起来很简单,但在 NLP 和 CV 的任务中,都取得了非常不错的 SOTA 结果。



同样的输入,同样的模型,经过两个 Dropout 得到的将是两个不同的分布,近似将这两个路径网络看作两个不同的模型网络。基于此,这两个不同的模型产生的不同分布而这篇文章的主要贡献就是在训练过程中不断拉低这两个分布之间的 KL 散度。由于 KL 散度本身具有不对称性,作者通过交换这两种分布的位置以间接使用整体对称的 KL 散度,称之为双向 KL 散度。

4.2.6 ESimCSE(Unsupervised):2021.09

https://arxiv.org/abs/2109.04380


SimCSE 构建正负例时存在两个两个缺点:


  • ①构造正例长度相等,导致模型预测时存在偏差,长度相等的文本会倾向预测相似度高。

  • ②对比学习理论上负例越多,对之间模型学习的越好,但增大 Batch 会受到性能的限制。


ESimCSE 针对以上问题做了相应的改进:



  • 正例构造:通过引入噪声较小的“单词重复”方式改变正例的长度,设置重复率 dup_rate,确定 dup_len 后利用均匀分布随机选取 dup_len 子词进行重复。

  • 负例构造:为了更有效的扩展负对,同时不降低性能,通过维护一个队列,重用前面紧接的 mini-batch 的编码嵌入来扩展负对:

  • ①将当前 mini-batch 的句嵌入放入队列,同时将“最老的”句子踢出队列。由于排队句子嵌入来自前面的 mini-batch,通过取其参数的移动平均来保持动量更新模型,并利用动量模型生成排队句子嵌入。

  • 在使用动量编码器时,关闭了 dropout,这可以缩小训练和预测之间的差距。

4.2.7 PromptBERT(Unsupervised):2022.01

https://arxiv.org/pdf/2201.04337v1.pdf


Prompt Learning 比较火热,号称 NLP 的第四范式,


  • 作者发现 BERT 在语义相似度方面表现不好,主要由:static token embeddings biases 和 ineffective layers,而不是 high cosine similarity of the sentence embedding。static token embedding 是在 bert 结构中,输入进 block 前,通过 embedding layer 产生的结果,这里强调是静态的 embedding,就是 embedding metrics 中每个 token 都唯一对应的 embedding,是不随句子环境而变化的。至于 ineffective layers 就很好理解了,就是 bert 中堆叠的 block 结构,比如 bert-base 中的 12 层。作者认为这些结构,对语义相似度的表征这个方面是无效的。

  • Anisotropy(各向异性):上篇我们已经提到,词向量是有维度的,每个维度上基向量单位向量长度不一样,就是各向异性的。这会造成计算向量相似度的时候产生偏差。如何度量 Anisotropy:


作者分析了造成 embedding bias 的原因,除了 token frequency 是造成 bias 的原因,作者又提出了:subwords,case sentitive



图中不同词频 token 的分布情况,颜色越深代表词频越高,我们可以看出词频高的 token,分布比较紧凑,词频低的 token,分布较分散。作者输出这个图像还有一个目的是他提出各向异性(anisotropy)和偏差(bias)是不相关的,各向异性不是导致偏差的原因。Embedding bias 意思是映射分布被一些不相关的信息所干扰,是可以用降维的方式去可视化的。


更多细节参考原论文,Prompt 效果就不赘述了,百度开发的 UIE 模型在 NLP 就很强大!

4.2.8 SNCSE(Unsupervised):2022.01

https://arxiv.org/abs/2201.05979


SNCSE 同样是由微软团队提出,主要是针对以上方法存在的问题:当前对比学习的数据增强方式,获取的正样本都极为相似,导致模型存在特征抑制,即模型不能区分文本相似度和语义相似度,并更偏向具有相似文本,而不考虑它们之间的实际语义差异。



为了减轻特征抑制,该论文提出了通过软负样本结合双向边际损失的无监督句子嵌入对比学习方法。其中,软负样本,即具有高度相似,但与原始样本在语义上存在明显的差异的样本。双向边际损失,即通过扩大原始样本与正例和原始样本与软负例之间的距离,使模型更好地学习到句子之间的语义差别。软负样本构造:为原文本添加显示的否定词。


  • 在获取句子表征时,受 PromptBERT 启发,通过三种模板表示原样本、正样本和软负样本:


4.2.9 DiffCSE(Unsupervised):2022.04

https://arxiv.org/pdf/2204.10298.pdf


结合句子间差异的无监督句子嵌入对比学习方法——DiffCSE 主要还是在 SimCSE 上进行优化(可见 SimCSE 的重要性),通过 ELECTRA 模型的生成伪造样本和 RTD(Replaced Token Detection)任务,来学习原始句子与伪造句子之间的差异,以提高句向量表征模型的效果。



其思想同样来自于 CV 领域(采用不变对比学习和可变对比学习相结合的方法可以提高图像表征的效果)。作者提出使用基于 dropout masks 机制的增强作为不敏感转换学习对比学习损失和基于 MLM 语言模型进行词语替换的方法作为敏感转换学习「原始句子与编辑句子」之间的差异,共同优化句向量表征。


在 SimCSE 模型中,采用 pooler 层(一个带有 tanh 激活函数的全连接层)作为句子向量输出。该论文发现,采用带有 BN 的两层 pooler 效果更为突出,BN 在 SimCSE 模型上依然有效。


  • ①对于掩码概率,经实验发现,在掩码概率为 30%时,模型效果最优。

  • ②针对两个损失之间的权重值,经实验发现,对比学习损失为 RTD 损失 200 倍时,模型效果最优。


参考链接:https://blog.csdn.net/PX2012007/article/details/127696477

4.2.10 小结

SimCSE 以来几种比较重要的文本增强式的对比学习算法,按时间顺序,理论上应该是距离越近的算法效果越好,但使用时,还是要结合具体的业务场景,算法没有好坏,还是用看怎么用。对于有些内容,可能叙述的不是很细致或是需要一定的知识铺垫,感兴趣的同学可以针对性的研读论文和辅助其他资料。当然,算法层出不穷,更新很快,后续出现比较重要的对比学习算法。

5.文本匹配常见思路(技巧提升)

  • TextCNN/TEXTRNN

  • Siamese-RNN

  • 采用多种 BERT 类预训练模型

  • 对单模型进行调参

  • 多模型融合

  • BERT 后接上 RCNN/RNN/CNN/LSTM/Siamese 等等

5.1 方案一

特征工程


  1. 数据清洗:大赛给的数据比较规整,数据清洗部分工作不多,简单做了特殊字符处理等操作。

  2. 数据增强


  • 传递闭包扩充(标签传递)


根据 IF A=B and A=C THEN B=C 的规则,对正样本做了扩充增强。


根据 IF A=B and A!=C THEN B!=C 的规则,对负样本做了扩充增强。


在对负样本进行扩充后, 正负样本比例从原始的 1.4:1, 变成 2.9:1。 所以又对负样本进行了下采样, 是的正负样本比例 1:1。


  • 同义词替换


使用开源包 synormise 的效果不太好, 后面可以尝试使用公开医学预料训练 word2vec 模型来做同义词替换(时间问题, 没有尝试)。


随机删除,随机替换, 随机交换句式比较短, 随机删除更短。很多 query 仅仅相差一个单词, 随机替换改变语义。多数属于问句, 随机交换改变了语义。


  1. 模型选择


在预训练模型的基础上通过对抗训练增强模型的泛化性能。


  • BRETBert 的一个下游基础任务语句对分类(Sentence Pair Classification Task), [CLS] Bert 的输出有一个维度的向量表示

  • BERT+CNN(LSTM)将 BERT 的输出特征作为文本的表示向量, 然后后面再接上 LSTM 或者 CNN(效果下降)

  • BERT+siamese 将大赛提供的 category 信息利用上, 借用孪生网络的思想与两个 Query 进行拼接(效果下降)。


  1. 结果分析


  • 单模型线上效果


目前所训练的模型中:


小模型中 BERT-wwm-ext 表现是最好的,


大模型中 RoBERTa-large-pair 表现最好。


在现有的资源和模型上, 对单模型的参数寻优到达一个天花板,线上最高的分数为 0.9603。后面开始探索多模型融合。


  • 多模型融合线上效果


将不同类型的预训练模型作为基模型进行多模型融合。基模型的挑选准则基于单模型的线上提交效果,从不同类型的单模型中挑选线上表现最好的参数, 重新训练融合。


基模型:


BERT-wwm-ext + FGM


RoBERTa-large-pair + FGM


Ernie(BaiDu)+ FGM


模型融合策略使用的是 averaging, 为了降低差别比较小的模型对结果的影响,采用 sigmoid 反函数的方式进行 ensemble。


关于对抗训练在 NLP 中的作用,引用大佬的一句话叫缘,妙不可言~

5.2 方案二

  1. 探索分析


文本长度:训练集和验证集分布类似,大都集中在 10-20 个字



标签分布




总体思路



  1. 数据划分


采用 kfold 交叉验证(右边的划分方式)


•利用全部数据,获得更多信息


•降低方差,提高模型性能



  1. 模型设计



二分类交叉熵损失函数:



  1. 模型融合


小模型同时加入 CHIP2019 数据训练



  1. 数据预处理


对称扩充、传递扩充(注意要保持原来的分布,否则会过拟合)



  1. 训练


  • 三种结构:(实际使用差别不大,第一种又好又简单)

  • 对抗训练



#代码来自苏剑林bert4keras
def adversarial_training(model, embedding_name, epsilon=1): """给模型添加对抗训练 其中model是需要添加对抗训练的keras模型,embedding_name 则是model里边Embedding层的名字。要在模型compile之后使用。 """ if model.train_function is None: # 如果还没有训练函数 model._make_train_function() # 手动make old_train_function = model.train_function # 备份旧的训练函数
# 查找Embedding层 for output in model.outputs: embedding_layer = search_layer(output, embedding_name) if embedding_layer is not None: break if embedding_layer is None: raise Exception('Embedding layer not found')
# 求Embedding梯度 embeddings = embedding_layer.embeddings # Embedding矩阵 gradients = K.gradients(model.total_loss, [embeddings]) # Embedding梯度 gradients = K.zeros_like(embeddings) + gradients[0] # 转为dense tensor
# 封装为函数 inputs = (model._feed_inputs + model._feed_targets + model._feed_sample_weights) # 所有输入层 embedding_gradients = K.function( inputs=inputs, outputs=[gradients], name='embedding_gradients', ) # 封装为函数
def train_function(inputs): # 重新定义训练函数 grads = embedding_gradients(inputs)[0] # Embedding梯度 delta = epsilon * grads / (np.sqrt((grads**2).sum()) + 1e-8) # 计算扰动 K.set_value(embeddings, K.eval(embeddings) + delta) # 注入扰动 outputs = old_train_function(inputs) # 梯度下降 K.set_value(embeddings, K.eval(embeddings) - delta) # 删除扰动 return outputs
model.train_function = train_function # 覆盖原训练函数 写好函数后,启用对抗训练只需要一行代码adversarial_training(model, 'Embedding-Token', 0.5)
复制代码


  1. 预测


  • 算数平均→几何平均→sigmoid 平均(用反函数取出 sigmoid/softmax 归一化之前的状态做平均,信息量更大,提升明显)



  • 分类阈值微调(0.47)

  • 伪标签



5.3 更多方案

更多方案就不一一展开了,参考下方链接:


https://tianchi.aliyun.com/notebook/101626


https://tianchi.aliyun.com/notebook/101648


https://tianchi.aliyun.com/notebook/101648


参考链接:


https://tianchi.aliyun.com/competition/entrance/231776/forum


https://tianchi.aliyun.com/notebook/102057

6.特定领域知识图谱(Domain-specific KnowledgeGraph:DKG)融合方案(重点!)

在前面技术知识下可以看看后续的实际业务落地方案和学术方案


关于图神经网络的知识融合技术学习参考下面链接PGL图学习项目合集&数据集分享&技术归纳业务落地技巧[系列十]


从入门知识到经典图算法以及进阶图算法等,自行查阅食用!


文章篇幅有限请参考专栏按需查阅:NLP知识图谱相关技术业务落地方案和码源

6.1 特定领域知识图谱知识融合方案(实体对齐):优酷领域知识图谱为例

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128614951

6.2 特定领域知识图谱知识融合方案(实体对齐):文娱知识图谱构建之人物实体对齐

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128673963

6.3 特定领域知识图谱知识融合方案(实体对齐):商品知识图谱技术实战

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128674429

6.4 特定领域知识图谱知识融合方案(实体对齐):基于图神经网络的商品异构实体表征探索

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128674929

6.5 特定领域知识图谱知识融合方案(实体对齐)论文合集

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128675199


论文资料链接:两份内容不相同,且按照序号从小到大重要性依次递减


知识图谱实体对齐资料论文参考(PDF)+实体对齐方案+特定领域知识图谱知识融合方案(实体对齐)


知识图谱实体对齐资料论文参考(CAJ)+实体对齐方案+特定领域知识图谱知识融合方案(实体对齐)

6.6 知识融合算法测试方案(知识生产质量保障)

方案链接:https://blog.csdn.net/sinat_39620217/article/details/128675698

7.总结

本项目主要围绕着特定领域知识图谱(Domain-specific KnowledgeGraph:DKG)融合方案:技术知识前置【一】-文本匹配算法、知识融合学术界方案、知识融合业界落地方案、算法测评 KG 生产质量保障讲解了文本匹配算法的综述,从经典的传统模型到孪生神经网络“双塔模型”再到预训练模型以及有监督无监督联合模型,期间也涉及了近几年前沿的对比学习模型,之后提出了文本匹配技巧提升方案,最终给出了 DKG 的落地方案。这边主要以原理讲解和技术方案阐述为主,之后会慢慢把项目开源出来,一起共建 KG,从知识抽取到知识融合、知识推理、质量评估等争取走通完整的流程。


部分参考链接:


文本匹配算法综述


文本匹配相关知识整理


【NLP】对比学习——文本匹配(一)


【NLP】对比学习——文本匹配(二)


1.《对比学习》https://zhuanlan.zhihu.com/p/434823574


2.《BERT-Flow:BERT 词向量的性质分析+标准化流》https://zhuanlan.zhihu.com/p/337134133


3.《BERT-flow:CMUx 字节提出的文本表示新 SOTA》https://zhuanlan.zhihu.com/p/318061606


4.《BERT-flow: Sentence-BERT + Normalizing flows》https://zhuanlan.zhihu.com/p/331807184


5.《细说 Bert-whitening 的原理》https://zhuanlan.zhihu.com/p/380874824


6.《ACL 2021|美团提出基于对比学习的文本表示模型,效果相比 BERT-flow 提升 8%》https://tech.meituan.com/2021/06/03/acl-2021-consert-bert.html


发布于: 刚刚阅读数: 4
用户头像

汀丶

关注

本博客将不定期更新关于NLP等领域相关知识 2022-01-06 加入

本博客将不定期更新关于机器学习、强化学习、数据挖掘以及NLP等领域相关知识,以及分享自己学习到的知识技能,感谢大家关注!

评论

发布
暂无评论
特定领域知识图谱(DKG)融合方案:技术知识前置【一】-文本匹配算法、知识融合学术界方案、知识融合业界落地方案、算法测评KG生产质量保障_自然语言处理_汀丶_InfoQ写作社区