我已经写了一个模型,其架构如下:
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)尝试了相同的操作,它确实有效。但是在这种情况下,它不能提供相同的性能。
请帮助我了解它在这里发生的情况。我是深度学习概念的新手。 谢谢。
我尝试过的一些实验:
编辑
我的班级的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)
答案 0 :(得分:1)
加载模型后,需要写model.eval()
。
state_dict = torch.load(MODEL_PATH)
model.load_state_dict(state_dict)
model.eval()
内容是这样的:
保存模型进行推理时,只需保存训练模型的学习参数即可。使用 state_dict
函数保存模型的 torch.save()
将为您以后恢复模型提供最大的灵活性,这就是为什么它是保存模型的推荐方法。
一个常见的 PyTorch 约定是使用 .pt
或 .pth
文件扩展名保存模型。
请记住,在运行推理之前,您必须调用 model.eval()
将 dropout 和批量归一化层设置为评估模式。否则会产生不一致的推理结果。