我有一系列向量,表示随时间变化的信号。我希望将信号的某些部分分类为两个类别:1或0。使用LSTM的原因是我认为网络需要了解整个信号才能进行分类。
我的问题在于开发PyTorch模型。下面是我想出的类。
class LSTMClassifier(nn.Module): def __init__(self, input_dim, hidden_dim, label_size, batch_size): self.lstm = nn.LSTM(input_dim, hidden_dim) self.hidden2label = nn.Linear(hidden_dim, label_size) self.hidden = self.init_hidden() def init_hidden(self): return (torch.zeros(1, self.batch_size, self.hidden_dim), torch.zeros(1, self.batch_size, self.hidden_dim)) def forward(self, x): lstm_out, self.hidden = self.lstm(x, self.hidden) y = self.hidden2label(lstm_out[-1]) log_probs = F.log_softmax(y) return log_probs
然而,这个模型出现了很多形状错误,我很难理解所有问题。我首先查看了这个 Stack Overflow 问题。
回答:
你应该始终参考PyTorch 文档,特别是inputs
和outputs
部分,始终如此。
分类器应该如下所示:
需要考虑的要点:
- 始终使用
super().__init__()
,因为它会在你的神经网络中注册模块,允许使用钩子等功能。 - 使用
batch_first=True
,这样你可以传递形状为(batch, timesteps, n_features)
的输入 - 不需要使用
zeros
来init_hidden
,如果未初始化,它是默认值 - 不需要每次都将
self.hidden
传递给LSTM。此外,你不应该这样做。这意味着每个批次数据的元素在某种程度上是下一步,而批次元素应该是独立的,你可能不需要这样做。 _, (h_n, _)
返回最后一个时间步的最后一个隐藏单元,形状正好是:(num_layers * num_directions, batch, hidden_size)
。在我们的例子中,num_layers
和num_directions
是1
,所以我们得到形状为(1, batch, hidden_size)
的输出张量- 重塑为
(batch, hidden_size)
,以便可以通过线性层传递 - 返回未经激活的logits。对于二元情况,只需要一个输出。使用
torch.nn.BCEWithLogitsLoss
作为二元情况的损失函数,使用torch.nn.CrossEntropyLoss
作为多类情况的损失函数。对于二元情况,sigmoid
是合适的激活函数,而对于多类情况,softmax
或log_softmax
是合适的激活函数。 - 对于二元分类,只需要一个输出。任何小于
0
的值(如果像本例中那样返回未归一化的概率)都被视为负值,任何大于0
的值都被视为正值。