做虚拟货币交易网站,成都建网站,个人网站策划书怎么做,flash网站价格DiffSynth-Studio训练踩坑记录#xff1a;PyTorch 2.5.1 Meta Tensor 新增模块 strictTrue 导致的加载失败环境#xff1a;
PyTorch 2.5.1DiffSynth-Studio / Wan2.1-T2V-1.3B
任务#xff1a;在官方 WanVideo 模型基础上增加模块#xff0c;继续训练 LoRA这篇文章记录一…DiffSynth-Studio训练踩坑记录PyTorch 2.5.1 Meta Tensor 新增模块 strictTrue 导致的加载失败环境PyTorch 2.5.1DiffSynth-Studio / Wan2.1-T2V-1.3B任务在官方 WanVideo 模型基础上增加模块继续训练 LoRA这篇文章记录一次在 WanVideo 训练过程中遇到的模型加载问题涉及到PyTorch 2.5.1 的 meta tensor 机制使用strictTrue加载权重导致的结构不匹配给模型增加新模块后如何正确加载旧 checkpoint。最后训练已经成功跑起来这里把整个排查和修复过程整理一下。1. 场景简介在 WanVideo 上加模块继续训练训练命令大致如下nohupbashexamples/wanvideo/model_training/lora/Wan2.1-T2V-1.3B.sh\wan2.1-1.3B.log21项目中使用self.pipeWanVideoPipeline.from_pretrained(torch_dtypetorch.bfloat16,devicedevice,model_configsmodel_configs,tokenizer_configtokenizer_config,audio_processor_configaudio_processor_config,)来下载并加载 Wan2.1-T2V-1.3B 模型。我对模型做了一个改动在原有模型的基础上增加了一些新的模块新的层希望用原模型的权重作为初始化继续训练 LoRA。自然地旧 checkpoint 中没有新模块对应的权重这为后面的报错埋下了伏笔。2. 第一层坑strictTrue 导致结构不匹配直接报错最开始代码里加载权重用的是默认的strictTrue类似model.load_state_dict(state_dict)# 默认 strictTrue当我在模型结构上增加模块之后这些新增层的参数在 checkpoint 中不存在。在strictTrue的情况下load_state_dict的行为是模型里有但state_dict里没有 → 归为missing_keys直接报错state_dict里有但模型里没有 → 归为unexpected_keys也会报错。也就是说只要你对模型结构进行了增删改strictTrue 会让加载必然失败。正确做法应该是改成strictFalseload_infomodel.load_state_dict(state_dict,strictFalse)print(missing:,load_info.missing_keys)print(unexpected:,load_info.unexpected_keys)允许结构不完全一致用missing_keys/unexpected_keys明确看到哪些参数没加载上、哪些是 checkpoint 里多余的。后面在修复时我把这一步和 meta 问题一起处理了最终使用load_infomodel.load_state_dict(state_dict,assignTrue,strictFalse)下面先解释第二层坑meta tensor。3. 什么是 meta tensor先理解再排错在这次问题里最关键的一条报错是NotImplementedError: Cannot copy out of meta tensor; no data! Please use torch.nn.Module.to_empty() instead of torch.nn.Module.to() when moving module from meta to a different device.这里的 “meta tensor” 其实是 PyTorch 提供的一种特殊机制meta device。3.1 meta 是什么可以简单理解为“只有形状和 dtype 信息、没有真实数据、不占显存的假张量用来先搭模型结构、后装权重。”比如withtorch.device(meta):wtorch.empty(16,16)print(w.device)# device(typemeta)print(w.shape)# torch.Size([16, 16])print(w.is_meta)# True特点有 shape、有 dtypew.is_meta True不占 GPU/CPU 实际内存但不能做任何需要真实数据的操作例如w.to(cuda)要拷贝数据w 1要访问数据卷积、matmul 等计算。3.2 为什么要有 meta大模型构建时如果立刻在 GPU 上分配全部参数很容易 OOM。因此很多框架采用“空权重 / meta device”技术withtorch.device(meta):modelMyBigModel()# 所有参数都是 meta tensor这一步只搭结构不占真实显存。后面再按策略把参数真正“实例化”到 GPU / CPU 并加载权重。3.3 和这次报错的关系在 DiffSynth-Studio 里构建 WanVideo 模型时就用了 meta 技术。也就是说模型刚被创建时参数是is_metaTrue还没有真实数据。而在diffsynth/core/loader/model.py中当时的代码类似modelmodel.to(dtypetorch_dtype,devicedevice)这里直接对 meta 模型调用.to()PyTorch 会尝试从 meta 上“拷贝”数据到目标设备。但 meta 上根本没有数据所以就抛出了Cannot copy out of meta tensor; no data! Please use torch.nn.Module.to_empty() ...官方的意思是对 meta 模型不要直接.to()而要用to_empty(device...)先在目标设备上创建“空参数容器”再用load_state_dict填入真正的 checkpoint 数据。4. 正确的迁移方式to_emptyload_state_dictPyTorch 2.5.1 下的推荐做法如下在 meta 设备上构建模型withtorch.device(meta):modelMyModel()不要直接model.to(cuda)而是modelmodel.to_empty(devicecuda)# 只分配空参数容器然后用 checkpoint 填充state_dicttorch.load(xx.pth,map_locationcpu)model.load_state_dict(state_dict)5. 把 meta strict 新增模块 这三件事串起来结合前面的分析这次问题本质上是三件事叠加模型是通过 meta 方式构建的我对模型结构做了修改增加了模块一开始用的是strictTrue随后在 meta 状态下直接调用了.to()。想要一劳永逸地解决需要做到判断是否有 meta 参数对 meta 模型用to_empty(device...)而不是.to()用load_state_dict(..., strictFalse)打印missing_keys/unexpected_keys初始化新增模块。最终我在load_model中整理出的核心逻辑大概是这样# 1. 判断是否有 meta 参数has_meta_paramany(p.is_metaforpinmodel.parameters())ifhas_meta_param:# 2. meta 模型使用 to_empty 迁移到目标设备# 注意PyTorch 2.5.1 要用关键字参数 devicemodelmodel.to_empty(devicedevice)# 3. 之后再统一 dtype此时已经不是 meta 了可以正常 .toiftorch_dtypeisnotNone:modelmodel.to(dtypetorch_dtype)else:# 非 meta 模型直接 .to 即可modelmodel.to(dtypetorch_dtype,devicedevice)# 4. 加载 checkpoint非严格模式 assignTrueload_infomodel.load_state_dict(state_dict,assignTrue,strictFalse)missingload_info.missing_keys unexpectedload_info.unexpected_keysifmissing:print(未加载到的参数 (missing_keys):)forkinmissing:print( ,k)ifunexpected:print(多余的权重 (unexpected_keys)state_dict 中有但模型中没有:)forkinunexpected:print( ,k)ifnotmissingandnotunexpected:print(所有参数均已加载)几点注意to_empty在 2.5.1 中不支持dtype参数所以用modelmodel.to_empty(devicedevice)modelmodel.to(dtypetorch_dtype)strictFalse是为了允许新增模块不在 checkpoint 中避免硬报错。assignTrue用的是 PyTorch 2.x 的新行为直接让参数引用指向state_dict中的 tensor减少一次拷贝。