我正在尝试在 PyTorch 中的堆叠 LSTM 网络层之间进行标准化。网络看起来像这样:
class LSTMClassifier(nn.Module):
def __init__(self, input_dim, hidden_dim, layer_dim, output_dim):
super().__init__()
self.hidden_dim = hidden_dim
self.layer_dim = layer_dim
self.lstm1 = nn.LSTM(input_dim, hidden_dim, layer_dim, batch_first=True)
self.lstm2 = nn.LSTM(input_dim, hidden_dim, hidden_dim, batch_first=True)
self.fc1 = nn.Linear(hidden_dim, 32)
self.fc2 = nn.Linear(32, 1)
self.dropout = nn.Dropout(p=0.2)
self.batch_normalisation1 = nn.BatchNorm1d(hidden_dim)
self.batch_normalisation2 = nn.BatchNorm1d(hidden_dim)
def forward(self, x):
h0, c0 = self.init_hidden(x)
out, (hn1, cn1) = self.lstm1(x, (h0, c0))
out = self.dropout(out) # error line
out = self.batch_normalisation1(out)
h1, c1 = self.init_hidden(out)
out, (hn2, cn2) = self.lstm2(out, (h1, c1))
out = self.dropout(out)
out = self.batch_normalisation1(out)
h2, c2 = self.init_hidden(out)
out, (hn3, cn3) = self.lstm2(out, (h2, c2))
out = self.dropout(out)
out = self.batch_normalisation1(out)
out = self.fc1(out[:, -1, :])
out = self.dropout(out)
out = self.fc2(out)
return out
def init_hidden(self, x):
h0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim)
c0 = torch.zeros(self.layer_dim, x.size(0), self.hidden_dim)
return [t for t in (h0, c0)]
我在上面评论过的地方出现了一个错误,这是由于 BatchNorm1d 期望二维输入而发生的。
特别是,我正在初始化模型并将批量数据传递到网络:
model = LSTMClassifier(5, 128, 3, 1)
model(X)
错误:
RuntimeError: running_mean should contain 3 elements not 128
X 输入张量的形状为
torch.Size([10, 3, 5])
,即批量大小为 10,每个输入的尺寸为 3 x 5,即 5 个特征和 3 个时间步长。
该错误是由于 BatchNorm1d 试图在错误的维度上进行标准化而产生的 - 在网络中,变量输出具有形状
torch.Size([1, 3, 128])
,即 5 个输入特征映射到 128 个超变量。
我可以重塑转发函数内的变量,但这似乎没有必要。我也尝试过使用 BatchNorm2d,但它需要 4d 张量,而我的变量 out 不是。有什么办法可以克服这个吗?
此外,我正在尝试在我的网络中添加标准化以加快训练速度 - 我不完全确定 PyTorch BatchNorm 函数是如何工作的,所以希望对此进行解释。具体来说,为什么我们应该在时间维度而不是特征维度上进行标准化?
这里有人指出批量归一化不能用于LSTM。 RNN & LSTM 中使用批量归一化正常吗?