首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >PyTorch -只保存模型结构而不考虑重量,然后加载并训练它。

PyTorch -只保存模型结构而不考虑重量,然后加载并训练它。
EN

Stack Overflow用户
提问于 2020-06-30 20:56:26
回答 1查看 1.6K关注 0票数 1

我想把模型结构、创作和培训分开。模型作者设计了模型结构,将未经过训练的模型保存到一个文件中,然后发送训练服务,加载模型结构并对模型进行训练。

Keras能够保存模型配置,然后加载它。

如何在PyTorch中实现同样的目标?

EN

回答 1

Stack Overflow用户

发布于 2020-07-01 05:57:54

您可以编写自己的函数在PyTorch中完成这一任务。重量的保存是直接的,你只需做一个torch.save(model.state_dict(), 'weightsAndBiases.pth')

为了保存模型结构,可以这样做:

(假设您有一个名为Network的模型类,并且实例化了yourModel = Network())

代码语言:javascript
复制
model_structure = {'input_size': 784,
              'output_size': 10,
              'hidden_layers': [each.out_features for each in yourModel.hidden_layers],
              'state_dict': yourModel.state_dict() #if you want to save the weights
}

torch.save(model_structure, 'model_structure.pth')

类似地,我们可以编写一个函数来加载结构。

代码语言:javascript
复制
def load_structure(filepath):
    structure = torch.load(filepath)
    model = Network(structure['input_size'],
                    structure['output_size'],
                    structure['hidden_layers'])
    # model.load_state_dict(structure['state_dict']) if you had saved weights as well
    
    return model

model = load_structure('model_structure.pth')
print(model)

编辑:好的,当您可以访问类的源代码时,或者如果类相对简单,那么您就可以定义这样的泛型类:

代码语言:javascript
复制
class Network(nn.Module):
    def __init__(self, input_size, output_size, hidden_layers, drop_p=0.5):
        ''' Builds a feedforward network with arbitrary hidden layers.
        
            Arguments
            ---------
            input_size: integer, size of the input layer
            output_size: integer, size of the output layer
            hidden_layers: list of integers, the sizes of the hidden layers
        
        '''
        super().__init__()
        # Input to a hidden layer
        self.hidden_layers = nn.ModuleList([nn.Linear(input_size, hidden_layers[0])])
        
        # Add a variable number of more hidden layers
        layer_sizes = zip(hidden_layers[:-1], hidden_layers[1:])
        self.hidden_layers.extend([nn.Linear(h1, h2) for h1, h2 in layer_sizes])
        
        self.output = nn.Linear(hidden_layers[-1], output_size)
        
        self.dropout = nn.Dropout(p=drop_p)
        
    def forward(self, x):
        ''' Forward pass through the network, returns the output logits '''
        
        for each in self.hidden_layers:
            x = F.relu(each(x))
            x = self.dropout(x)
        x = self.output(x)
        
        return F.log_softmax(x, dim=1)

但是,这只适用于简单的情况,所以我想这不是您想要的。

一种选择是,您可以在一个单独的.py文件中定义模型的体系结构,并将其与其他必要的东西一起导入(如果模型体系结构很复杂),或者您可以在那时和那里完全定义模型。

另一种选择是将您的option模型转换为onxx并保存它。

另一种选择是,在Tensorflow中,您可以创建一个.pb文件,该文件定义了模型的体系结构和权重,而在option中,您可以这样做:

代码语言:javascript
复制
torch.save(model, filepath)

这将保存模型对象本身,因为torch.save()最终只是一个基于泡菜的保存。

代码语言:javascript
复制
model = torch.load(filepath)

然而,这有其局限性,例如,您的模型类定义可能是不可选择的(在一些复杂的模型中是可能的)。因为这是一个不确定的解决方法,所以您通常会得到的答案是-不,您必须在加载经过训练的模型之前声明类定义(即您需要访问模型类源代码。

边注:一个核心的PyTorch开发人员关于在没有代码的情况下加载pytorch模型的限制的官方回答:

  1. 我们只保存类定义的源代码。除此之外,我们不进行保存(比如类所引用的包源)。
代码语言:javascript
复制
import foo

class MyModel(...):
    def forward(input):
        foo.bar(input)

在这里,包foo没有保存在模型检查点中。

  1. 健壮地序列化python构造是有限制的。例如,默认的拾取器不能序列化lambda。有些帮助包可以序列化比标准更多的python构造,但它们仍然有局限性。Dill 25就是其中之一。

鉴于这些限制,在没有原始源文件的情况下,没有健壮的方法可以让torch.load工作。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62666027

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档