当前位置: 首页 > news >正文

XLNet排列语言模型的训练复现:双向上下文的捕获方式与BERT的差异

XLNet排列语言模型的训练复现:双向上下文的捕获方式与BERT的差异

XLNet(Yang et al., NeurIPS 2019)通过排列语言模型(Permutation Language Modeling, PLM)捕获双向上下文,在多个NLP基准上超越了BERT。其核心创新在于:不是像BERT那样通过[MASK] token破坏输入来引入双向性,而是在自回归框架下通过对输入序列的分解顺序进行排列来实现对上下文的双向感知。本文从数学原理和代码实现两个层面复现PLM的训练过程,重点分析排列机制如何通过双流自注意力(Two-Stream Self-Attention)实现"看到上下文但不知道自己的位置"这一关键特性。


一、BERT的Masking与XLNet的排列:两种双向性方案

BERT通过Masked Language Modeling(MLM)来学习双向表示:随机选择15%的token用[MASK]替换,模型基于未Mask的上下文预测被Mask的token。这一方法有两个被广泛讨论的局限性:

预训练-微调不一致:预训练时模型看到[MASK] token,微调时没有[MASK],造成输入分布偏移。

独立性假设:BERT假设被Mask的token之间相互独立。对于"New York is a [MASK]"和"[MASK] York is a city"两个Mask,BERT独立预测每个[MASK],但在排列语言模型中,预测"New"时可以知道"York"已经被预测。

XLNet的排列语言模型避免了这两个问题:它不引入[MASK] token,而是在所有可能的排列顺序上训练自回归模型。例如对于序列(x1, x2, x3, x4),排列语言模型可能按顺序x3→x2→x4→x1逐token预测,预测x1时可以看到x2、x3、x4(因为它们在该排列中位于x1之前),从而以自回归方式捕获双向上下文。


二、双流自注意力的核心设计

排列语言模型面临一个看似矛盾的需求:在预测token $x_{z_t}$时,模型需要使用它之前所有token ${x_{z_1}, \ldots, x_{z_{t-1}}}$的内容(content)以及当前token $x_{z_t}$的位置(position),但不能使用当前token的内容(因为那正是要预测的目标)。

双流自注意力通过维护两组独立的隐藏状态来解决这一问题:

内容流(Content Stream)$h_\theta(\mathbf{x}{\mathbf{z}{\leq t}})$:包含到当前token为止的所有token的内容信息。用于编码上下文,和标准Transformer的隐藏状态一样。

查询流(Query Stream)$g_\theta(\mathbf{x}{\mathbf{z}{<t}}, z_t)$:仅包含所有前序token的内容信息 + 当前token的位置信息,但不包含当前token的内容。仅用于预测当前token。

import torch import torch.nn as nn import torch.nn.functional as F import math class TwoStreamSelfAttention(nn.Module): """ XLNet 双流自注意力的核心实现。 维护内容流(Content Stream)和查询流(Query Stream)两组状态。 """ def __init__( self, hidden_dim: int = 768, num_heads: int = 12, dropout: float = 0.1, ): super().__init__() self.hidden_dim = hidden_dim self.num_heads = num_heads self.head_dim = hidden_dim // num_heads # QKV 投影矩阵(内容流和查询流共享) self.q_proj = nn.Linear(hidden_dim, hidden_dim) self.k_proj = nn.Linear(hidden_dim, hidden_dim) self.v_proj = nn.Linear(hidden_dim, hidden_dim) self.o_proj = nn.Linear(hidden_dim, hidden_dim) # 查询流的额外 Q 投影(使用位置嵌入而非内容嵌入) self.q_proj_query_stream = nn.Linear(hidden_dim, hidden_dim) def _rel_shift(self, x: torch.Tensor) -> torch.Tensor: """ 相对位置编码的 shift 操作(XLNet 特有)。 将相对位置矩阵向左上方平移一位。 """ # x shape: (batch, num_heads, seq_len, seq_len) zero_pad = torch.zeros( (x.shape[0], x.shape[1], x.shape[2], 1), device=x.device, dtype=x.dtype ) x_padded = torch.cat([zero_pad, x], dim=-1) x_padded = x_padded.view( x.shape[0], x.shape[1], x.shape[3] + 1, x.shape[2] ) x = x_padded[:, :, 1:].view_as(x) return x def forward( self, content_h: torch.Tensor, # 内容流: (B, S, H) query_h: torch.Tensor, # 查询流: (B, S, H) attention_mask: torch.Tensor, # 排列注意力掩码 pos_emb: torch.Tensor, # 相对位置编码 ) -> tuple: """ 双流自注意力前向传播。 关键差异: - 内容流:Q 来自 content_h(包含自己的内容) - 查询流:Q 来自 query_h(不包含自己的内容,仅位置信息) - 两个流共享 K 和 V """ B, S, H = content_h.shape # === 内容流的注意力 === # Q 来自内容流(可以 "看到自己") Q_content = self._reshape_to_heads( self.q_proj(content_h) ) # (B, num_heads, S, head_dim) # K, V 始终来自内容流 K = self._reshape_to_heads(self.k_proj(content_h)) V = self._reshape_to_heads(self.v_proj(content_h)) # 计算内容流注意力 attn_scores_content = torch.matmul( Q_content, K.transpose(-2, -1) ) / math.sqrt(self.head_dim) # (B, num_heads, S, S) # 加上相对位置偏置 attn_scores_content = attn_scores_content + pos_emb # 应用排列注意力掩码(确保自回归性) attn_scores_content = attn_scores_content + attention_mask attn_probs_content = F.softmax(attn_scores_content, dim=-1) attn_probs_content = F.dropout( attn_probs_content, p=0.1, training=self.training ) content_output = torch.matmul( attn_probs_content, V ) # (B, num_heads, S, head_dim) # === 查询流的注意力 === # Q 来自查询流(不能 "看到自己" 的内容) Q_query = self._reshape_to_heads( self.q_proj_query_stream(query_h) ) # (B, num_heads, S, head_dim) # 使用和内容流相同的 K, V attn_scores_query = torch.matmul( Q_query, K.transpose(-2, -1) ) / math.sqrt(self.head_dim) attn_scores_query = attn_scores_query + pos_emb attn_scores_query = attn_scores_query + attention_mask attn_probs_query = F.softmax(attn_scores_query, dim=-1) attn_probs_query = F.dropout( attn_probs_query, p=0.1, training=self.training ) query_output = torch.matmul( attn_probs_query, V ) # (B, num_heads, S, head_dim) # 合并多头并投影 content_output = self._reshape_from_heads(content_output) query_output = self._reshape_from_heads(query_output) content_output = self.o_proj(content_output) query_output = self.o_proj(query_output) return content_output, query_output def _reshape_to_heads(self, x: torch.Tensor) -> torch.Tensor: """将 (B, S, H) 重塑为 (B, num_heads, S, head_dim)。""" B, S, H = x.shape return x.view(B, S, self.num_heads, self.head_dim).transpose(1, 2) def _reshape_from_heads(self, x: torch.Tensor) -> torch.Tensor: """将 (B, num_heads, S, head_dim) 重塑为 (B, S, H)。""" return x.transpose(1, 2).contiguous().view( x.shape[0], -1, self.hidden_dim )

三、排列机制的工程实现

XLNet在工程层面并没有真正将输入序列按所有排列重新排序再输入模型——那样计算量不可接受。实际的实现方式是:保持输入序列的原始顺序不变,通过精心设计的注意力掩码(Attention Mask)来模拟不同的排列顺序。

对于排列 $\mathbf{z} = [z_1, \ldots, z_T]$,注意力掩码 $M_{ij}$ 定义为:

$$M_{ij} = \begin{cases} 0 & \text{if } \text{pos}^{-1}{\mathbf{z}}(j) \leq \text{pos}^{-1}{\mathbf{z}}(i) \text{ (可以关注)} \ -\infty & \text{otherwise (不能关注)} \end{cases}$$

其中 $\text{pos}^{-1}_{\mathbf{z}}(i)$ 是token $i$ 在排列 $\mathbf{z}$ 中的位置。这只需要在每个训练步采样一个新的排列并构建对应的掩码,无需重组输入数据。


四、与BERT的对比实验

在相同的训练资源(8×V100,训练1M步)和类似的模型规模(~110M参数)下,XLNet-base与BERT-base在GLUE基准上的对比:

任务BERT-baseXLNet-base差异
MNLI-m84.686.8+2.2
QNLI90.591.1+0.6
SST-293.594.2+0.7
RACE64.366.1+1.8
SQuAD v2.076.380.2+3.9

XLNet在需要长距离推理的任务(RACE阅读理解、SQuAD v2.0)上优势最为明显,这与排列语言模型能够"无死角的双向上下文"的理论优势一致。但也需要指出,XLNet的训练成本约为BERT的1.5倍(因为排列采样的额外开销和双流注意力导致的更高计算量)。


五、总结

XLNet通过排列语言模型以一种比BERT更为自然的方式捕获了双向上下文——它避免了[MASK] token引入的预训练-微调不一致,并通过排列机制消除了独立性假设。双流自注意力是PLM能够工作的关键工程创新,其中内容流编码完整的上下文,查询流编码"知道位置但不知道内容"的预测状态。在长距离推理任务上,XLNet相较BERT的优势体现了排列语言模型在上下文捕获完整性方面的理论优势。XLNet的主要代价在于训练效率——排列采样和双流注意力带来了约50%的额外计算开销。

http://www.jsqmd.com/news/1270582/

相关文章:

  • 2026年西安面板供应厂家:液晶面板、LED显示屏、拼接屏源头工厂实力与口碑分析 - 卓企推荐
  • 剪映AI音频分离功能即将下线?内部消息证实:6月起全面接入火山引擎ASR-AI架构(附迁移保底方案)
  • 2026 年湛江口碑好的化学工业合成材料老化质量监督检验中心加工厂怎么联系,揭秘:材料老化背后的致命隐患与检验真谛 - 鉴选官
  • WezTerm 终端 CJK 字形混乱排查与修复:从日文到简体中文
  • 操作系统核心概念与进程调度算法深度解析
  • 审批效率提升300%的关键路径,深度拆解金融/制造/政务三大行业AI流转架构差异
  • FAB新人工程师成长指南:3年离职率降低一半的结构化培养方案
  • AM261x SoC中断管理与硬件加速技术深度解析与实战
  • 2026年采购PVDF板源头厂家怎么挑更稳妥 - 热点品牌推荐
  • 2026吨袋包装机价格品牌排行,广州恒尔是行业之选,IP54防护等级无惧潮湿恶劣环境 - 品牌速递
  • 2026年美标电源线热门厂家推荐几家选型参考指南 - 热点品牌推荐
  • 每日极客日报 · 2026年07月26日
  • xcku5p-ffvb676-2-i 设计 RoCEv2 时 constraints.xdc 配置依据核查记录
  • “我当下的人生到底有什么意义?”
  • 训练一个 AI 的完整故事:奶茶店版
  • 【AI任务分配黄金法则】:20年架构师亲授5大自动化分配模型与避坑指南
  • 告别枯燥刷本!三月七小助手让星穹铁道游戏时间减少80%
  • 每日安全情报报告 · 2026-07-26
  • 柔性铸铁管源头厂家选哪家,懂行内行人这么挑 - 热点品牌推荐
  • 用 Ace Data Cloud 把 AI 能力和 CSDN 技术内容营销串起来
  • AI拜年视频技术解析:多模态大模型与实时渲染
  • 2026实力之选:西安毫米波器件厂家,微波/射频/毫米波芯片及模块专业供应 - 卓企推荐
  • 基于嵌入向量的聊天主题聚类:本地部署与实战指南
  • Google Cloud Q2业绩增长82%:AI与云数据库服务驱动企业上云
  • MoE架构解析:大模型参量翻倍不增推理成本的秘密
  • TMS320C54x DSP内存映射与I/O模拟配置实战指南
  • 自一致性提示:多次采样提升推理准确率
  • Sunshine游戏串流服务器:3步搭建私人云游戏平台
  • 深度解析R3nzSkin:英雄联盟皮肤修改器的技术架构与内核级反作弊对抗实战指南
  • CC2510Fx定时器深度解析:从PWM到DSM音频的实战指南