先把当时的情况摆出来。为了省显存打开 gradient_checkpointing,训练立刻报 RuntimeError: element 0 of tensors does not require grad and does not have a grad_fn。
原因不止一个,得分开看。输入 embedding 没有开启 requires_grad。少数情况下是PEFT 模型需要显式调用专用准备函数。
少数情况下是检查点重算时输入张量被 detach。不容易想到的是,部分冻结层阻断了梯度回传路径。
先对 PEFT 模型调用专用开关
model.enable_input_require_grads()
训练脚本里同时打开检查点
model.gradient_checkpointing_enable()
然后确认输入嵌入需要梯度
python -c "print(model.get_input_embeddings().weight.requires_grad)"
缓存设为不可用,避免重算冲突
model.config.use_cache = False
排查用的命令都是临时敲的,没有写成脚本,事后才整理。
手上没有现成的复现脚本,就照着线上请求手工拼了一个。
别只看报错消失,验证要多做一步。反向传播正常执行,显存占用下降约三成,loss 能持续下降而不再报无梯度,长序列训练也能稳定跑完。
这里还有个坑。开了检查点还留着 use_cache=True 会同时占用两份缓存,不只是不省显存还可能报形状冲突,训练前记得关掉。这类问题最好一次改到位,反复小改反而容易把原因搅混。