繁体   English   中英

Pytorch minibatching 阻止模型训练

[英]Pytorch minibatching keeps model from training

我正在尝试通过二进制特征对序列进行分类。 我有一个序列/标签对的数据集,并且正在使用一个简单的单层 LSTM 对每个序列进行分类。 在我实施 minibatching 之前,我在测试集上获得了合理的准确率 (80%),训练损失将从 0.6 到 0.3(平均)。

我使用本教程的部分内容实现了 minibatching: https ://pytorch.org/tutorials/beginner/chatbot_tutorial.html

但是,现在我的模型不会比批量大小设置为 1 且所有其他参数完全相同的 70-72%(70% 的数据有一个标签)更好。 此外,损失从 0.0106 开始,然后很快变得非常小,结果没有显着变化。 我觉得没有批处理和大小为 1 的批处理之间的结果应该是一样的,所以我可能有一个错误,但在我的生活中我找不到它。 我的代码如下。

训练代码(一个epoch):

for i in t:
    model.zero_grad()

    # prep inputs
    last = i+self.params['batch_size']
    last = last if last < len(train_data) else len(train_data)
    batch_in, lengths, batch_targets = self.batch2TrainData(train_data[shuffled][i:last], word_to_ix, label_to_ix)

    iters += 1

    # forward pass.
    tag_scores = model(batch_in, lengths)

    # compute loss, then do backward pass, then update gradients
    loss = loss_function(tag_scores, batch_targets)
    loss.backward()

    # Clip gradients: gradients are modified in place
    nn.utils.clip_grad_norm_(model.parameters(), 50.0)

    optimizer.step()

职能:

def prep_sequence(self, seq, to_ix):
    idxs = [to_ix[w] for w in seq]
    return torch.tensor(idxs, dtype=torch.long)

# transposes batch_in
def zeroPadding(self, l, fillvalue=0):
    return list(itertools.zip_longest(*l, fillvalue=fillvalue))

# Returns padded input sequence tensor and lengths
def inputVar(self, batch_in, word_to_ix):
    idx_batch = [self.prep_sequence(seq, word_to_ix) for seq in batch_in]
    lengths = torch.tensor([len(idxs) for idxs in idx_batch])
    padList = self.zeroPadding(idx_batch)
    padVar = torch.LongTensor(padList)
    return padVar, lengths

# Returns all items for a given batch of pairs
def batch2TrainData(self, batch, word_to_ix, label_to_ix):
    # sort by dec length
    batch = batch[np.argsort([len(x['turn']) for x in batch])[::-1]]
    input_batch, output_batch = [], []
    for pair in batch:
        input_batch.append(pair['turn'])
        output_batch.append(pair['label'])
    inp, lengths = self.inputVar(input_batch, word_to_ix)
    output = self.prep_sequence(output_batch, label_to_ix)
    return inp, lengths, output

模型:

class LSTMClassifier(nn.Module):

    def __init__(self, params, vocab_size, tagset_size, weights_matrix=None):
        super(LSTMClassifier, self).__init__()
        self.hidden_dim = params['hidden_dim']

        if weights_matrix is not None:
            self.word_embeddings = nn.Embedding.from_pretrained(weights_matrix)
        else:
            self.word_embeddings = nn.Embedding(vocab_size, params['embedding_dim'])

        self.lstm = nn.LSTM(params['embedding_dim'], self.hidden_dim, bidirectional=False)

        # The linear layer that maps from hidden state space to tag space
        self.hidden2tag = nn.Linear(self.hidden_dim, tagset_size)

    def forward(self, batch_in, lengths):
        embeds = self.word_embeddings(batch_in)
        packed = nn.utils.rnn.pack_padded_sequence(embeds, lengths)
        lstm_out, _ = self.lstm(packed)
        outputs, _ = nn.utils.rnn.pad_packed_sequence(lstm_out)
        tag_space = self.hidden2tag(outputs)
        tag_scores = F.log_softmax(tag_space, dim=0)
        return tag_scores[-1]

对于其他有类似问题的人,我让它工作了。 我删除了 log_softmax 计算,所以这个:

tag_space = self.hidden2tag(outputs)
tag_scores = F.log_softmax(tag_space, dim=0)
return tag_scores[-1]

变成这样:

tag_space = self.hidden2tag(outputs)
return tag_space[-1]

我还将 NLLLoss 更改为 CrossEntropyLoss(上面未显示),并在没有参数的情况下初始化 CrossEntropyLoss(也就是没有 ignore_index)。

我不确定为什么这些更改是必要的(文档甚至说 NLLLoss 应该在 log_softmax 层之后运行),但他们让我的模型工作并将我的损失恢复到合理范围(~0.5)。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM