PaddleHub 文本匹配实战:基于 ERNIE 双塔(Siamese)模型的 Fine-tune 与预测指南
2026/9/23 1:38:42 网站建设 项目流程

PaddleHub 文本匹配实战:基于 ERNIE 双塔(Siamese)模型的 Fine-tune 与预测指南

【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers

本文以 PaddleHub 提供的 Transformer 预训练模型(ERNIE、BERT、RoBERTa 等)为核心,系统讲解如何以动态图方式在中文文本匹配数据集 LCQMC 上完成文本匹配任务的微调(Fine-tune)与预测。读者将掌握从模型选择、数据集加载、优化器与训练器配置,到模型评估与批量预测的完整实战流程,并理解 Sentence Transformer 双塔网络相比传统句对分类在计算效率上的核心优势。

文本匹配任务与预训练模型的演进

在 2017 年之前,工业界和学术界对 NLP 文本的处理主要依赖序列模型,如循环神经网络(Recurrent Neural Network, RNN)。随着深度学习的发展,模型参数数量飞速增长,为训练这些参数需要更大规模的数据集以避免过拟合。然而对于大部分 NLP 任务——尤其是句法、语义相关的任务——构建大规模标注数据集成本极高且非常困难;相比之下,大规模未标注语料库的构建则相对容易。

近年来的研究表明,基于大规模未标注语料库的预训练模型(Pretrained Models, PTM)能够习得通用的语言表示,将预训练模型 Fine-tune 到下游任务可获得出色表现,同时避免从零开始训练模型。本示例即展示如何使用 PaddleHub 的 Transformer 模型 Module(如 ERNIE、BERT、RoBERTa 等),以动态图方式完成文本匹配任务的 Fine-tune 与预测。

文本匹配的两种建模方案

方案一:句对拼接 + CLS 特征(高计算量)

使用预训练模型 ERNIE 完成文本匹配任务,一种直观做法是将 query 和 title 文本拼接后输入 ERNIE,取CLS特征(即 pooled_output),再接全连接层进行二分类。这本质上是将文本匹配建模为句对分类任务。

该方案的问题在于:ERNIE 的模型参数非常庞大,句对拼接输入导致计算量非常大,预测速度也不够理想,难以满足线上业务的延迟要求。针对这一问题,可以使用 Sentence Transformer 网络来优化计算量。

方案二:Sentence Transformer 双塔结构(推荐)

Sentence Transformer 采用了双塔(Siamese)的网络结构:Query 和 Title 分别输入 Transformer 网络,共享网络参数,得到各自的 token embedding 特征;随后对 token embedding 进行 pooling(本教程使用 mean pooling 操作),输出分别记作 u、v;最后将三个表征(u, v, |u-v|)拼接起来,进行二分类。更多关于 Sentence Transformer 的信息可参考论文 "Sentence-BERT: Sentence Embeddings using Siamese BERT-Networks"(arXiv:1908.10084)。

该结构在源码中得到完整印证。以ernie_tiny模块为例(modules/text/language_model/ernie_tiny/module.py):

  • task='text-matching'时,模型由ErnieModel.from_pretrained加载共享底座,并在其上加Dropout(0.1)与维度为hidden_size * 3 → 2Linear分类头,损失函数为CrossEntropyLoss,评估指标为paddle.metric.Accuracy()
  • 前向过程分别对 query 与 title 调用同一个self.model(参数共享),对 token embedding 按pad_token_id构造 attention mask 后求sum / mask得到query_meantitle_mean(即 mean pooling);
  • 随后计算sub = |query_mean - title_mean|,并concat([query_mean, title_mean, sub], axis=-1)得到 3 倍 hidden size 的特征,送入分类器得到 logits 与 softmax 概率。

这正是文档所述双塔网络 +(u, v, |u-v|)拼接的完整实现。

环境依赖

运行本示例需要:

  • paddlepaddle >= 2.0.0
  • paddlehub >= 2.0.0

如何开始 Fine-tune

我们以中文文本匹配数据集 LCQMC 为示例数据集,在训练集(train.tsv)上进行模型训练,并在开发集(dev.tsv)上验证、在测试集(test.tsv)上测试。使用 PaddleHub Fine-tune API 进行微调分为 4 个步骤。

Step1:选择模型

import paddlehub as hub model = hub.Module(name='ernie_tiny', version='2.0.2', task='text-matching')

参数说明:

  • name:模型名称,可以选择ernieernie_tinybert-base-casedbert-base-chineseroberta-wwm-extroberta-wwm-ext-large等;
  • version:Module 版本号;
  • task:Fine-tune 任务类型,此处为text-matching,表示文本匹配任务。

通过这一行代码,model即被初始化为一个适用于文本匹配任务的双塔(Siamese)结构模型。PaddleHub 还提供 BERT 等多种模型可供选择,当前支持文本匹配任务的模型对应加载示例如下:

模型名PaddleHub Module
ERNIE, Chinesehub.Module(name='ernie')
ERNIE tiny, Chinesehub.Module(name='ernie_tiny')
ERNIE 2.0 Base, Englishhub.Module(name='ernie_v2_eng_base')
ERNIE 2.0 Large, Englishhub.Module(name='ernie_v2_eng_large')
BERT-Base, English Casedhub.Module(name='bert-base-cased')
BERT-Base, English Uncasedhub.Module(name='bert-base-uncased')
BERT-Large, English Casedhub.Module(name='bert-large-cased')
BERT-Large, English Uncasedhub.Module(name='bert-large-uncased')
BERT-Base, Multilingual Casedhub.Module(name='bert-base-multilingual-cased')
BERT-Base, Multilingual Uncasedhub.Module(name='bert-base-multilingual-uncased')
BERT-Base, Chinesehub.Module(name='bert-base-chinese')
BERT-wwm, Chinesehub.Module(name='chinese-bert-wwm')
BERT-wwm-ext, Chinesehub.Module(name='chinese-bert-wwm-ext')
RoBERTa-wwm-ext, Chinesehub.Module(name='roberta-wwm-ext')
RoBERTa-wwm-ext-large, Chinesehub.Module(name='roberta-wwm-ext-large')
RBT3, Chinesehub.Module(name='rbt3')
RBTL3, Chinesehub.Module(name='rbtl3')
ELECTRA-Small, Englishhub.Module(name='electra-small')
ELECTRA-Base, Englishhub.Module(name='electra-base')
ELECTRA-Large, Englishhub.Module(name='electra-large')
ELECTRA-Base, Chinesehub.Module(name='chinese-electra-base')
ELECTRA-Small, Chinesehub.Module(name='chinese-electra-small')

从源码结构看,TransformerModule(paddlehub/module/nlp_module.py)声明了_tasks_supported = ['seq-cls', 'token-cls', 'text-matching'],其中text-matching即文本匹配任务;不同task会在模块__init__中装配不同的任务头与损失函数。

Step2:下载并加载数据集

train_dataset = LCQMC(tokenizer=model.get_tokenizer(), max_seq_len=128, mode='train') dev_dataset = LCQMC(tokenizer=model.get_tokenizer(), max_seq_len=128, mode='dev') test_dataset = LCQMC(tokenizer=model.get_tokenizer(), max_seq_len=128, mode='test')

参数说明:

  • tokenizer:该 Module 所需的 tokenizer,负责对输入文本完成切词,并转化成 Module 运行所需的模型输入格式;
  • mode:数据模式,可选项为traindevtest,默认为train
  • max_seq_len:ERNIE/BERT 模型使用的最大序列长度,若出现显存不足,请适当调低该参数。

预训练模型 ERNIE 对中文数据的处理以字为单位,tokenizer 的作用是把原始输入文本转化成模型可以接受的输入数据形式。PaddleHub 2.0 中的各类预训练模型已内置对应 tokenizer,可通过model.get_tokenizer()获取。

LCQMC 数据集的加载逻辑在 paddlehub/datasets/lcqmc.py 中实现:该数据集类通过@download_data(url=...)装饰器在首次使用时自动下载并缓存数据,train/test/dev模式分别对应train.tsv/test.tsv/dev.tsv,标签集合为['0', '1'](0 表示不相似、1 表示相似)。其基类TextMatchingDataset(paddlehub/datasets/base_nlp_dataset.py)以 tab 分隔读取文本对:每行text_a \t text_b \t label,并分别对 query 与 title 独立编码为input_ids+token_type_ids__getitem__返回(query_input_ids, query_token_type_ids, title_input_ids, title_token_type_ids, label)五个字段——这与双塔模型的输入形态一一对应。

Step3:选择优化策略和运行配置

optimizer = paddle.optimizer.AdamW(learning_rate=5e-5, parameters=model.parameters()) trainer = hub.Trainer(model, optimizer, checkpoint_dir='./', use_gpu=True)
优化策略

Paddle 2.0 提供了多种优化器,如SGDAdamWAdamax等。其中AdamW常用参数:

  • learning_rate:全局学习率,默认 1e-3;本示例使用 5e-5,是 Transformer 预训练模型微调的常见取值;
  • parameters:待优化的模型参数。

其余可配置参数可参考 PaddlePaddle 官方AdamWAPI 文档。

运行配置

Trainer主要控制 Fine-tune 的训练过程,可控制参数包括:

  • model:被优化模型;
  • optimizer:优化器选择;
  • use_vdl:是否使用 VisualDL 可视化训练过程;
  • checkpoint_dir:模型参数保存目录;
  • compare_metrics:保存最优模型的衡量指标比较函数(未指定时默认比较validation_step返回的第一个指标,值越大越好)。

从 paddlehub/finetune/trainer.py 的源码可以看到Trainer的底层行为:根据use_gpu调用paddle.set_device选择设备;若use_vdl=True则在checkpoint_dir/visualization下创建LogWriter记录训练与评估指标;训练循环中通过training_step/validation_step分发到模型,并自动处理多卡(paddle.DataParallel)场景;每个save_interval轮末会先在eval_dataset上评估,若指标优于历史最优(由compare_metrics判定),则将模型保存到checkpoint_dir/best_model

Step4:执行训练和模型评估

trainer.train( train_dataset, epochs=10, batch_size=32, eval_dataset=dev_dataset, save_interval=2, ) trainer.evaluate(test_dataset, batch_size=32)

trainer.train执行模型训练,主要参数:

  • train_dataset:训练数据集;
  • epochs:训练轮数;
  • batch_size:训练时每一步用到的样本数目,若使用 GPU,请根据实际情况调整;
  • num_workers:数据加载子进程数量,默认为 0;
  • eval_dataset:验证集,设置后 Trainer 会在每个save_interval轮末执行评估并依据指标保存最优模型;
  • log_interval:打印日志的间隔,单位为执行的批训练次数;
  • save_interval:保存模型的间隔频次,单位为训练的轮数。

trainer.evaluate执行模型评估,主要参数:

  • eval_dataset:评估所用的数据集;
  • batch_size:评估时每一步用到的样本数目,若使用 GPU,请根据实际情况调整。

需要说明的是,验证集上的评估结果由模型内部的validation_step计算(文本匹配任务返回acc指标,见 paddlehub/module/nlp_module.py 中text-matching分支的training_step/validation_step)。

模型预测

完成 Fine-tune 后,训练过程中在验证集上表现最优的模型会被保存在${CHECKPOINT_DIR}/best_model目录下,其中${CHECKPOINT_DIR}为 Fine-tune 时所选择的 checkpoint 保存目录(目录内含model.pdparamsmodel.pdopt,分别保存模型与优化器状态)。

以下代码使用最优模型进行预测:

import paddlehub as hub data = [ ['这个表情叫什么', '这个猫的表情叫什么'], ['什么是智能手环', '智能手环有什么用'], ['介绍几本好看的都市异能小说,要完结的!', '求一本好看点的都市异能小说,要完结的'], ['一只蜜蜂落在日历上(打一成语)', '一只蜜蜂停在日历上(猜一成语)'], ['一盒香烟不拆开能存放多久?', '一条没拆封的香烟能存放多久。'], ] label_map = {0: 'similar', 1: 'dissimilar'} model = hub.Module( name='ernie_tiny', version='2.0.2', task='text-matching', load_checkpoint='./checkpoint/best_model/model.pdparams', label_map=label_map) results = model.predict(data, max_seq_len=128, batch_size=1, use_gpu=True) for idx, texts in enumerate(data): print('TextA: {}\tTextB: {}\t Label: {}'.format(texts[0], texts[1], results[idx]))

要点说明:

  • load_checkpoint指向最优模型的model.pdparams权重文件,加载逻辑见 modules/text/language_model/ernie_tiny/module.py(paddle.load+set_state_dict);
  • label_map将模型输出的类别索引映射为可读标签,此处0 → similar1 → dissimilar
  • model.predict在内部对每对(query, title)分别编码,调用双塔模型计算 softmax 概率并取argmax,再经label_map映射输出(见 paddlehub/module/nlp_module.py 的_convert_text_to_input_batchifypredict);
  • 传入的数据要求每个元素是包含两个字符串的列表,即[query, title]形式的文本对。

一键运行:参考仓库内的训练脚本

除了逐步骤调用 API,仓库还提供了可直接运行的脚本 demo/text_matching/train.py,通过命令行参数即可控制训练:

python train.py --num_epoch 10 --use_gpu True --learning_rate 5e-5 \ --max_seq_len 64 --batch_size 128 --checkpoint_dir ./checkpoint --save_interval 2

脚本默认使用ernie_tinyversion='2.0.2'task='text-matching')模型,支持--num_epoch(训练轮数)、--use_gpu(是否使用 GPU)、--learning_rate(学习率)、--max_seq_len(最大序列长度)、--batch_size(批大小)、--checkpoint_dir(checkpoint 目录)、--save_interval(保存间隔)等参数,训练结束后还会在测试集上执行trainer.evaluate。对应的预测示例见 demo/text_matching/predict.py,可直接体验完整"训练 → 最优模型加载 → 批量预测"闭环。

小结

本文围绕 PaddleHub 的text-matching任务,完整介绍了文本匹配的两种建模思路(句对拼接 CLS 分类 vs Sentence Transformer 双塔结构),并以 LCQMC 为例给出了选择模型、加载数据、配置优化器与 Trainer、训练评估、加载最优 checkpoint 预测的完整四步流程。结合仓库源码可以看到:双塔结构通过参数共享与 mean pooling 显著降低推理计算量;Trainer自动完成 checkpoint 轮次恢复、最优模型保存与 VisualDL 可视化;TextMatchingDataset与 tokenizer 将原始文本对转换为双塔模型所需的双路input_ids/token_type_ids输入。掌握上述 API 与原理后,可以便捷地将 ERNIE、BERT、RoBERTa 等预训练模型迁移到自己的文本匹配(如语义检索、Query-Title 相关性判定)业务场景中。

【免费下载链接】PaddleFormersPaddleFormers is an easy-to-use library of pre-trained large language model zoo based on PaddlePaddle.项目地址: https://gitcode.com/gh_mirrors/pa/PaddleFormers

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询