轻松使用阿里达摩院开源在魔搭社区上的CLUE语义匹配模型

简介: 本文将介绍达摩院NLP团队在魔搭社区(ModelScope)上开源的语义匹配模型及其使用方法。

简介

CLUE(中文语言理解测评基准)是中文语言理解领域的权威榜单,包含多项测评任务。近日,达摩院NLP团队在其中的语义匹配榜登顶,并在魔搭社区(ModelScope)上开源了预训练和微调后的模型。本文将介绍该模型及其使用方法。

模型链接:https://modelscope.cn/models/damo/nlp_masts_sentence-similarity_clue_chinese-large/summary

CLUE语义匹配榜(截止到2022-12-07)

CLUE语义匹配任务

CLUE作为最常用的中文NLP模型的评估基准,其各个榜单的排名已经成为衡量NLP技术水平的重要指标,推动着NLP技术的不断进步和突破。语义匹配是NLP领域中的一个重要的任务,旨在从语义上衡量两段文本的相关性。

语义匹配在产业界有着广泛的应用场景,如社区问答、信息检索和推荐等。在搜索相关性场景下,语义匹配用于衡量Query和Document的相关程度,是搜索引擎中的重要一环。基于针对大搜场景的搜索相关性数据集,CLUE构建了语义匹配榜,吸引了众多国内的NLP团队参与。

通常来讲,语义匹配是一个二分类问题,即两段文本相关或不相关。而CLUE语义匹配榜对文本的相关性进行了进一步的细化,分成了三档,即“0”代表相关程度差,“1”代表有一定相关性,“2”代表非常相关,数字越大表示相关性越高。此外,CLUE语义匹配数据集也融合了相关性、权威性、内容质量、 时效性等维度。

MaSTS模型

此次达摩院NLP团队登顶CLUE语义匹配榜,得益于其在预训练和语义匹配领域的长期的耕耘,以及对相关算法的持续跟进迭代。预训练技术通常能够给多个NLP下游任务带来提升,如文本分类,序列标注和阅读理解。而领域适应预训练同样能够在各业务领域带来显著的帮助[1]。达摩院NLP团队针对搜索相关性领域开发了一套新的预训练方法MaSTS,改进了MLM任务的掩码策略,较通用模型能够获得更好的效果。

在微调阶段,模型采用了基于交互的深度语义匹配方法[2]。基于MaSTS预训练模型,将Query的文本(Text 1)和Document的文本(Text 2)通过特殊字符SEP拼接在一起,通过多个Transformer建立Query和Document文本之间的匹配信号。最终基于特殊字符CLS通过MLP网络计算各个相关性的概率。将多个微调后的模型基于相关性的概率进行集成后,最终输出的结果在CLUE语义匹配榜获得了榜首。相关预训练和微调后的模型已经在魔搭社区(ModelScope)上开源,并可以轻松上手使用。

魔搭社区(ModelScope)是由阿里巴巴达摩院,联合CCF开源发展委员会,共同作为项目发起方成立的一个模型开源社区及创新平台。 达摩院的众多业界领先模型都在魔搭社区上开源。打开魔搭社区提供的Notebook,就能够非常简易地调用MaSTS中文文本相似度模型,以及微调MaSTS预训练模型。

使用教程

接下来我们介绍如何轻松使用阿里达摩院开源在魔搭社区上的CLUE语义匹配模型。

模型微调

首先载入QBQTC数据集。与之前的方法类似,我们也将Dev集加入训练[3]

frommodelscope.msdatasetsimportMsDatasetfromdatasetsimportconcatenate_datasetsdataset_id='QBQTC'# 载入训练集train_dataset=MsDataset.load(dataset_id, namespace='damo', subset_name='default', split='train', keep_default_na=False)
dev_dataset=MsDataset.load(dataset_id, namespace='damo', subset_name='default', split='validation', keep_default_na=False)
train_dataset._hf_ds=concatenate_datasets([train_dataset._hf_ds, dev_dataset._hf_ds])  # 随版本更新该方法可能失效# 载入公开测试集eval_dataset=MsDataset.load(dataset_id, namespace='damo', subset_name='public', split='test', keep_default_na=False)
print("训练集:")
print(train_dataset._hf_ds)
print("公开测试集:")
print(eval_dataset._hf_ds)
训练集:
Dataset({
    features: ['id', 'query', 'title', 'label'],
    num_rows: 200000
})
公开测试集:
Dataset({
    features: ['id', 'query', 'title', 'label'],
    num_rows: 5000
})

基于MaSTS预训练模型-CLUE语义匹配,在载入的训练集上进行微调。

调整训练的超参数。根据GPU的显存调整BATCH_SIZE,推荐使用官方的超参数,即BATCH_SIZE=64。

importos.pathasospfrommodelscope.trainersimportbuild_trainerfrommodelscope.utils.hubimportread_configmodel_id='damo/nlp_masts_backbone_clue_chinese-large'WORK_DIR='./workspace'BATCH_SIZE=64# 推荐使用官方的超参数cfg=read_config(model_id, revision='v1.0.0')
cfg.train.work_dir=WORK_DIRcfg_file=osp.join(WORK_DIR, 'train_config.json')
cfg.train.max_epochs=7# train_dataloader的配置cfg.train.dataloader.batch_size_per_gpu=BATCH_SIZEcfg.train.optimizer.lr=2.0e-5# lr_scheduler的配置cfg.train.lr_scheduler= {
'type': 'LinearLR',
'start_factor': 1.0,
'end_factor': 0.0,
'total_iters':
int(cfg.train.max_epochs*len(train_dataset) //BATCH_SIZE),
'options': {
'warmup': {
'type': 'LinearWarmup',
'warmup_iters': int(cfg.train.max_epochs*len(train_dataset) *0.9//BATCH_SIZE)
        },
'by_epoch': False    }
}
cfg.dump(cfg_file)
kwargs=dict(
model=model_id,
model_revision='v1.0.0',
train_dataset=train_dataset,
eval_dataset=eval_dataset,
cfg_file=cfg_file,
)
trainer=build_trainer(default_args=kwargs)
print('===============================================================')
print('pre-trained model loaded, training started:')
print('===============================================================')
trainer.train()
print('===============================================================')
print('train success.')
print('===============================================================')
foriinrange(cfg.train.max_epochs):
eval_results=trainer.evaluate(f'{WORK_DIR}/epoch_{i+1}.pth')
print(f'epoch {i} evaluation result:')
print(eval_results)
print('===============================================================')
print('evaluate success')
print('===============================================================')

模型预测

使用多个模型集成,并提交最终的结果。这里以基于MaSTS,RoBERTa和StructBERT三个预训练底座训练得到的模型为例。首先载入这三个训练好的模型。

frommodelscope.modelsimportModelfromtransformersimportBertTokenizertokenizer=BertTokenizer.from_pretrained('bert-base-chinese')
masts_model=Model.from_pretrained('damo/nlp_masts_sentence-similarity_clue_chinese-large', revision='v1.0.0')
roberta_model=Model.from_pretrained('damo/nlp_roberta_sentence-similarity_clue_chinese-large', revision='v1.0.0')
structbert_model=Model.from_pretrained('damo/nlp_structbert_sentence-similarity_clue_chinese-large', revision='v1.0.0')

测试这三个模型在公开测试集上的效果。

基于MaSTS的模型在公开测试集上的效果要优于另外两个模型。

deftokenize_and_align_labels(examples):
# tokenize the textstokenized_inputs=tokenizer(
examples["query"],
examples["title"],
padding="max_length",
truncation=True,
max_length=512,
    )
if"label"inexamples:
tokenized_inputs["labels"] = [int(l) forlinexamples["label"]]
returntokenized_inputstokenized_eval_dataset=eval_dataset._hf_ds.map(
tokenize_and_align_labels,
batched=True,
remove_columns=eval_dataset._hf_ds.column_names,
desc="Running tokenizer on datasets",
)
importtorchfromtorch.utils.data.dataloaderimportDataLoaderfromtransformersimportDataCollatorWithPaddingfromsklearnimportmetrics@torch.no_grad()
defevaluate(
model,
tokenizer,
eval_dataset,
batch_size: int=512,
):
model=model.cuda().eval()
data_collator=DataCollatorWithPadding(tokenizer=tokenizer)
eval_dataloader=DataLoader(
eval_dataset,
batch_size=batch_size,
shuffle=False,
collate_fn=data_collator,
pin_memory=True,
num_workers=4,
    )
predictions= []
forbatchineval_dataloader:
batch= {k: v.to(model.device) fork, vinbatch.items()}
outputs=model(
input_ids=batch["input_ids"],
attention_mask=batch["attention_mask"],
token_type_ids=batch["token_type_ids"],
        )
y_pred=outputs.logits.argmax(-1)
predictions+=y_pred.tolist()
references=eval_dataset["labels"]
accuracy=metrics.accuracy_score(references, predictions)
f1=metrics.f1_score(references, predictions, average="macro")
returnaccuracy, f1accuracy, f1=evaluate(masts_model, tokenizer, tokenized_eval_dataset)
print(f"MaSTS accuracy: {accuracy}, marco f1: {f1}")
accuracy, f1=evaluate(roberta_model, tokenizer, tokenized_eval_dataset)
print(f"RoBERTa accuracy: {accuracy}, marco f1: {f1}")
accuracy, f1=evaluate(structbert_model, tokenizer, tokenized_eval_dataset)
print(f"StructBERT accuracy: {accuracy}, marco f1: {f1}")
MaSTS accuracy: 0.797, marco f1: 0.7408626647960889
RoBERTa accuracy: 0.785, marco f1: 0.7333059055826837
StructBERT accuracy: 0.7896, marco f1: 0.7358745897202524

载入榜单测试集。

leaderboard_eval_dataset=MsDataset.load(dataset_id, namespace='damo', subset_name='default', split='test', keep_default_na=False)
tokenized_leaderboard_eval_dataset=leaderboard_eval_dataset._hf_ds.map(
tokenize_and_align_labels,
batched=True,
remove_columns=leaderboard_eval_dataset._hf_ds.column_names,
desc="Running tokenizer on datasets",
)
print("榜单测试集:")
print(leaderboard_eval_dataset._hf_ds)
榜单测试集:
Dataset({
    features: ['id', 'query', 'title', 'label'],
    num_rows: 10000
})

集成三个模型输出的logits,并产生最终的结果。

importtorchfromtorch.utils.data.dataloaderimportDataLoaderfromtransformersimportDataCollatorWithPaddingfromsklearnimportmetrics@torch.no_grad()
definference(
model,
tokenizer,
eval_dataset,
batch_size: int=512,
):
model=model.cuda().eval()
data_collator=DataCollatorWithPadding(tokenizer=tokenizer)
eval_dataloader=DataLoader(
eval_dataset,
batch_size=batch_size,
shuffle=False,
collate_fn=data_collator,
pin_memory=True,
num_workers=4,
    )
logits= []
forbatchineval_dataloader:
batch= {k: v.to(model.device) fork, vinbatch.items()}
outputs=model(
input_ids=batch["input_ids"],
attention_mask=batch["attention_mask"],
token_type_ids=batch["token_type_ids"],
        )
logits.append(outputs.logits.cpu())
logits=torch.cat(logits)
returnlogitsmasts_logits=inference(masts_model, tokenizer, tokenized_leaderboard_eval_dataset)
roberta_logits=inference(roberta_model, tokenizer, tokenized_leaderboard_eval_dataset)
structbert_logits=inference(structbert_model, tokenizer, tokenized_leaderboard_eval_dataset)
importjson# 集成三个模型的logits输出ensemble_logits=torch.stack([masts_logits, roberta_logits, structbert_logits]).mean(0)
predictions=logits.argmax(-1).tolist()
# 输出预测文件提交评测系统withopen("qbqtc_predict.json", "w") asf:
foridx, pinenumerate(predictions):
json.dump({"id": idx, "label": str(p)}, f)
f.write("\n")

集成这3个模型的榜单评测结果为 marco f1: 75.464, accuracy: 80.940

总结

本文介绍了阿里达摩院开源在魔搭社区上的CLUE语义匹配模型及其使用教程,通过简单的模型融合策略,可以获得不错的结果。从BERT的开源到T5,再到最近的ChatGPT,语言模型以极快的速度发展。达摩院NLP团队希望通过开源开放进一步推动NLP技术在国内的发展和应用,帮助开发者轻松上手前沿的模型算法,并构建自己的语言模型和AI应用。


参考文献

[1] Suchin Gururangan, Ana Marasovic, Swabha Swayamdipta, Kyle Lo, Iz Beltagy, Doug Downey, Noah A. Smith. Don't Stop Pretraining: Adapt Language Models to Domains and Tasks. ACL 2020: 8342-8360

[2] Rodrigo Frassetto Nogueira, Wei Yang, Kyunghyun Cho, Jimmy Lin. Multi-Stage Document Ranking with BERT. CoRR abs/1910.14424 (2019)

[3] Junjie Wang, Yuxiang Zhang, Ping Yang, Ruyi Gan. Towards No.1 in CLUE Semantic Matching Challenge: Pre-trained Language Model Erlangshen with Propensity-Corrected Loss. CoRR abs/2208.02959 (2022)

相关文章
|
7天前
|
机器学习/深度学习 开发者 内存技术
阶跃星辰 Step 3.5 Flash 预训练/中训练/训练框架全部开源!
阶跃星辰开源Step 3.5 Flash——迄今最强开源Agent基座模型,含Base/Midtrain权重及Steptron全栈训练框架,支持预训练、SFT与强化学习,专为智能体设计。已登OpenRouter榜首,获社区广泛好评。(239字)
210 22
|
SQL 存储 负载均衡
MySQL实战 主从同步(原理+实战)
MySQL实战 主从同步(原理+实战)
MySQL实战 主从同步(原理+实战)
|
5月前
|
存储 人工智能 前端开发
超越问答:深入理解并构建自主决策的AI智能体(Agent)
如果说RAG让LLM学会了“开卷考试”,那么AI智能体(Agent)则赋予了LLM“手和脚”,使其能够思考、规划并与真实世界互动。本文将深入剖析Agent的核心架构,讲解ReAct等关键工作机制,并带你一步步构建一个能够调用外部工具(API)的自定义Agent,开启LLM自主解决复杂任务的新篇章。
1016 6
|
3月前
|
JSON 安全 JavaScript
HTTPS 原理
HTTPS是HTTP与SSL/TLS的结合,通过数字证书验证身份,利用非对称加密安全交换会话密钥,再以对称加密高效传输数据。它确保了通信的机密性、完整性和服务器真实性,在互联网上构建安全加密通道。
|
人工智能 JSON Rust
用 Rust 实现敏感信息拦截插件,提升 AI 网关安全防护能力
本⽂对敏感信息拦截插件的使用方式和实现原理进行了简单介绍,它能够自动检测并处理请求和响应中的敏感词,有效防止敏感信息泄露。通过对不同数据范围的支持和灵活的配置选项,该插件能够适应各种应用场景,确保数据的安全性和合规性。
714 96
|
10月前
|
Ubuntu 安全
Ubuntu中遇到"无法创建临时文件"/tmp/..."在普通或root用户运行apt-get update时的错误解决办法
这些步骤当然不能涵盖所有可能出现问题的场合,但是能覆盖大多数常见的情景。希望这些信息能帮到你解决"无法创建临时文件"/tmp/..."这样的问题。不过,请记住,因为修改系统文件和目录的权限,清理临时文件,或者运行磁盘检查,都可能对系统造成影响,所以执行这些操作前要先确认这是安全的,必要时最好先做好数据备份。
686 10
|
决策智能 数据库 开发者
使用Qwen2.5+SpringBoot+SpringAI+SpringWebFlux的基于意图识别的多智能体架构方案
本项目旨在解决智能体的“超级入口”问题,通过开发基于意图识别的多智能体框架,实现用户通过单一交互入口使用所有智能体。项目依托阿里开源的Qwen2.5大模型,利用其强大的FunctionCall能力,精准识别用户意图并调用相应智能体。 核心功能包括: - 意图识别:基于Qwen2.5的大模型方法调用能力,准确识别用户意图。 - 业务调用中心:解耦框架与业务逻辑,集中处理业务方法调用,提升系统灵活性。 - 会话管理:支持连续对话,保存用户会话历史,确保上下文连贯性。 - 流式返回:支持打字机效果的流式返回,增强用户体验。 感谢Qwen2.5系列大模型的支持,使项目得以顺利实施。
4399 8
使用Qwen2.5+SpringBoot+SpringAI+SpringWebFlux的基于意图识别的多智能体架构方案
|
数据采集 机器学习/深度学习 自然语言处理
ModelScope模型库体验之中文StructBERT系列预训练语言模型
StructBERT在BERT的基础上提出改进优化,通过在句子级别和词级别引入两个新的目标函数,打乱句子/词的顺序并使模型对其进行还原的方式,能让机器更好地掌握人类语法,加深对自然语言的理解,使得模型学习到更强的语言结构信息。
48180 0
ModelScope模型库体验之中文StructBERT系列预训练语言模型

热门文章

最新文章