NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践

这篇具有很好参考价值的文章主要介绍了NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践

文本匹配多用于计算两个文本之间的相似度,该示例会基于 ESimCSE 实现一个无监督的文本匹配模型的训练流程。文本匹配多用于计算两段「自然文本」之间的「相似度」。

例如,在搜索引擎中,我们通常需要判断用户的搜索内容是否相似:

A:蛋黄吃多了有什么坏处    B:吃鸡蛋白过多有什么坏处  ->  不相似
A:蛋黄吃多了有什么坏处    B:蛋黄可以多吃吗         ->  相似
...

那最直觉的思路就是让人工去标注文本对,再喂给模型去学习,这种方法称为基于「监督学习」训练出的模型:

但是,如果我们今天没有这么多的标注数据,只有一大堆的「未标注」数据,我们还能训练一个匹配模型吗?这种不依赖于「人工标注数据」的方式,就叫做「无监督」(或自监督)学习方式。我们今天要讲的 SimCSE, 就是一种「无监督」训练模型。

SimCSE: Simple Contrastive Learning of Sentence Embeddings

1.SimCSE 是如何做到无监督的?

SimCSE 将对比学习(Contrastive Learning)的思想引入到文本匹配中。对比学习的核心思想就是:将相似的样本拉近,将不相似的样本推远

但现在问题是:我们没有标注数据,怎么知道哪些文本是相似的,哪些是不相似的呢?SimCSE 相出了一种很妙的办法,由于预训练模型在训练的时候通常都会使用 dropout 机制。这就意味着:即使是同一个样本过两次模型也会得到两个不同的 embedding。而因为同样的样本,那一定是相似的,模型输出的这两个 embedding 距离就应当尽可能的相近;反之,那些不同的输入样本过模型后得到的 embedding 就应当尽可能的被推远。

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践,NLP知识领域专栏,自然语言处理,人工智能,语义匹配,文本匹配,SimCSE,DiffCSE

具体来讲,一个 batch 内每个句子会过 2 次模型,得到 2 * batch 个向量,将这些句子中通过同样句子得到的向量设置为正例,其他设置为负例。

假设 a1 和 a2 是由句子 a 过两次模型得到的结果,那么一个 batch 内的正负例构建如下所示:

a1 a2 b1 b2 c1 c2
a1 -100 1 0 0 0 0
a2 1 -100 0 0 0 0
b1 0 0 -100 1 0 0
b2 0 0 1 -100 0 0
c1 0 0 0 0 -100 1
c2 0 0 0 0 1 -100

其中,对角线上的 - 100 表示自身和自身不做相似度比较。

2. SimCSE 的缺点?

从 SimCSE 的正例构建中我们可以看出来,所有的正例都是由「同一个句子」过了两次模型得到的。这就会造成一个问题:模型会更倾向于认为,长度相同的句子就代表一样的意思。由于数据样本是随机选取的,那么很有可能在一个 batch 内采样到的句子长度是不相同的。

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践,NLP知识领域专栏,自然语言处理,人工智能,语义匹配,文本匹配,SimCSE,DiffCSE

为了解决这个问题,我们最终采取的实现方式为 ESimCSE

3. ESimCSE 解决模型对文本长度的敏感问题

ESimCSE 通过随机重复单词(Word Repetition)的方式来构建正例,巧妙的解决了句子长度敏感性的问题:

ESimCSE: Enhanced Sample Building Method for Contrastive Learning of Unsupervised Sentence Embedding

要想消除模型对句子长度的敏感,我们就需要在构建正例的时候让输入句子的长度发生改变,如下所示:

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践,NLP知识领域专栏,自然语言处理,人工智能,语义匹配,文本匹配,SimCSE,DiffCSE

那么,改变句子长度通常有 3 种方法:随机删除、随机添加、同义词替换,但它们均存在句意变化的风险:

方法 原句子 变换后的句子 句意是否改变
随机删除 我 [不] 喜欢你 我喜欢你
随机添加 今天的饭好吃 今天的饭 [不] 好吃
同义词替换 小明长得像一只 [狼] 小明长得像一只 [狗]

用语义变换后的句子去构建正例,模型效果自然会受到影响。

那如果我们随机重复一些单词呢?

方法 原句子 变换后的句子 句意是否改变
随机重复单词 今天天气很好 今今天天气很好好
随机重复单词 我喜欢你 我我喜欢欢你

可以看到,通过随机重复单词,既能够改变句子长度,又不会轻易改变语义。

实现上,假设我们有一个 batch 的句子,我们先依次将每一个句子都进行随机单词重复(产生正例),如下:

origin ->     ['人和畜生的区别', '今天天气很好', '三星手机屏幕是不是最好的?']
repetition -> ['人人和畜生的的区别', '今今天天气很好好', '三星星手机屏屏幕是不是最最好好的?']

随后,我们将 origin 的 embedding(batch,768) 和 repetition 的 embedding(batch,768)做矩阵乘法,可以得到一个矩阵(batch,batch),矩阵对角线上就是正例,其余的均是负例:

句子 a 句子 b 句子 c
句子 a 0.9248 0.2342 0.4242
句子 b 0.3142 0.9123 0.1422
句子 c 0.2903 0.1857 0.9983

矩阵中第(i,j)个元素代表 origin 列表中的第 i 个元素和 repetition 列表中第 j 个元素的相似度。

接下来就好构建训练标签了,因为 label 都在对角线上,所以第 n 行的 label 就是 n 。

labels = [i for i in range(len(origin))]     # labels = [0, 1, 2]

之后就用 CrossEntropyLoss 去计算并梯度回传就能开始训练啦。

def forward(
        self,
        query_input_ids: torch.tensor,
        query_token_type_ids: torch.tensor,
        doc_input_ids: torch.tensor,
        doc_token_type_ids: torch.tensor,
        device='cpu'
        ) -> torch.tensor:
        """
        传入query/doc对,构建正/负例并计算contrastive loss。

        Args:
            query_input_ids (torch.LongTensor): (batch, seq_len)
            query_token_type_ids (torch.LongTensor): (batch, seq_len)
            doc_input_ids (torch.LongTensor): (batch, seq_len)
            doc_token_type_ids (torch.LongTensor): (batch, seq_len)
            device (str): 使用设备

        Returns:
            torch.tensor: (1)
        """
        query_embedding = self.get_pooled_embedding(
            input_ids=query_input_ids,
            token_type_ids=query_token_type_ids
        )                                                           # (batch, self.output_embedding_dim)

        doc_embedding = self.get_pooled_embedding(
            input_ids=doc_input_ids,
            token_type_ids=doc_token_type_ids
        )                                                           # (batch, self.output_embedding_dim)
        
        cos_sim = torch.matmul(query_embedding, doc_embedding.T)    # (batch, batch)
        margin_diag = torch.diag(torch.full(                        # (batch, batch), 只有对角线等于margin值的对角矩阵
            size=[query_embedding.size()[0]], 
            fill_value=self.margin
        )).to(device)
        cos_sim = cos_sim - margin_diag                             # 主对角线(正例)的余弦相似度都减掉 margin
        cos_sim *= self.scale                                       # 缩放相似度,便于收敛

        labels = torch.arange(                                      # 只有对角上为正例,其余全是负例,所以这个batch样本标签为 -> [0, 1, 2, ...]
            0, 
            query_embedding.size()[0], 
            dtype=torch.int64
        ).to(device)
        loss = self.criterion(cos_sim, labels)

        return loss

4.DiffCSE

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

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践,NLP知识领域专栏,自然语言处理,人工智能,语义匹配,文本匹配,SimCSE,DiffCSE

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

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

①对于掩码概率,经实验发现,在掩码概率为30%时,模型效果最优。
②针对两个损失之间的权重值,经实验发现,对比学习损失为RTD损失200倍时,模型效果最优。

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

5. 数据集准备

项目中提供了一部分示例数据,我们使用未标注的用户搜索记录数据来训练一个文本匹配模型,数据在 data/LCQMC

若想使用自定义数据训练,只需要仿照示例数据构建数据集即可:

  • 训练集:
喜欢打篮球的男生喜欢什么样的女生
我手机丢了,我想换个手机
大家觉得她好看吗
晚上睡觉带着耳机听音乐有什么害处吗?
学日语软件手机上的
...
  • 测试集:
开初婚未育证明怎么弄?	初婚未育情况证明怎么开?	1
谁知道她是网络美女吗?	爱情这杯酒谁喝都会醉是什么歌	0
人和畜生的区别是什么?	人与畜生的区别是什么!	1
男孩喝女孩的尿的故事	怎样才知道是生男孩还是女孩	0
...

由于是无监督训练,因此训练集(train.txt)中不需要记录标签,只需要大量的文本即可。

测试集(dev.tsv)用于测试无监督模型的效果,因此需要包含真实标签。

每一行用 \t 分隔符分开,第一部分部分为句子A,中间部分为句子B,最后一部分为两个句子是否相似(label)

6.模型训练

修改训练脚本 train.sh 里的对应参数, 开启模型训练:

python train.py \
    --model "nghuyong/ernie-3.0-base-zh" \
    --train_path "data/LCQMC/train.txt" \
    --dev_path "data/LCQMC/dev.tsv" \
    --save_dir "checkpoints/LCQMC" \
    --img_log_dir "logs/LCQMC" \
    --img_log_name "ERNIE-ESimCSE" \
    --learning_rate 1e-5 \
    --dropout 0.3 \
    --batch_size 64 \
    --max_seq_len 64 \
    --valid_steps 400 \
    --logging_steps 50 \
    --num_train_epochs 8 \
    --device "cuda:0"

正确开启训练后,终端会打印以下信息:

...
0%|          | 0/2 [00:00<?, ?it/s]
100%|██████████| 2/2 [00:00<00:00, 226.41it/s]
DatasetDict({
    train: Dataset({
        features: ['text'],
        num_rows: 477532
    })
    dev: Dataset({
        features: ['text'],
        num_rows: 8802
    })
})
global step 50, epoch: 1, loss: 0.34367, speed: 2.01 step/s
global step 100, epoch: 1, loss: 0.19121, speed: 2.02 step/s
global step 150, epoch: 1, loss: 0.13498, speed: 2.00 step/s
global step 200, epoch: 1, loss: 0.10696, speed: 1.99 step/s
global step 250, epoch: 1, loss: 0.08858, speed: 2.02 step/s
global step 300, epoch: 1, loss: 0.07613, speed: 2.02 step/s
global step 350, epoch: 1, loss: 0.06673, speed: 2.01 step/s
global step 400, epoch: 1, loss: 0.05954, speed: 1.99 step/s
Evaluation precision: 0.58459, recall: 0.87210, F1: 0.69997, spearman_corr: 
0.36698
best F1 performence has been updated: 0.00000 --> 0.69997
global step 450, epoch: 1, loss: 0.25825, speed: 2.01 step/s
global step 500, epoch: 1, loss: 0.27889, speed: 1.99 step/s
global step 550, epoch: 1, loss: 0.28029, speed: 1.98 step/s
global step 600, epoch: 1, loss: 0.27571, speed: 1.98 step/s
global step 650, epoch: 1, loss: 0.26931, speed: 2.00 step/s
...

logs/LCQMC 文件下将会保存训练曲线图:

NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践,NLP知识领域专栏,自然语言处理,人工智能,语义匹配,文本匹配,SimCSE,DiffCSE

7.模型推理

完成模型训练后,运行 inference.py 以加载训练好的模型并应用:

...
    if __name__ == '__main__':
    ...
    sentence_pair = [
        ('男孩喝女孩的故事', '怎样才知道是生男孩还是女孩'),
        ('这种图片是用什么软件制作的?', '这种图片制作是用什么软件呢?')
    ]
    ...
    res = inference(query_list, doc_list, model, tokenizer, device)
    print(res)

运行推理程序:

python inference.py

得到以下推理结果:

[0.1527191698551178, 0.9263839721679688]   # 第一对文本相似分数较低,第二对文本相似分数较高

参考链接:https://github.com/HarderThenHarder/transformers_tasks/blob/main/text_matching/supervised

github无法连接的可以在:https://download.csdn.net/download/sinat_39620217/88214437 下载

更多优质内容请关注公号:汀丶人工智能;会提供一些相关的资源和优质文章,免费获取阅读。文章来源地址https://www.toymoban.com/news/detail-649085.html

到了这里,关于NLP文本匹配任务Text Matching [无监督训练]:SimCSE、ESimCSE、DiffCSE 项目实践的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 自然语言处理NLP:文本预处理Text Pre-Processing

    大家好,自然语言处理(NLP)是计算机科学领域与人工智能领域中的一个重要方向,其研究能实现人与计算机之间用自然语言进行有效通信的各种理论和方法。本文将介绍文本预处理的本质、原理、应用等内容,助力自然语言处理和模型的生成使用。 文本预处理是将原始文本数

    2024年04月26日
    浏览(51)
  • 【自然语言处理(NLP)】基于ERNIE语言模型的文本语义匹配

    作者简介 :在校大学生一枚,华为云享专家,阿里云专家博主,腾云先锋(TDP)成员,云曦智划项目总负责人,全国高等学校计算机教学与产业实践资源建设专家委员会(TIPCC)志愿者,以及编程爱好者,期待和大家一起学习,一起进步~ . 博客主页 : ぃ灵彧が的学习日志

    2024年02月10日
    浏览(63)
  • NLP | 基于LLMs的文本分类任务

    比赛链接:讯飞开放平台 来源:DataWhale AI夏令营3(NLP)   ①Roberta在预训练的阶段中没有对下一句话进行预测( NSP ) ②采用了 动态掩码 ③使用 字符级 和 词级别 表征的 混合文本编码 。 论文:https://arxiv.org/pdf/1907.11692.pdf   DataWhale Topline的改进:   特征1:平均池化Mean

    2024年02月11日
    浏览(36)
  • NLP文本生成全解析:从传统方法到预训练完整介绍

    本文深入探讨了文本生成的多种方法,从传统的基于统计和模板的技术到现代的神经网络模型,尤其是LSTM和Transformer架构。文章还详细介绍了大型预训练模型如GPT在文本生成中的应用,并提供了Python和PyTorch的实现代码。 关注TechLead,分享AI全维度知识。作者拥有10+年互联网服

    2024年02月05日
    浏览(45)
  • chatgpt实现NLP基本任务(实体识别、关系抽取、属性抽取、事件抽取、文本分类)

    抽取文本: 驻港部队从1993年初开始组建,1996年1月28日组建完毕,1997年7月1日0时进驻香港,取代驻港英军接管香港防务,驻港军费均由中央人民政府负担。《中华人民共和国香港特别行政区驻军法》规定了驻香港部队的职责为防备和抵抗侵略,保卫香港特别行政区的安全以及

    2024年02月13日
    浏览(48)
  • 基于SimCSE和Faiss的文本向量检索实践

    目录 文本的向量表示 1、SimCSE 2、支持无监督训 3、训练注意事项 向量检索 1、精准查找flat 2、HNSWx 3、IVFx 4、PQx 5、LSH 对博客标题进行向量检索 数据向量化 构建索引 文本检索 测试检索 传统的文本检索一般是建立倒排索引,对搜索词的召回结果进行打分排序返回最终结果,但

    2024年02月16日
    浏览(42)
  • 7个顶级开源数据集来训练自然语言处理(NLP)和文本模型

    推荐:使用 NSDT场景编辑器快速助你搭建可二次编辑的3D应用场景 NLP现在是一个令人兴奋的领域,特别是在像AutoNLP这样的用例中,但很难掌握。开始使用NLP的主要问题是缺乏适当的指导和该领域的过度广度。很容易迷失在各种论文和代码中,试图吸收所有内容。 要意识到的是

    2024年02月13日
    浏览(60)
  • [oneAPI] 基于BERT预训练模型的英文文本蕴含任务

    比赛:https://marketing.csdn.net/p/f3e44fbfe46c465f4d9d6c23e38e0517 Intel® DevCloud for oneAPI:https://devcloud.intel.com/oneapi/get_started/aiAnalyticsToolkitSamples/ 我们在Intel® DevCloud for oneAPI平台上构建了我们的实验环境,充分利用了其完全虚拟化的特性,使我们能够专注于模型的开发和优化,无需烦心底

    2024年02月11日
    浏览(35)
  • 模板匹配Template Matching

     实现代码: 运行结果:

    2024年02月11日
    浏览(45)
  • 【三】3D匹配Matching之可变形曲面匹配Deformable Surface—get_deformable_surface_matching_result()算子

    😊😊😊 欢迎来到本博客 😊😊😊 🌟🌟🌟 Halcon算子太多,学习查找都没有系统的学习查找路径,本专栏主要分享Halcon各类算子含义及用法,有时间会更新具体案例。 😊😊😊 具体食用方式:可以点击本专栏【Halcon算子快速查找】–搜索你要查询的算子名称;或者点击

    2024年02月09日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包