Python PyTorch:保存权重和模型定义

Python PyTorch:保存权重和模型定义,python,pytorch,Python,Pytorch,在原型设计过程中,我经常对PyTorch模型进行多次更改。例如,假设我正在试验的第一个模型是: 类模型(nn.Module): 定义初始化(self,**参数): super()。\uuuu init\uuuuu() self.l1=nn.线性(128,1) 然后我将添加另一层: 类模型(nn.Module): 定义初始化(self,**参数): super()。\uuuu init\uuuuu() self.l1=nn.线性(128,32) self.l2=nn.Linear(32,1)

在原型设计过程中,我经常对PyTorch模型进行多次更改。例如,假设我正在试验的第一个模型是:

类模型(nn.Module):
定义初始化(self,**参数):
super()。\uuuu init\uuuuu()
self.l1=nn.线性(128,1)
然后我将添加另一层:

类模型(nn.Module):
定义初始化(self,**参数):
super()。\uuuu init\uuuuu()
self.l1=nn.线性(128,32)
self.l2=nn.Linear(32,1)
或者加上一些卷积,等等

问题是,我执行的实验越多,我经常会变得杂乱无章,因为我还没有找到一种简单的方法来保存模型定义及其权重,以便加载以前的状态

我知道我能做到:

torch.save({'model':model(),'state':model.state_dict()},path)
#或者直接
火炬。保存(模型、路径)
但是加载模型还需要模型类(此处为
model
)存在于当前文件中

在这种情况下,您可以简单地执行以下操作:

model=…#获取模型(顺序、功能模型或模型子类)
model.save('path/to/location')
这节省了模型的架构/配置和权重等。这意味着您可以在没有定义体系结构的情况下加载模型:

model=keras.models.load_model('path/to/location'))
提及:

SavedModel和HDF5文件包含:

  • 模型的配置(拓扑)
  • 模型的权重
  • 模型的优化器状态(如果有)
因此,模型可以在完全相同的状态下重新实例化,而无需任何修改 用于模型定义或培训的代码

这就是我想在PyTorch中实现的目标


PyTorch是否有类似的方法?对于这些情况,最佳做法是什么?

由于Pytorch在模型中提供了巨大的灵活性,因此在单个文件中保存体系结构和权重将是一个挑战。Keras模型通常仅通过堆叠Keras组件来构建,但pytorch模型由库使用者以自己的方式编排,因此可以包含任何类型的逻辑

我认为你有三个选择:

  • 为你的实验提出一个有组织的模式,这样就不太可能丢失模型定义。您可以选择一些简单的方法,例如通过仅定义每个模型的模式命名的文件。我会推荐这种方法,因为这种级别的组织可能会从其他方面受益,并且开销最小

  • 尝试将代码与pickle文件一起保存。虽然有可能,但我认为这会让你陷入一个有很多潜在问题的困境

  • 使用不同的标准化方法保存模型,例如。如果您不想选择选项1,我建议您选择这条路线。Onnx确实允许您保存pytorch模型的架构及其权重,但也有一些缺点。例如,它只支持某些操作,因此完全自定义的
    转发
    方法或使用非矩阵操作可能不起作用


  • 由于Pytorch在模型中提供了巨大的灵活性,因此在单个文件中保存体系结构和权重将是一个挑战。Keras模型通常仅通过堆叠Keras组件来构建,但pytorch模型由库使用者以自己的方式编排,因此可以包含任何类型的逻辑

    我认为你有三个选择:

  • 为你的实验提出一个有组织的模式,这样就不太可能丢失模型定义。您可以选择一些简单的方法,例如通过仅定义每个模型的模式命名的文件。我会推荐这种方法,因为这种级别的组织可能会从其他方面受益,并且开销最小

  • 尝试将代码与pickle文件一起保存。虽然有可能,但我认为这会让你陷入一个有很多潜在问题的困境

  • 使用不同的标准化方法保存模型,例如。如果您不想选择选项1,我建议您选择这条路线。Onnx确实允许您保存pytorch模型的架构及其权重,但也有一些缺点。例如,它只支持某些操作,因此完全自定义的
    转发
    方法或使用非矩阵操作可能不起作用

  • 这是正确的方法。但是,为了将来的参考,我想添加以下对我有用的方法

    让我们假设模型的
    forward
    方法是固定的,也就是说,只有底层架构发生了更改,输入和输出形状相同。在本例中,我们只对表示整个体系结构的
    Sequential
    属性感兴趣:

    类模型(nn.Module):
    定义初始化(self,**hparams):
    超级(模型,自我)。\uuuu初始化
    #这个属性是我们唯一关心的
    self.net=nn.Sequential(
    #在这里用不同的层进行实验。。。
    )
    def前进(自身,x):
    return self.net(x)#这是固定的!
    
    然后,我们可以保存模型架构(基本上只是
    net
    属性)及其权重:

    m=Model()
    #训练/测试/有效。。。
    T.save({'net':m.net,'weights':m.state_dict()},./version1.pth')
    
    最后,按照如下方式执行加载:

    m=Model()
    检查点=T.load('./version1.pth')
    m、 net=检查点['net']
    m、 加载状态命令(检查点['weights'])
    
    是正确的选择。但是,为了将来的参考,我想添加以下对我有用的方法

    让我们假设模型的
    forward
    方法是固定的,也就是说,只有underyin