Я написал модель, архитектура выглядит следующим образом:
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), это сработало. Но в этом случае он не дает такой же производительности.
Пожалуйста, помогите мне понять, что здесь происходит. Я новичок в концепции глубокого обучения.
Спасибо.
Несколько экспериментов, которые я пробовал:
- Я загрузил сохраненные веса каждого подмодуля и загрузил лучшие параметры, как-то приблизился к лучшему результату.
- Взял скрытый слой из каждого подмодуля перед применением выпадения, стал лучше, чем предыдущий, но не самый лучший!
EDIT
Функция 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)