使用 LSTM 和 CNN 对 Keras 进行时间序列分类故障排除

Troubleshooting Keras with LSTM and CNN for time series classification

我一直在尝试复制之前关于结合 LSTM 和 CNN 的问题:

但是,出于某种原因,我的 val_accuracy 自第一个纪元以来一直停留在 0.4166。

有趣的是,无论模型架构如何,这个值都大致相同。这让我觉得哪里出了问题,但我不知道从哪里开始进行故障排除。

一些数据背景:

  1. 多变量时间序列(5 个时间步 x 20 个特征)数据,有 3 个可能 类。

  2. training/validation/test 组的输入形状为 (180000, 5,20) / (60000,5,20) / (60000,5,20)。

  3. X 训练集使用 sklearn StandardScaler 标准化,然后在验证集和测试集上进行转换。 y 标签是单热编码的。

使用 LSTM 和 CNN 的示例模型:

model = keras.Sequential()
model.add(keras.layers.LSTM(200, return_sequences=True, 
                            input_shape=(X_train_scaled.shape[1], X_train_scaled.shape[2]) ))

model.add(keras.layers.Conv1D(200, kernel_size=3, activation = 'relu'))
model.add(keras.layers.GlobalMaxPooling1D())
model.add(keras.layers.Dense(100))
model.add(keras.layers.Dense(y_train.shape[1], activation='softmax'))
model.compile(loss='categorical_crossentropy', optimizer='sgd', metrics=['acc'])
  1. 模型上拟合函数的输出:
Epoch 1/20
2828/2828 [==============================] - 115s 40ms/step - loss: 1.0861 - acc: 0.4100 - val_loss: 1.0836 - val_acc: 0.4166
Epoch 2/20
2828/2828 [==============================] - 108s 38ms/step - loss: 1.0837 - acc: 0.4164 - val_loss: 1.0838 - val_acc: 0.4166
Epoch 3/20
2828/2828 [==============================] - 114s 40ms/step - loss: 1.0828 - acc: 0.4184 - val_loss: 1.0833 - val_acc: 0.4165
Epoch 4/20
2828/2828 [==============================] - 111s 39ms/step - loss: 1.0830 - acc: 0.4175 - val_loss: 1.0837 - val_acc: 0.4166
Epoch 5/20
2828/2828 [==============================] - 74s 26ms/step - loss: 1.0834 - acc: 0.4161 - val_loss: 1.0835 - val_acc: 0.4164

编辑: 在更仔细地查看我的数据之后,我现在有这样的东西:

Epoch 1/20
2828/2828 [==============================] - 129s 45ms/step - loss: 0.9560 - acc: 0.5143 - val_loss: 0.9044 - val_acc: 0.5479
Epoch 2/20
2828/2828 [==============================] - 131s 46ms/step - loss: 0.8977 - acc: 0.5520 - val_loss: 0.8937 - val_acc: 0.5527
Epoch 3/20
2828/2828 [==============================] - 116s 41ms/step - loss: 0.8887 - acc: 0.5559 - val_loss: 0.8982 - val_acc: 0.5519
Epoch 4/20
2828/2828 [==============================] - 95s 33ms/step - loss: 0.8820 - acc: 0.5616 - val_loss: 0.8834 - val_acc: 0.5606
Epoch 5/20
2828/2828 [==============================] - 100s 35ms/step - loss: 0.8786 - acc: 0.5624 - val_loss: 0.8823 - val_acc: 0.5580
Epoch 6/20
2828/2828 [==============================] - 82s 29ms/step - loss: 0.8728 - acc: 0.5661 - val_loss: 0.8797 - val_acc: 0.5628
Epoch 7/20
2828/2828 [==============================] - 120s 42ms/step - loss: 0.8723 - acc: 0.5679 - val_loss: 0.8744 - val_acc: 0.5677
Epoch 8/20
2828/2828 [==============================] - 158s 56ms/step - loss: 0.8686 - acc: 0.5670 - val_loss: 0.8733 - val_acc: 0.5679
Epoch 9/20
2828/2828 [==============================] - 146s 51ms/step - loss: 0.8646 - acc: 0.5714 - val_loss: 0.8764 - val_acc: 0.5667
Epoch 10/20
2828/2828 [==============================] - 134s 47ms/step - loss: 0.8632 - acc: 0.5720 - val_loss: 0.8715 - val_acc: 0.5701
Epoch 11/20
2828/2828 [==============================] - 141s 50ms/step - loss: 0.8612 - acc: 0.5734 - val_loss: 0.8721 - val_acc: 0.5694
Epoch 12/20
2828/2828 [==============================] - 151s 53ms/step - loss: 0.8582 - acc: 0.5753 - val_loss: 0.8690 - val_acc: 0.5713
Epoch 13/20
2828/2828 [==============================] - 137s 49ms/step - loss: 0.8554 - acc: 0.5792 - val_loss: 0.8694 - val_acc: 0.5699
Epoch 14/20
2828/2828 [==============================] - 121s 43ms/step - loss: 0.8541 - acc: 0.5779 - val_loss: 0.8709 - val_acc: 0.5691
Epoch 15/20
2828/2828 [==============================] - 134s 47ms/step - loss: 0.8476 - acc: 0.5826 - val_loss: 0.8643 - val_acc: 0.5766
Epoch 16/20
2828/2828 [==============================] - 137s 48ms/step - loss: 0.8453 - acc: 0.5838 - val_loss: 0.8664 - val_acc: 0.5742
Epoch 17/20
2828/2828 [==============================] - 152s 54ms/step - loss: 0.8409 - acc: 0.5872 - val_loss: 0.8716 - val_acc: 0.5683
Epoch 18/20
2828/2828 [==============================] - 150s 53ms/step - loss: 0.8391 - acc: 0.5892 - val_loss: 0.8663 - val_acc: 0.5726
Epoch 19/20
2828/2828 [==============================] - 133s 47ms/step - loss: 0.8341 - acc: 0.5920 - val_loss: 0.8687 - val_acc: 0.5766
Epoch 20/20
2828/2828 [==============================] - 117s 41ms/step - loss: 0.8331 - acc: 0.5913 - val_loss: 0.8643 - val_acc: 0.5764

在模型架构上工作的最初倾向是好的,但你的情况的真正问题很可能在于你的数据集是如何构建的。

您所拥有的恒定准确度很可能是因为网络只预测了一个 class(实际上您的 class 中的一个具有 41% 目标分布) .

我的建议是关注数据,而不是模型的架构。从 100 单位切换到 200 不会解决您的问题;相反,我仍然会做的是默认尝试 'adam' 优化器并微调学习率。

话虽这么说,鉴于您遇到的问题,您是否有足够的时间步长来完成您要尝试进行的特定 class化? 5 个时间步可能不足以让您的模型捕获数据集上的模式。

所有的功能真的都是必需的吗?您可以尝试 RandomForest/XGBoost 来消除所有对因变量 (y).

没有太大贡献的特征

从重申数据集和您要解决的任务开始。确保时间序列数据本身是有意义的,而不是纯粹的噪音。尝试对一小部分数据集进行过拟合,然后才继续对整个数据集进行训练。