nn.transformer不能直接处理原始文本,因其仅提供纯注意力块堆叠,需手动添加词嵌入、位置编码、掩码逻辑及输出解码;输入须为(seq_len,batch_size,embed_dim)三维张量,且默认不校验形状,易因维度错位或掩码缺失导致运行错误。

直接用 nn.Transformer 是可行的,但必须自己补全输入预处理、位置编码、掩码逻辑和输出解码——它不包含任何嵌入层或位置编码,也不是开箱即用的“模型”,而是一个纯注意力块堆叠器。
为什么 nn.Transformer 不能直接喂原始文本或序列ID?
nn.Transformer 的输入要求是三维张量 (seq_len, batch_size, embed_dim),且默认假设你已经完成了:词嵌入(nn.Embedding)、位置编码(需手动加)、以及所有必要的掩码(如 src_mask、tgt_mask、memory_mask)。它不做任何形状校验,传错维度只会报 RuntimeError: expected tensor to have size 1 at dimension 2 这类模糊错误。
常见误操作包括:
- 把
(batch_size, seq_len, embed_dim)直接传进去(没转置)→ 报size mismatch - 漏掉
tgt_mask导致 decoder 自回归失效 → 输出全是重复 token - 用
nn.TransformerEncoder当完整 Transformer 模型用 → 缺少 decoder,无法做 seq2seq
如何正确构造一个可训练的 Seq2Seq Transformer?
以机器翻译为例,你需要显式拼装以下组件:
- 两个
nn.Embedding层(source 和 target vocab) - 一个可学习的
nn.Parameter位置编码(shape:(max_len, embed_dim)),加到嵌入输出上 - 用
torch.nn.Transformer实例,注意设置num_encoder_layers和num_decoder_layers - decoder 的
tgt输入必须右移一位(tgt[:-1]),并用nn.Transformer.generate_square_subsequent_mask()构造 causal mask - 最后接一个线性层 + log_softmax,匹配 target vocab size
关键代码片段:
model = nn.Transformer(
d_model=512,
nhead=8,
num_encoder_layers=6,
num_decoder_layers=6,
dim_feedforward=2048,
dropout=0.1
)
# 注意:输入要转置!
src = src_emb(src_ids).transpose(0, 1) # (seq_len, batch, 512)
tgt = tgt_emb(tgt_ids[:-1]).transpose(0, 1)
tgt_mask = model.generate_square_subsequent_mask(tgt.size(0))
output = model(src, tgt, tgt_mask=tgt_mask) # (seq_len, batch, 512)
logits = output.transpose(0, 1) @ lm_head_weight.t() # 或用 nn.Linear
训练时最容易崩的三个地方
不是模型写错了,而是数据流或掩码没对齐:
-
src和tgt的seq_len维度必须是第一维(nn.Transformer强制按 time-step 并行计算,不是 batch-first) -
tgt_mask必须是上三角矩阵(float('-inf')填上三角,0 填下三角),否则 decoder 会偷看未来 token -
src_key_padding_mask和tg t_key_padding_mask要用bool类型张量(True表示 pad 位置),传int或float会静默失败
调试建议:在 forward 开头加 assert src.dim() == 3 and src.size(0) > 1,避免单 token 输入触发内部 reshape 错误。
想快速验证结构,别碰 nn.Transformer ——改用 Hugging Face Transformers
如果你只是想跑通一个标准 Transformer(比如 bert-base-uncased 或 t5-small),nn.Transformer 的胶水代码量远超收益。HF 的 AutoModelForSeq2SeqLM 封装了全部预处理、缓存、生成逻辑,且支持 generate() 接口:
from transformers import AutoModelForSeq2SeqLM
model = AutoModelForSeq2SeqLM.from_pretrained("t5-small")
outputs = model.generate(input_ids, max_length=50)
而自己用 nn.Transformer 写等效逻辑,至少要额外实现 beam search、past_key_values 缓存、padding 处理——这些都不是“架构”本身该关心的事。
真正需要手写 nn.Transformer 的场景极少:比如定制化稀疏 attention、替换 FFN 结构、或做底层机制研究。日常建模,它更像一个“乐高底座”,不是成品玩具。
Python免费学习笔记(深入):立即使用
在学习笔记中,你将探索 Python 的核心概念和高级技巧!











