fairseq 语言模型自适应输入表示(Adaptive Input Representations)实战指南:原理、配置与训练

发布时间:2026/9/19 6:45:28
fairseq 语言模型自适应输入表示(Adaptive Input Representations)实战指南:原理、配置与训练 fairseq 语言模型自适应输入表示Adaptive Input Representations实战指南原理、配置与训练【免费下载链接】fairseqFacebook AI Research Sequence-to-Sequence Toolkit written in Python.项目地址: https://gitcode.com/gh_mirrors/fa/fairseq本指南聚焦 fairseq 中的自适应输入表示Adaptive Input RepresentationsBaevski and Auli, 2018技术它在处理 WikiText-103、Google Billion Words 这类超大规模词表的语言建模任务时通过按词频将词表切分为多个子空间、逐级降维的 Embedding 与输出层大幅压缩参数量与计算开销。读完本文你将掌握如何复现 fairseq 官方 WikiText-103 自适应输入语言模型的完整数据准备、训练与评估流程理解AdaptiveInput、AdaptiveSoftmax、adaptive_loss三者如何协同工作并能独立调整 cutoff、factor、权重绑定等关键超参数。一、背景为什么语言模型需要自适应输入标准语言模型会为词表中的每个 token 维护一个独立的 Embedding 向量输出层则用词表大小 × 隐藏维度的全连接矩阵计算全词表 softmax。当词表达到数十万规模如 WikiText-103 约 26 万 token、Google Billion Words 约 80 万 token时输入 Embedding 矩阵和输出投影矩阵占据了模型绝大部分参数量每个训练步都要对所有词计算 logits计算量与显存开销随词表线性增长。Baevski 和 Auli2018提出的自适应输入表示将词表按词频切分成若干个band频带高频词使用较大维度的 Embedding低频词使用逐步缩小维度的 Embedding最后统一通过一个线性投影映射到模型主维度。这样既保留了低频词的区分能力又避免了为每个低频词都维护高维向量。配套的自适应 SoftmaxGrave et al., 2017在输出侧做对称的切分与降维输入侧、输出侧通过权重绑定进一步共享参数——这正是 fairseq 中transformer_lm_wiki103架构的核心设计。二、预训练模型fairseq 官方发布了两个采用自适应输入表示训练好的语言模型对应文档 examples/language_model/README.adaptive_inputs.md 中的表格均可在 fairseq/models/transformer_lm.py 的hub_models()中查到注册信息可通过 PyTorch Hub 直接加载描述参数量数据集模型与测试集Adaptive InputsBaevski and Auli, 20181026MGoogle Billion Wordstransformer_lm.gbw.adaptive_hugeAdaptive InputsBaevski and Auli, 2018247MWikiText-103transformer_lm.wiki103.adaptive在 examples/language_model/README.md 中同样列出了这两个模型的下载入口adaptive_lm_gbw_huge.tar.bz2、adaptive_lm_wiki103.v2.tar.bz2。Hub 中这两个模型对应的 tokenizer 为moses、BPE 为fastbpe加载后可用sample()生成文本或用score()计算困惑度。如果你的目标是复现论文中的结果推荐从 WikiText-103 版本247M 参数入手。三、数据准备WikiText-103 预处理与二值化训练自适应输入语言模型前需要先按通用语言建模流程准备 WikiText-103 数据。完整的预处理说明见 examples/language_model/README.md 的 Training a transformer language model with the CLI tools 一节。第一步进入 examples/language_model 目录运行官方数据脚本该脚本从 wikitext-103-v1.zip 下载并解压原始语料逻辑见 examples/language_model/prepare-wikitext-103.shcd examples/language_model/ bash prepare-wikitext-103.sh cd ../..第二步使用fairseq-preprocess将文本二值化。注意语言建模任务需要加--only-source将同一份数据同时作为源与目标TEXTexamples/language_model/wikitext-103 fairseq-preprocess \ --only-source \ --trainpref $TEXT/wiki.train.tokens \ --validpref $TEXT/wiki.valid.tokens \ --testpref $TEXT/wiki.test.tokens \ --destdir>fairseq-train --task language_modeling \ >默认值wiki103含义decoder_layers16Transformer 解码器层数decoder_embed_dim1024模型主维度decoder_ffn_embed_dim4096前馈网络隐层维度decoder_attention_heads8注意力头数adaptive_inputTrue启用自适应输入 Embeddingadaptive_input_factor4每个 band 的维度衰减因子adaptive_input_cutoff20000,60000输入侧词表切分点adaptive_softmax_cutoff20000,60000输出侧切分点与输入侧一致adaptive_softmax_dropout0.2输出尾部投影的 dropouttie_adaptive_weightsTrue绑定输入 Embedding 与输出投影权重tie_adaptive_projTrue绑定输入/输出侧的低维投影权重dropout/attention_dropout/activation_dropout0.3 / 0.1 / 0.1各类 dropout词表 26 万左右、cutoff 为[20000, 60000]时AdaptiveInput会自动在末尾追加真实词表大小见 fairseq/modules/adaptive_input.py实际切分为三个 band[0, 20000)、[20000, 60000)、[60000, vocab_size)。六、源码原理AdaptiveInput 与 AdaptiveSoftmax 如何协同6.1 输入侧AdaptiveInput核心实现位于 fairseq/modules/adaptive_input.pyAdaptiveInput的构造函数接收vocab_size、padding_idx、initial_dim、factor、output_dim和cutoff六个核心参数L16-L26并在__init__中按 cutoff 生成若干个 bandL40-L54for i in range(len(self.cutoff)): prev self.cutoff[i - 1] if i 0 else 0 size self.cutoff[i] - prev dim int(initial_dim // (factor**i)) seq nn.Sequential( nn.Embedding(size, dim, self.padding_idx), quant_noise( nn.Linear(dim, output_dim, biasFalse), q_noise, qn_block_size ), ) self.embeddings.append(seq)每个 band 的 Embedding 维度按initial_dim // factor**i递减factor 默认 4随后用一个无偏置线性层将各 band 统一投影到output_dim模型主维度 1024。前向过程L70-L81通过input.lt(cutoff[i])与input.ge(cutoff[i-1])构造掩码把每个 token 分派到对应 band 的chunk_input input[mask] - cutoff[i-1]上完成查表最终拼回完整输出。初始化时Embedding 权重以std dim**-0.5的正态分布初始化、padding 位置置零线性层用 Xavier 均匀初始化L56-L63。在 fairseq/models/transformer_lm.py 中build_model会在args.adaptive_input为真时用decoder_input_dim、adaptive_input_factor、adaptive_input_cutoff构造AdaptiveInput否则退化为普通Embedding。6.2 输出侧AdaptiveSoftmax输出头实现位于 fairseq/modules/adaptive_softmax.py。AdaptiveSoftmax同样按 cutoff 切分词表但与输入侧方向相反head 覆盖高频词tail 按input_dim // factor**(i1)逐级降维。它只在需要时计算部分词表的分对数adapt_targetL180-L203把目标词映射为head 类标 band 内偏移从而规避全词表 softmax。在 fairseq/models/transformer/transformer_decoder.py 的build_output_projection中当adaptive_softmax_cutoff非空时创建AdaptiveSoftmax并且当tie_adaptive_weights为真时把输入 Embedding 直接传给adaptive_inputs参数head 层使用TiedHeadModule复用 band 0 的权重见 fairseq/modules/adaptive_softmax.py。若同时开启tie_adaptive_projtail 的降维投影也会通过TiedLinear与输入侧共享L140-L152——这就是transformer_lm_wiki103在 26 万词表下仅 247M 参数的关键。6.3 损失函数adaptive_lossfairseq/criterions/adaptive_loss.py 中的AdaptiveLoss是自适应 Softmax 的配套损失其注释引用自 GPU 高效 softmax 近似论文前向时先断言model.decoder.adaptive_softmax存在L53-L56然后对net_output调用adaptive_softmax(net_output[0], orig_target)拿到分段 logits 与重映射后的 targetL67对每个 band 分别计算F.cross_entropyL72-L80并按 token 数归一化reduce_metrics中通过utils.get_perplexity直接汇报困惑度L93-L115。这也解释了为何该损失与--ddp-backendlegacy_ddp强绑定——AdaptiveLoss的梯度汇总依赖 fairseq 的 legacy DDP 实现。6.4 测试佐证仓库测试同样验证了这套组合的可用性tests/test_binaries.py 中的test_transformer_lm_with_adaptive_softmax使用--criterion adaptive_loss --adaptive-softmax-cutoff 5,10,15完成训练、评估与生成全流程tests/gpu/test_binaries_gpu.py 的_quantize_language_model在量化语言模型时同样以adaptive_loss--adaptive-softmax-cutoff 5,10,15组合训练并显式设置--ddp-backend no_c10d。七、评估训练完成后使用fairseq-eval-lm评估困惑度示例输出格式来自 examples/language_model/README.mdfairseq-eval-lm>inproceedings{ baevski2018adaptive, title{Adaptive Input Representations for Neural Language Modeling}, author{Alexei Baevski and Michael Auli}, booktitle{International Conference on Learning Representations}, year{2019}, url{https://openreview.net/forum?idByxZX20qFQ}, }【免费下载链接】fairseqFacebook AI Research Sequence-to-Sequence Toolkit written in Python.项目地址: https://gitcode.com/gh_mirrors/fa/fairseq创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考