在pytorch中保存和加载模型权重后,为什么会得到不同的结果?

时间:2019-04-29 09:45:38

标签: python python-3.x pytorch

我已经写了一个模型,其架构如下:

CNNLSTM(                                                                                                                                                                                  
  (cnn): CNNText(                                                                                                                                                                         
    (embed): Embedding(19410, 300, padding_idx=0)                                                                                                                                         
    (convs1): ModuleList(                                                                                                                                                                 
      (0): Conv2d(1, 32, kernel_size=(3, 300), stride=(1, 1))                                                                                                                             
      (1): Conv2d(1, 32, kernel_size=(5, 300), stride=(1, 1))                                                                                                                             
      (2): Conv2d(1, 32, kernel_size=(7, 300), stride=(1, 1))                                                                                                                             
    )                                                                                                                                                                                     
    (dropout): Dropout(p=0.6)                                                                                                                                                             
    (fc1): Linear(in_features=96, out_features=1, bias=True)                                                                                                                              
  )                                                                                                                                                                                       
  (lstm): RNN(                                                                                                                                                                        
    (embedding): Embedding(19410, 300, padding_idx=0)                                                                                                                                     
    (rnn): LSTM(300, 150, batch_first=True, bidirectional=True)                                                                                                                           
    (attention): Attention(                                                                                                                                                               
      (dense): Linear(in_features=300, out_features=1, bias=True)                                                                                                                         
      (tanh): Tanh()                                                                                                                                                                      
      (softmax): Softmax()                                                                                                                                                                
    )                                                                                                                                                                                     
    (fc1): Linear(in_features=300, out_features=50, bias=True)                                                                                                                            
    (dropout): Dropout(p=0.5)                                                                                                                                                             
    (fc2): Linear(in_features=50, out_features=1, bias=True)                                                                                                                              
  )                                                                                                                                                                                       
  (fc1): Linear(in_features=146, out_features=1, bias=True)                                                                                                                               
)

我在同一数据集上使用RNN和CNN的方式有所不同,并且保存了权重。在混合模型中,我使用以下函数加载权重:

def load_pretrained_weights(self, model='cnn', path=None):
    if model not in ['cnn', 'rnn']:
        raise AttributeError("Model must be either rnn or cnn")
    if model == 'cnn':
        self.cnn.load_state_dict(torch.load(path))
    if model == 'rnn':
        self.lstm.load_state_dict(torch.load(path))

并使用以下功能冻结子模块:

def freeze(self):    
    for p in self.cnn.parameters():
        p.requires_grad = False
    for p in self.lstm.parameters():
        p.requires_grad = False

然后,我训练了模型,并且与每个训练过的子模块和 单独评估。 我在时代循环中使用了一种早期停止技术来保存最佳参数。 训练后,我创建了一个相同类的新实例,并且在加载保存的“最佳”参数时,并没有得到相似的结果。 我单独对每个子模块(此处为RNN和CNNText)尝试了相同的操作,它确实有效。但是在这种情况下,它不能提供相同的性能。

请帮助我了解它在这里发生的情况。我是深度学习概念的新手。 谢谢。

我尝试过的一些实验:

  1. 我加载了每个子模块的重量并加载了最佳参数,以某种方式接近最佳结果。
  2. 在应用Dropout之前,从每个子模块中获取隐藏层,它比上一个更好,但不是最好的!

编辑

我的班级的init函数如下。 RNN和CNN只是通常的实现。

class CNNLSTM(nn.Module):

    def __init__(self, vocab_size, embedding_dim, embedding_weight, rnn_arch, isCuda=True, class_num=1, kernel_num=32, kernel_sizes=[3,4,5],train_wv=False, rnn_num_layers=1, rnn_bidirectional=True, rnn_use_attention=True):

        super(CNNLSTM, self).__init__()
        self.cnn = CNNText(vocab_size, embedding_dim, embedding_weight, class_num, kernel_num = kernel_num, kernel_sizes=kernel_sizes, static=train_wv,dropout=0.6)
        self.lstm = RNN(rnn_arch, vocab_size, embedding_dim, embedding_weight, num_layers=rnn_num_layers, rnn_unit='lstm', embedding_train=train_wv, isCuda=isCuda, bidirectional=rnn_bidirectional, use_padding=True, use_attention=rnn_use_attention, num_class=class_num)
        self.fc1 = nn.Linear(rnn_arch[-1] + len(kernel_sizes) * kernel_num , class_num)

声明对象后

我将单独的预训练子模块加载为

model.load_pretrained_weights('rnn', 'models/bilstm_2_atten.pth')
model.load_pretrained_weights('cnn', 'models/cnn2.pth')

model.freeze()

然后我训练最后一个线性层。 我将模型参数值另存为

torch.save(model.state_dict(),path)

因此,从上一个纪元的第3/4开始,我得到了“最佳”结果。 训练后,我加载了最佳效果的参数,

state_dict = torch.load(MODEL_PATH)
model.load_state_dict(state_dict)

1 个答案:

答案 0 :(得分:1)

加载模型后,需要写model.eval()

state_dict = torch.load(MODEL_PATH)
model.load_state_dict(state_dict)
model.eval()

参考:Pytorch Documentation

内容是这样的:


保存模型进行推理时,只需保存训练模型的学习参数即可。使用 state_dict 函数保存模型的 torch.save() 将为您以后恢复模型提供最大的灵活性,这就是为什么它是保存模型的推荐方法。

一个常见的 PyTorch 约定是使用 .pt.pth 文件扩展名保存模型。

请记住,在运行推理之前,您必须调用 model.eval() 将 dropout 和批量归一化层设置为评估模式。否则会产生不一致的推理结果。