做网站公司怎么做,网站推广计划书范文500字,网站建设属于会计哪个科目,一站式网站建设价格NLP文本匹配任务Text Matching [无监督训练]#xff1a;SimCSE、ESimCSE、DiffCSE 项目实践
文本匹配多用于计算两个文本之间的相似度#xff0c;该示例会基于 ESimCSE 实现一个无监督的文本匹配模型的训练流程。文本匹配多用于计算两段「自然文本」之间的「相似度」。
例如…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 就应当尽可能的被推远。 具体来讲一个 batch 内每个句子会过 2 次模型得到 2 * batch 个向量将这些句子中通过同样句子得到的向量设置为正例其他设置为负例。
假设 a1 和 a2 是由句子 a 过两次模型得到的结果那么一个 batch 内的正负例构建如下所示
a1a2b1b2c1c2a1-10010000a21-1000000b100-100100b2001-10000c10000-1001c200001-100
其中对角线上的 - 100 表示自身和自身不做相似度比较。
2. SimCSE 的缺点
从 SimCSE 的正例构建中我们可以看出来所有的正例都是由「同一个句子」过了两次模型得到的。这就会造成一个问题模型会更倾向于认为长度相同的句子就代表一样的意思。由于数据样本是随机选取的那么很有可能在一个 batch 内采样到的句子长度是不相同的。 为了解决这个问题我们最终采取的实现方式为 ESimCSE。
3. ESimCSE 解决模型对文本长度的敏感问题
ESimCSE 通过随机重复单词Word Repetition的方式来构建正例巧妙的解决了句子长度敏感性的问题
ESimCSE: Enhanced Sample Building Method for Contrastive Learning of Unsupervised Sentence Embedding
要想消除模型对句子长度的敏感我们就需要在构建正例的时候让输入句子的长度发生改变如下所示 那么改变句子长度通常有 3 种方法随机删除、随机添加、同义词替换但它们均存在句意变化的风险
方法原句子变换后的句子句意是否改变随机删除我 [不] 喜欢你我喜欢你是随机添加今天的饭好吃今天的饭 [不] 好吃是同义词替换小明长得像一只 [狼]小明长得像一只 [狗]是
用语义变换后的句子去构建正例模型效果自然会受到影响。
那如果我们随机重复一些单词呢
方法原句子变换后的句子句意是否改变随机重复单词今天天气很好今今天天气很好好否随机重复单词我喜欢你我我喜欢欢你否
可以看到通过随机重复单词既能够改变句子长度又不会轻易改变语义。
实现上假设我们有一个 batch 的句子我们先依次将每一个句子都进行随机单词重复产生正例如下
origin - [人和畜生的区别, 今天天气很好, 三星手机屏幕是不是最好的]
repetition - [人人和畜生的的区别, 今今天天气很好好, 三星星手机屏屏幕是不是最最好好的]
随后我们将 origin 的 embeddingbatch768 和 repetition 的 embeddingbatch768做矩阵乘法可以得到一个矩阵batchbatch矩阵对角线上就是正例其余的均是负例
句子 a句子 b句子 c句子 a0.92480.23420.4242句子 b0.31420.91230.1422句子 c0.29030.18570.9983
矩阵中第ij个元素代表 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,devicecpu) - 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_idsquery_input_ids,token_type_idsquery_token_type_ids) # (batch, self.output_embedding_dim)doc_embedding self.get_pooled_embedding(input_idsdoc_input_ids,token_type_idsdoc_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_valueself.margin)).to(device)cos_sim cos_sim - margin_diag # 主对角线正例的余弦相似度都减掉 margincos_sim * self.scale # 缩放相似度便于收敛labels torch.arange( # 只有对角上为正例其余全是负例所以这个batch样本标签为 - [0, 1, 2, ...]0, query_embedding.size()[0], dtypetorch.int64).to(device)loss self.criterion(cos_sim, labels)return loss
4.DiffCSE
结合句子间差异的无监督句子嵌入对比学习方法——DiffCSE主要还是在SimCSE上进行优化可见SimCSE的重要性通过ELECTRA模型的生成伪造样本和RTDReplaced Token Detection任务来学习原始句子与伪造句子之间的差异以提高句向量表征模型的效果。 其思想同样来自于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:0000: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 文件下将会保存训练曲线图 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 下载
更多优质内容请关注公号汀丶人工智能会提供一些相关的资源和优质文章免费获取阅读。