PyTorch:模型和数据的save和load

-柚子皮-

API

torch.save和torch.load

torch.save(obj, f, pickle_module=pickle, pickle_protocol=DEFAULT_PROTOCOL, _use_new_zipfile_serialization=True)

Saves an object to a disk file.

torch.save:将序列化的对象保存到disk。这个函数使用Python的pickle实用程序进行序列化。使用这个函数可以保存各种对象的模型、张量和字典。
torch.load:使用pickle unpickle工具将pickle的对象文件反序列化为内存。
torch.nn.Module.load_state_dict:使用反序列化状态字典加载model's参数字典。

TORCH.UTILS.MODEL_ZOO

Loads the Torch serialized object at the given URL.

torch.utils.model_zoo.load_url(url, model_dir=None, map_location=None, progress=True, check_hash=False, file_name=None)

示例:

state_dict = torch.hub.load_state_dict_from_url('https://s3.amazonaws.com/pytorch/models/resnet18-5c106cde.pth')

模型加载和保存

PyTorch 中保存模型主要分为两类:保存整个模型和只保存模型参数。

A common PyTorch convention is to save models using either a .pt or .pth file extension.

保存加载整个模型(不推荐)

保存整个网络模型

(网络结构+权重参数)

torch.save(model, 'net.pth')

这里加载的 net.pt 其实是一个字典,通常包含如下内容:

        网络结构:输入尺寸、输出尺寸以及隐藏层信息,以便能够在加载时重建模型。
        模型的权重参数:包含各网络层训练后的可学习参数,可以在模型实例上调用 state_dict() 方法来获取,比如只保存模型权重参数时用到的 model.state_dict()。
        优化器参数:有时保存模型的参数需要稍后接着训练,那么就必须保存优化器的状态和所其使用的超参数,也是在优化器实例上调用 state_dict() 方法来获取这些参数。
        其他信息:有时我们需要保存一些其他的信息,比如 epoch,batch_size 等超参数。

出错:

AttributeError: Can't pickle local object 'AtomicModel.get_metrics.<locals>.<lambda>'
AttributeError: Can't pickle local object 'AtomicModel._get_metrics.<locals>._accuracy_score'
原因:pickle不能序列化lambda函数,或者是闭包。[python模块 - pickle模块]

加载整个网络模型

(可能比较耗时)

model = torch.load('net.pth')

只保存加载模型参数(推荐)

保存模型的权重参数

(速度快,占内存少)

torch.save(model.state_dict(), 'net_params.pth')

这里model.state_dict() 将每一层的可学习参数映射为参数矩阵,其中只包含具有可学习参数的层(卷积层、全连接层等)。

load模型参数

因为我们只保存了模型的参数,所以需要先定义一个网络对象,然后再加载模型参数。torch.load 返回的是一个 OrderedDict,.state_dict()只是把所有模型的参数都以OrderedDict的形式存下来。
model = ClassNet()
state_dict = torch.load('net_params.pth')
model.load_state_dict(state_dict)

load_state_dict的参数Strict=False

new_model.load_state_dict(state_dict, strict=False)
      如果哪一天我们需要重新写这个网络的,比如使用new_model,如果直接load会出现unexpected key。但是加上strict=False可以很容易地加载预训练的参数(注意检查key是否匹配),直接忽略不匹配的key,对于匹配的key则进行正常的赋值。

跨设备保存加载模型map_location

在 CPU 上加载在 GPU 上训练并保存的模型(Save on GPU, Load on CPU):

device = torch.device('cpu')
model = TheModelClass()
# Load all tensors onto the CPU device
model.load_state_dict(torch.load('net_params.pkl', map_location=device))
map_location:a function, torch.device, string or a dict specifying how to remap storage locations

令 torch.load() 函数的 map_location 参数等于 torch.device('cpu') 即可。 这里令 map_location 参数等于 'cpu' 也同样可以。

否则会出错:RuntimeError: Attempting to deserialize object on a CUDA device but torch.cuda.is_available() is False. If you are running on a CPU-only machine, please use torch.load with map_location=torch.device('cpu') to map your storages to the CPU.

解决:torch.load(model_path_name, map_location=None if torch.cuda.is_available() else 'cpu')

[Pytorch学习(十七)--- 模型load各种问题解决]

自定义保存内容(推荐)

针对前面“保存加载整个模型”内容过多,我们可以自定义需要save的内容。特别地,如果还想保存某一次训练采用的优化器、epochs等信息,可将这些信息组合起来构成一个字典,然后将字典保存起来:

# saving a checkpoint assuming the network class named ClassNet
checkpoint = {'model': ClassNet(), 'model_state_dict': model.state_dict(),
              'optimizer_state_dict': optimizer.state_dict(), 'epoch': epoch}
torch.save(checkpoint, 'checkpoint.pkl')

load自定义保存的字典

def load_checkpoint(filepath):
    checkpoint = torch.load(filepath)
    model = checkpoint['model']  # 提取网络结构
    model.load_state_dict(checkpoint['model_state_dict'])  # 加载网络权重参数
    optimizer = TheOptimizerClass()
    optimizer.load_state_dict(checkpoint['optimizer_state_dict'])  # 加载优化器参数
    
    for parameter in model.parameters():
        parameter.requires_grad = False
    model.eval()
    
    return model
    
model = load_checkpoint('checkpoint.pkl')

后续使用

      如果加载模型只是为了进行推理测试,则将每一层的 requires_grad 置为 False,即固定这些权重参数;还需要调用 model.eval() 将模型置为测试模式,主要是将 dropout 和 batch normalization 层进行固定,否则模型的预测结果每次都会不同。

      如果希望继续训练,则调用 model.train(),以确保网络模型处于训练模式。

[SAVING AND LOADING MODELS]

数据加载和保存

torch.save和torch.load不仅可以针对模型,还可以是任何对象。因为它本身就是使用Python的pickle实用程序进行序列化。

示例

如feature 是 一个元素为自定义类对象的list

torch.save(features, feature_file_name_path)

features = torch.load(feature_file_name_path)

from: -柚子皮-

ref:

在DQN(Deep Q-Network)中,评估网络和目标网络的更新是通过优化器`optim.Adam`来实现的。评估网络用于预测当前状态下采取不同行动的价值,而目标网络用于计算未来状态的预期回报。这两个网络的结构相同,但参数不同。 以下是使用PyTorch实现DQN中的评估网络和目标网络更新的代码: ```python import torch import torch.nn as nn import torch.optim as optim class DQN(nn.Module): def __init__(self, input_size, output_size): super(DQN, self).__init__() self.fc1 = nn.Linear(input_size, 128) self.fc2 = nn.Linear(128, 64) self.fc3 = nn.Linear(64, output_size) def forward(self, x): x = torch.relu(self.fc1(x)) x = torch.relu(self.fc2(x)) x = self.fc3(x) return x # 创建评估网络和目标网络 eval_net = DQN(input_size, output_size) target_net = DQN(input_size, output_size) # 将目标网络的参数设置为评估网络的参数 target_net.load_state_dict(eval_net.state_dict()) # 设置优化器 optimizer = optim.Adam(eval_net.parameters(), lr=0.001) # 训练过程 for episode in range(num_episodes): # ... 进行训练,获取经验数据(state, action, reward, next_state, done) # 计算损失函数 loss = compute_loss(states, actions, rewards, next_states, dones, eval_net, target_net) # 反向传播和优化 optimizer.zero_grad() loss.backward() optimizer.step() # 每隔一定的步骤,更新目标网络的参数 if episode % update_target_every == 0: target_net.load_state_dict(eval_net.state_dict()) ``` 在这个例子中,我们首先定义了一个名为`DQN`的神经网络类,它包含三个全连接层。然后,我们创建了评估网络`eval_net`和目标网络`target_net`,并将目标网络的参数设置为评估网络的参数。接下来,我们使用`optim.Adam`优化器来优化评估网络的参数。 在训练过程中,我们计算损失函数,然后使用优化器的`zero_grad()`方法清除梯度,执行反向传播`loss.backward()`,并使用`optimizer.step()`更新评估网络的参数。最后,我们每隔一定的步骤(例如每1000步)更新目标网络的参数,使其与评估网络保持一致。
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值