pytorch加载分布式方式训练的模型

当使用PyTorch的load_state_dict加载分布式训练的模型时,若`strict=False`模型能加载但输出可能不正确。若`strict=True`,需移除'模块.'前缀以匹配权重。解决方案是创建新字典,将旧键转换。在加载后,模型预测结果与原始模型不符,可能原因包括未调用`model.eval()`、模型结构中存在dropout等。参考链接提供了详细排查步骤。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

出现的问题

  1. 使用load_state_dict函数,如果strict=False,模型可以加载,但是模型的输出不对
  2. 如果strict=True,但是没有新建字典,模型无法加载

问题解决

  • 保存的模型使用分布式方式训练,如果加载后模型不用分布式,则需要修改模型的key.
  • 分布式模型的权值名字前面有module.,非分布式不包含。
    比如分布式模型的权值名称名称为module.blocks.0.norm1.weight ,非分布式模型权值名称名称blocks.0.norm1.weight
  • 需要重新建一个字典,用去掉module.的名字座位key,值不变

代码示例

chk_filename = os.path.join(args.checkpoint, args.resume if args.resume else args.evaluate)
print('Loading checkpoint', chk_filename)
checkpoint = torch.load(chk_filename, map_location=lambda storage, loc: storage)
checkpoint = checkpoint['model_pos']
new_checkpoint = {} ## 新建一个字典来访模型的权值
# print(checkpoint)
for k,value in checkpoint.items():
    key = k.split('module.')[-1]
    new_checkpoint[key] = value
    # print(k,key)

# model_pos.load_state_dict(checkpoint['model_pos'], strict=True)
model_pos.load_state_dict(new_checkpoint, strict=True)

保存的模型重新加载后,与原始模型预测的结果不一致,从下面几个方面查找原因

  1. 是否使用了model.eval()
  2. 模型结构里面存在dropout?

  3. 参考https://blog.youkuaiyun.com/pearl8899/article/details/109661274
    参考文章2
### PyTorch DataParallel 分布式训练 #### 使用 `DataParallel` 实现多GPU训练 为了利用多个GPU加速神经网络的训练,在PyTorch中可以采用`torch.nn.DataParallel`类[^1]。该方法会自动分割输入数据,并将其分配给不同的GPU上的模型副本处理;当所有子任务完成后,它还会收集各个部分的结果并将它们合并成完整的输出。 下面是一个简单的例子展示怎样设置一个基于`DataParallel`接口的应用程序: ```python import torch import torch.nn as nn from torchvision import models, transforms from torch.utils.data import DataLoader class SimpleCNN(nn.Module): def __init__(self): super(SimpleCNN, self).__init__() resnet = models.resnet18(pretrained=True) self.backbone = nn.Sequential(*list(resnet.children())[:-1]) self.fc = nn.Linear(512, 10) def forward(self, x): with torch.no_grad(): features = self.backbone(x).flatten(start_dim=1) out = self.fc(features) return out def prepare_data(batch_size_per_gpu): transform = transforms.Compose([ transforms.Resize((224, 224)), transforms.ToTensor(), ]) train_loader = DataLoader( dataset, batch_size=batch_size_per_gpu * torch.cuda.device_count(), # 总batch size为每张卡上batch size之和 shuffle=True, num_workers=4 ) return train_loader if __name__ == '__main__': model = SimpleCNN().cuda() if torch.cuda.device_count() > 1: print(f"Using {torch.cuda.device_count()} GPUs!") model = nn.DataParallel(model) optimizer = torch.optim.Adam(model.parameters()) criterion = nn.CrossEntropyLoss() dataloader = prepare_data(batch_size_per_gpu=32) for epoch in range(num_epochs): running_loss = 0.0 for i, (inputs, labels) in enumerate(dataloader): inputs, labels = inputs.to('cuda'), labels.to('cuda') outputs = model(inputs) loss = criterion(outputs, labels) optimizer.zero_grad() loss.backward() optimizer.step() running_loss += loss.item() ``` 这段代码展示了如何创建一个多GPU版本的卷积神经网络,并对其进行训练。注意这里定义了一个辅助函数`prepare_data()`用于准备数据集加载器,其中指定了总的批量大小等于每个GPU上的批次数乘以GPU数量[^3]。 需要注意的是虽然`DataParallel`易于使用,但它也有一些局限性,比如只适合于单台机器内的多GPU环境,并且由于其内部机制的原因可能导致性能不如更先进的分布式训练方案如`DistributedDataParallel`。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值