☰
PaddleNLP MPNet 模型全解析:架构原理、配置参数与实战调用指南
2026/9/25 5:03:19 网站建设 项目流程
  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

MPNet(Masked and Permuted Language Modeling)是由微软提出的预训练语言模型,它在掩码语言建模(MLM)与排列语言建模(PLM)之间找到了统一的折中方案,弥补了 BERT 依赖独立性假设、XLNet 忽略 token 绝对位置的缺陷。本指南以 paddlenlp.transformers.mpnet.rst 对应的 API 参考为主线,结合 modeling.py、configuration.py、tokenizer.py 的实现细节,系统讲解 MPNet 在 PaddleNLP 中的配置体系、模型架构、各任务头封装与分词器用法。读完本文,你将掌握 MPNet 系列模型从加载、配置、前向推理到下游任务微调的完整调用方法,并能对照源码理解其相对位置编码、池化策略等核心机制。

一、模块总览:PaddleNLP 中的 MPNet 家族

在 PaddleNLP 中,MPNet 的完整实现集中在 paddlenlp/transformers/mpnet 目录下,由四个文件构成:

文件职责
configuration.py定义MPNetConfig与预训练配置常量
modeling.py定义MPNetModel、MPNetPretrainedModel及五个下游任务模型
tokenizer.py定义MPNetTokenizer
__init__.py汇总导出 modeling 与 tokenizer 的公开符号

对应地,中文 API 文档在 docs/zh/source 下拆分为三个 RST 节点:paddlenlp.transformers.mpnet.rst(模块入口)、paddlenlp.transformers.mpnet.modeling.rst 与 paddlenlp.transformers.mpnet.tokenizer.rst,分别由automodule指令自动抽取源码 docstring 生成。

modeling.py中公开的类名如下(见__all__列表):MPNetModel、MPNetPretrainedModel、MPNetForMaskedLM、MPNetForSequenceClassification、MPNetForMultipleChoice、MPNetForTokenClassification、MPNetForQuestionAnswering。其中MPNetModel通过@register_base_model装饰器注册为基座模型,MPNetPretrainedModel是抽象预训练基类,负责权重下载与加载。

二、MPNetConfig:模型架构的 12 个核心参数

MPNetConfig继承自PretrainedConfig(定义于 configuration_utils.py),用于在实例化模型时完整定义架构。其默认值与mpnet-base保持一致,源码中的完整签名如下:

def __init__( self, vocab_size: int = 30527, hidden_size: int = 768, num_hidden_layers: int = 12, num_attention_heads: int = 12, intermediate_size: int = 3072, hidden_act: str = "gelu", hidden_dropout_prob: float = 0.1, attention_probs_dropout_prob: float = 0.1, max_position_embeddings: int = 514, initializer_range: float = 0.02, layer_norm_eps: float = 1e-5, relative_attention_num_buckets: int = 32, pad_token_id: int = 1, bos_token_id: int = 0, eos_token_id: int = 2, **kwargs ):

各参数的含义与取值说明如下:

参数默认值作用说明
vocab_size30527词表大小,决定input_ids可表示的 token 数量
hidden_size768编码器层与池化层的隐层维度
num_hidden_layers12Transformer 编码器层数
num_attention_heads12每层注意力头数,须能整除hidden_size
intermediate_size3072前馈网络(FFN)中间层维度
hidden_act"gelu"编码器与池化层的非线性激活函数,支持"gelu"、"relu"、"silu"、"gelu_new"
hidden_dropout_prob0.1嵌入层、编码器与池化层全连接层的 dropout 概率
attention_probs_dropout_prob0.1注意力概率矩阵的 dropout 比例
max_position_embeddings514最大序列长度(含特殊 token),mpnet-base 为 514
initializer_range0.02权重矩阵截断正态初始化的标准差
layer_norm_eps1e-5LayerNorm 的 epsilon
relative_attention_num_buckets32相对位置编码的分桶数量

MPNetConfig还声明了model_type = "mpnet",并建立了attribute_map = {"num_classes": "num_labels"},即旧属性名num_classes会自动映射到新属性num_labels。特殊 token 的默认约定为:pad_token_id=1、bos_token_id=0、eos_token_id=2。

从源码结构看,MPNET_PRETRAINED_INIT_CONFIGURATION目前为空字典,预训练权重信息直接维护在MPNetPretrainedModel.pretrained_resource_files_map中,目前内置的官方权重为mpnet-base,其model_state.pdparams权重文件托管于百度 BOS。

三、MPNetModel:双任务统一模型的 Paddle 实现

MPNetModel由三部分组成:MPNetEmbeddings、MPNetEncoder与MPNetPooler。前向传播的返回值为二元组(sequence_output, pooled_output)。

3.1 嵌入层:位置感知的"非 padding 累计"编码

MPNetEmbeddings包含词嵌入、位置嵌入、LayerNorm 与 dropout。与 BERT 直接使用预置position_ids不同,MPNet 的位置 id 由输入动态推导:

def create_position_ids_from_input_ids(input_ids, padding_idx=1): mask = (input_ids != padding_idx).astype(paddle.int64) incremental_indices = paddle.cumsum(mask, axis=1).astype(mask.dtype) * mask return incremental_indices.astype(paddle.int64) + padding_idx

该函数借鉴了 fairseq 的make_positions:非 padding 符号按其在有效 token 序列中的顺序编号(从padding_idx + 1起),padding 符号则被屏蔽忽略。这保证了即使样本被 padding 到不同长度,模型接收到的位置信息仍然与真实语序严格对应——这是 MPNet 能在预训练中同时保留绝对位置信号的关键。position_ids可通过前向接口手动传入,缺省时自动按上述规则生成。

3.2 编码器:相对位置分桶 + 前置/后置 LayerNorm

MPNetEncoder由num_hidden_layers个MPNetLayer堆叠而成(nn.LayerList深拷贝同一层),并额外维护一个relative_attention_bias嵌入表,尺寸为(relative_attention_num_buckets, num_attention_heads)。

MPNet 的核心创新在于注意力计算同时融合了绝对位置(通过位置嵌入)与相对位置(通过分桶偏置):

def compute_position_bias(self, x, position_ids=None, num_buckets=32): bsz, qlen, klen = x.shape[0], x.shape[1], x.shape[1] context_position = paddle.arange(qlen).unsqueeze(1) memory_position = paddle.arange(klen).unsqueeze(0) relative_position = memory_position - context_position rp_bucket = self.relative_position_bucket(relative_position, num_buckets=num_buckets) values = self.relative_attention_bias(rp_bucket) ...

相对位置按 T5 风格进行分桶映射:relative_position_bucket先将位置差取负号判断正负(负向偏移计入一半桶数),再对绝对值做对数分桶,max_distance=128以内的精确距离用小桶表示,超出部分通过对数缩放压缩到大桶中。最终生成的position_bias形状为[batch, num_heads, qlen, klen],在MPNetAttention中直接加到注意力得分上。

注意力层(MPNetAttention)的实现在结构上遵循"前置 LayerNorm"(Pre-LN)设计:Q/K/V 线性投影后按头拆分并乘以scale = attention_head_size ** -0.5,加上position_bias与attention_mask后 softmax、dropout,与 V 相乘得到上下文向量,经输出投影和 dropout 后,再与残差连接一起过 LayerNorm。MPNetLayer中的 FFN 同样采用残差 + 后 LayerNorm 结构。此外,每层都会返回layer_att(注意力得分)与所有中间层输出,便于分析注意力模式或做中间层特征提取。

3.3 池化层:首 token 池化

MPNetPooler取序列第一个 token(<s>)的隐状态,经nn.Linear(hidden_size, hidden_size)与nn.Tanh得到[batch_size, hidden_size]的pooled_output,供分类类任务使用。

3.4 前向接口与注意力掩码约定

MPNetModel.forward(input_ids, position_ids=None, attention_mask=None)的约定如下:

  • input_ids:int64型,形状[batch_size, sequence_length];
  • position_ids:可选,范围[0, max_position_embeddings - 1];
  • attention_mask:可选。缺省时自动以input_ids != pad_token_id生成;当 mask 为二维时,会扩展为[batch, 1, 1, seq_len]并转换为(1.0 - mask) * -10000.0的加法掩码形式,1表示可见、0表示被屏蔽。

官方示例(取自 docstring,可直接运行):

import paddle from paddlenlp.transformers import MPNetModel, MPNetTokenizer tokenizer = MPNetTokenizer.from_pretrained('mpnet-base') model = MPNetModel.from_pretrained('mpnet-base') inputs = tokenizer("Welcome to use PaddlePaddle and PaddleNLP!") inputs = {k: paddle.to_tensor([v]) for (k, v) in inputs.items()} outputs = model(**inputs) # outputs[0]: sequence_output, [1, seq_len, 768] # outputs[1]: pooled_output, [1, 768]

四、五个下游任务模型:一行代码接入分类、抽取与问答

modeling.py在基座模型之上封装了五个带任务头的模型,均通过from_pretrained加载预训练权重后直接微调。

4.1 MPNetForMaskedLM —— 掩码语言建模

结构为MPNetModel + MPNetLMHead。MPNetLMHead先做dense → 激活 → LayerNorm,再与词嵌入权重共享的解码矩阵做转置矩阵乘法并加偏置,输出[batch, seq_len, vocab_size]的prediction_scores。labels中值为-100的位置将被忽略(不参与损失计算),仅对有效标签位置计算CrossEntropyLoss。传入labels时返回三元组(masked_lm_loss, prediction_scores, sequence_output),否则返回(prediction_scores, sequence_output)。

4.2 MPNetForSequenceClassification —— 文本分类 / 回归

在pooled_output之上接Dropout + Linear(hidden_size, num_labels),适用于 GLUE 类任务。分类器的 dropout 优先使用config.classifier_dropout,未设置时回退到hidden_dropout_prob。返回[batch_size, num_classes]的 logits。

4.3 MPNetForMultipleChoice —— 多项选择

将[batch, num_choice, seq_len]的输入展平为[batch * num_choice, seq_len]过基座模型,池化后经单输出分类头得到[batch * num_choice, 1],再 reshape 回[batch, num_choice]。适用于 RocStories、SWAG 等多项选择任务,构造时默认num_choices=2。

4.4 MPNetForTokenClassification —— 序列标注 / NER

直接对sequence_output逐 token 做Dropout + Linear(hidden_size, num_labels),返回[batch, seq_len, num_labels]的 logits,适用于命名实体识别等任务。

4.5 MPNetForQuestionAnswering —— 抽取式问答

在sequence_output上接Linear(hidden_size, 2),经转置与paddle.unstack拆出start_logits与end_logits(形状均为[batch, seq_len]),用于 SQuAD 类答案区间抽取。

五、MPNetTokenizer:与 BERT 几乎一致的分词方案

MPNetTokenizer继承自BertTokenizer(实现在 bert/tokenizer.py),因此完整继承了 BasicTokenizer(小写化、标点切分、中文字符切分、Unicode 归一化)与 WordpieceTokenizer 的分词管线,但特殊 token 体系针对 MPNet 做了定制:

  • 预训练配置:mpnet-base默认do_lower_case=True;
  • 特殊 token:bos_token="<s>"、eos_token="</s>"、unk_token="[UNK]"、sep_token="</s>"、pad_token="<pad>"、cls_token="<s>"、mask_token="<mask>";
  • mask_token以lstrip=True注册为AddedToken,使其像普通词一样保留前置空格;
  • 词表文件名为vocab.txt,官方权重对应资源地址见pretrained_resource_files_map。

序列拼接格式与 BERT 有明显差异:

  • 单序列:<s> X </s>;
  • 序列对:<s> A </s></s> B </s>(两个</s>连用分隔两段)。

对应的get_special_tokens_mask会为双序列返回[1] + 0... + [1, 1] + 0... + [1]的掩码。由于 MPNet 不使用 token type id,create_token_type_ids_from_sequences直接返回全 0。__call__支持max_length、stride、padding、truncation、pad_to_multiple_of、return_offsets_mapping等完整参数集,与基类保持一致。

典型调用:

from paddlenlp.transformers import MPNetTokenizer tokenizer = MPNetTokenizer.from_pretrained('mpnet-base') # 单序列 print(tokenizer("Welcome to use PaddlePaddle and PaddleNLP!")) # 序列对:用于句对分类 / 匹配任务 print(tokenizer("sentence A", "sentence B"))

六、从配置到模型:四种标准加载方式

MPNetConfig的 docstring 给出了标准用法,结合 PaddleNLP 的from_pretrained机制,共有四条加载路径:

from paddlenlp.transformers import MPNetModel, MPNetConfig # 1. 仅用默认配置实例化(相当于 mpnet-base 风格架构) configuration = MPNetConfig() model = MPNetModel(configuration) # 2. 自定义配置实例化(例如改为 6 层 6 头) custom_config = MPNetConfig(hidden_size=384, num_hidden_layers=6, num_attention_heads=6) model = MPNetModel(custom_config) # 3. 直接加载官方预训练权重 model = MPNetModel.from_pretrained('mpnet-base') # 4. 从模型对象反向获取配置 configuration = model.config

方式 2 适合从零训练或蒸馏小模型;方式 3 会从pretrained_resource_files_map指定的 BOS 地址自动下载model_state.pdparams权重。MPNetPretrainedModel._init_weights使用paddle.tensor.normal以initializer_range为标准差初始化nn.Linear与nn.Embedding权重。

七、正确性与可用性验证:仓库测试与文档

PaddleNLP 为 MPNet 提供了完整的单测覆盖,可作为复现与验证的依据:

  • tests/transformers/mpnet/test_modeling.py:验证MPNetModel及各任务头的前向输出形状、配置改动后的行为、序列输出与池化输出的一致性等;
  • tests/transformers/mpnet/test_tokenizer.py:验证特殊 token 拼接、get_special_tokens_mask、token type id 全零等分词器行为。

中文文档侧,除入口页 paddlenlp.transformers.mpnet.rst 外,还有 modeling 与 tokenizer 两个子页面,通过automodule与:members:、:no-undoc-members:、:show-inheritance:指令自动生成全部公开 API 的参考手册,所有 docstring 即上文各节引用的参数与返回说明的第一手来源。

八、实战小结与选型建议

综上,PaddleNLP 的 MPNet 实现具备三个鲜明特点:

  1. 位置编码双轨制:动态累计位置 id(绝对位置)+ 分桶相对位置偏置(相对位置),这正是 MPNet 论文提出的"掩码 + 排列"统一建模在工程上的落地形态,实现位于 modeling.py 的MPNetEmbeddings与MPNetEncoder.compute_position_bias;
  2. 任务覆盖齐全:一个基座模型 + 五个任务头(MLM、分类/回归、多项选择、序列标注、抽取式问答),覆盖 NLP 主流下游场景,且任务头均共享from_pretrained加载机制;
  3. 分词即插即用:MPNetTokenizer直接复用 BERT 分词能力,仅需注意其特殊的<s> A </s></s> B </s>句对格式与全零 token type id。

若你的场景需要比 BERT 更强的上下文建模(例如句子对匹配、抽取式问答、长文本表示),且不介意其预训练权重仅有mpnet-base一档,可优先选用 MPNet 系列。具体接入时,建议以"分词器 + 任务模型 +from_pretrained('mpnet-base')"的组合快速起步,再根据算力与精度诉求调整hidden_size、num_hidden_layers等配置项重新训练或蒸馏。

  • 人工智能
  • 大模型
  • 预训练
  • 微调
  • LoRA
  • RLHF
  • 强化学习
  • 分布式训练

【免费下载链接】PaddleNLP

Easy-to-use and powerful LLM and SLM library with awesome model zoo.

项目地址:https://gitcode.com/gh_mirrors/pa/PaddleNLP
点击查看免费下载

相关推荐

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

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

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

立即咨询