了解RNN的softmax输出层

时间:2018-11-26 06:32:44

标签: python lstm pytorch rnn softmax

这是Keras中的一个简单的LSTM模型:

input = Input(shape=(max_len,))
model = Embedding(input_dim=input_dim, output_dim=embed_dim, input_length=max_len)(input)
model = Dropout(0.1)(model)
model = Bidirectional(LSTM(units=blstm_dim, return_sequences=True, recurrent_dropout=0.1))(model)
out =Dense(label_dim, activation="softmax")(model)

这是我尝试将其转换为Pytorch模型:

class RNN(nn.Module):
    def __init__(self, input_dim, embed_dim, blstm_dim, label_dim):
        super(RNN, self).__init__()
        self.embed = nn.Embedding(input_dim, embed_dim)
        self.blstm = nn.LSTM(embed_dim, blstm_dim,  bidirectional=True, batch_first=True)
        self.fc = nn.Linear(2*blstm_dim, label_dim)


    def forward(self, x):
        h0 = torch.zeros(2, x.size(0), blstm_dim).to(device) 
        c0 = torch.zeros(2, x.size(0), blstm_dim).to(device)
        x = self.embed(x)
        x = F.dropout(x, p=0.1, training=self.training)
        x,_ = self.blstm(x, (h0, c0))
        x = self.fc(x)
        return F.softmax(x, dim=1)
#        return x

现在运行Keras模型可以得到以下信息:

Epoch 5/5
38846/38846 [==============================] - 87s 2ms/step - loss: 0.0374 - acc: 0.9889 - val_loss: 0.0473 - val_acc: 0.9859

但是运行PyTorch模型可以做到这一点:

Train Epoch: 10/10 [6400/34532 (19%)]   Loss: 2.788933
Train Epoch: 10/10 [12800/34532 (37%)]  Loss: 2.788880
Train Epoch: 10/10 [19200/34532 (56%)]  Loss: 2.785547
Train Epoch: 10/10 [25600/34532 (74%)]  Loss: 2.796180
Train Epoch: 10/10 [32000/34532 (93%)]  Loss: 2.790446
Validation: Average loss: 0.0437, Accuracy: 308281/431600 (71%)

我确保损耗和优化器相同(交叉熵和RMSprop)。现在有趣的是,如果我从PyTorch模型中删除softmax(即使用代码中的哈希输出,我会得到正确的结果:

Train Epoch: 10/10 [32000/34532 (93%)]  Loss: 0.022118
Validation: Average loss: 0.0009, Accuracy: 424974/431600 (98%)

这是我的问题:

1)我在上面打印的两个模型是否相等(因为我还没有弄清楚如何在PyTorch中做到这一点,所以请忽略recurrent_dropout)吗?

2)我在PyTorch中的softmax输出层出了什么问题?

非常感谢!

1 个答案:

答案 0 :(得分:1)

  1. 我打印的两个模型是否都在等效模型之上(由于我不知道如何在PyTorch中做到这一点,所以请忽略recurrent_dropout)吗?

除了辍学,我看不出有什么区别。因此,它们在结构上应该完全等效。

一个注意事项:如果以这种方式使用它,则不必初始化状态(如果您不重用状态)。您只需使用x,_ = self.blstm(x)转发LSTM,它将自动用零初始化状态。

  1. PyTorch中的softmax输出层在做什么?

PyTorch torch.nn.CrossEntropyLoss已包含softmax:

  

此标准将nn.LogSoftmax()nn.NLLLoss()合并为一个   单班。

因此,它实际上是具有logits的CE。我想这会使它更有效率。因此,您只需在最后省略softmax激活即可。