我有一个非常简单的 Pytorch LSTM,我试图在金融数据集上运行。我以前用过它的形式,直到现在它还没有让我失望。
PyTorch 中的 LSTM 看起来像这样
class LSTMPredictor(nn.Module):
def __init__(self, n_features, n_hidden, n_layers):
super().__init__()
self.lstm = nn.LSTM(
input_size=n_features,
hidden_size=n_hidden,
batch_first=True,
num_layers=n_layers,
)
self.drop = nn.Dropout(0.1)
self.regressor = nn.Linear(n_hidden, 1)
def forward(self, x):
_, (hidden, _) = self.lstm(hidden)
hidden = self.drop1(out)
preds = self.regressor(hidden[-1])
return preds
我已将其精简到我遇到问题的最小形式。
对于我有的参数
n_features = 19
n_hidden = 256
n_layers = 1
SEQ_LEN=120
在 torch 和 tf 模型中,这些都是使用的参数
现在这是我的问题
当我尝试训练这个模型时,它无法学习,损失仍然很高,并且在原始值的 +/-50% 左右波动。
在尝试调试模型时,我最终尝试了 Tensorflow (Keras) 实现(不会有什么坏处)。
超级简单
model = Sequential()
model.add(LSTM(256, input_shape=(SEQ_LEN, 19)))
model.add(Dropout(0.1))
model.add(Dense(1))
奇怪的是这个模型确实会学习!? 损失随着每经过一步而持续减少到一个点。
一些额外信息
我尝试在CPU上运行torch模型,这不是问题。 我尝试过使用火炬后端
import keras_core as keras
和 os.environ["KERAS_BACKEND"] = "torch"
运行相同的 Keras 模型,并使用火炬张量处理所有内容。当我这样做时,模型就起作用了。
我现在真的很茫然,这两种实现有什么不同? 非常感谢任何帮助:)
编辑 我想我可能已经将问题隔离为与 torch.float32 和 float64 之间的差异有关。当我使用 float32 在 torch 后端运行 keras 模型时,在它无法学习的地方会发生同样的事情,可能会发生梯度消失的情况吗?
您的前向方法是错误的,您使用
hidden
作为输入而不是 x
!,并且您没有使用 LSTM dropout 的 pytorch 标准方法。这是正确的形式:
class LSTMPredictor(nn.Module):
def __init__(self, n_features, n_hidden, n_layers, dropout_rate=0.1):
super().__init__()
self.lstm = nn.LSTM(
input_size=n_features,
hidden_size=n_hidden,
batch_first=True,
num_layers=n_layers,
dropout=dropout_rate # Apply dropout only if there are multiple LSTM layers
)
self.regressor = nn.Linear(n_hidden, 1)
def forward(self, x):
out, (hidden, _) = self.lstm(x)
preds = self.regressor(hidden[-1])
return preds
附注仅当有多个 LSTM 层时才应用 dropout。