把权重从 fp32 转成 bf16 后,模型能加载但输出全是重复字符,用原精度权重却完全正常。
原因不止一个,得分开看。转换时直接对权重做了截断而不是类型转换;保存时 dtype 元数据与实际数据不一致;部分层的归一化权重也被转成了低精度;转换脚本按字节拷贝,忽略了张量布局。
先确认权重张量的真实类型
python -c "from safetensors import safe_open;f=safe_open('m.safetensors','pt');print(f.get_tensor('model.embed_tokens.weight').dtype)"
然后用官方接口做类型转换并保存
model = model.to(torch.bfloat16); model.save_pretrained('./bf16')
随后对归一化层保留 fp32
python -c "print('keep layernorm in fp32')"
末了加载后做一次固定输入的输出对比
python -c "print(out_ids[:20])")
这类改动我都写进变更记录,过两周再出问题时能对上号。
我习惯把每一步的执行时间和结果记在一边,后面复盘省事。
改完先别撤,确认这几项。转换后的模型输出与原精度接近,不再出现重复乱码,显存占用下降到一半。
提醒一点。嵌入层与输出层对精度最敏感,整体转低精度时这两层出问题最明显,必要时单独保留高精度。同一份配置在测试环境跑通,不代表线上没事,两边的默认值经常不一样。