Keras (R) - 为什么所有输入的预测概率(二进制分类)都相同?

Keras (R) - Why are predicted probabilities (binary classification) the same for all inputs?

我使用 R 中的 Keras 来训练用于时间序列预测的完全连接的神经网络(二进制 class化)。为了使用标准的多层感知器来完成这项任务,我使用滑动 window 方法转换我的时间序列数据(向数据添加滞后输入特征)。因此,使用 1 个二进制标签、2 个输入时间序列和 2 个回溯(用于说明),转换后的数据具有以下结构:

    label     a     b     a.1     b.1     a.2     b.2
1    1       0.1   0.3     NA      NA      NA      NA
2    1       0.2   0.2     0.1    0.3      NA      NA
3    0       0.4   0.4     0.2    0.2      0.1    0.3
4    1       0.1   0.6     0.4    0.4      0.2    0.2
5    0       0.15  0.25    0.1    0.6      0.4    0.4
...

在省略 NA 行并删除 a 和 b 列后,使用的数据矩阵如下所示:

    label    a.1     b.1     a.2     b.2
3    0       0.2     0.2     0.1     0.3
4    1       0.4     0.4     0.2     0.2
5    0       0.1     0.6     0.4     0.4
...

在接下来的步骤中,我创建了两个阈值来拆分训练、验证和测试集中的数据,并根据这些阈值进行实际拆分:

## Thresholds
train_valid_split = 1700
valid_test_split = 1800

## amount of features (columns of data matrix minus first label column)
features = ncol(data_mlp) - 1 

## Container for train, validation and test set (both input x and label y)
train_x = array(0, dim = c(train_valid_split, features))
train_y = array(0, dim = c(train_valid_split))
valid_x = array(0, dim = c((valid_test_split-train_valid_split), features))
valid_y = array(0, dim = c((valid_test_split-train_valid_split)))
test_x = array(0, dim = c((nrow(data_mlp)-valid_test_split), features))
test_y = array(0, dim = c((nrow(data_mlp)-valid_test_split)))

## Fill container with the data
train_x = data_mlp[1:train_valid_split, 2:ncol(data_mlp)]
train_y = data_mlp[1:train_valid_split, 1, drop=F]
valid_x = data_mlp[(train_valid_split+1):valid_test_split, 2:ncol(data_mlp)]
valid_y = data_mlp[(train_valid_split+1):valid_test_split, 1, drop=F]
test_x = data_mlp[(valid_test_split+1):nrow(data_mlp), 2:ncol(data_mlp)]
test_y = data_mlp[(valid_test_split+1):nrow(data_mlp), 1, drop=F]

计算验证步骤后,我训练并拟合了以下 Keras 模型:

## Validation steps
valid_steps = valid_test_split - train_valid_split

## Keras sequential model
model = keras_model_sequential() %>%
  layer_dense(units = 32, input_shape = c(features),
              activation = "relu") %>%
  layer_dense(units = 1, activation = "sigmoid")

model %>% compile(
  optimizer = "adam", # rmsprop
  loss = "binary_crossentropy",
  metrics = c("accuracy")
)

history = model %>% fit(
  x = train_x,
  y = train_y,
  steps_per_epoch = 90,
  epochs = 10,
  validation_data = list(valid_x, valid_y),
  validation_steps = valid_steps,
  shuffle=FALSE
)

但是,当通过预测所有测试输入的 class 概率来评估测试集上的模型时,所有概率都完全相同。因此,每个输入都预测相同的 class。

> results = model %>% predict(test_x)
> results
           [,1]
 [1,] 0.5740806
 [2,] 0.5740806
 [3,] 0.5740806
 [4,] 0.5740806
 [5,] 0.5740806
 [6,] 0.5740806
 [7,] 0.5740806
  ...

我不明白为什么概率是一样的。我尝试使用不同的输入数据、不同的回顾(或多或少的滞后)、更多的时期、更多的 steps_per_epoch、不同的优化器、不同的单位数量等。预测的概率发生了变化,但它们始终相同所有输入。

有趣的是,具有相同验证和测试拆分以及相同回顾的相同数据的 lstm 模型不会产生相同的概率。 lstm 结果更合理。但我也想尝试 MLP + 滑动 window 方法,因为我读到它可能会在某些任务上产生更好的预测性能。所以我的猜测是我的数据准备(滑动 window)或模型架构有错误,但我无法弄清楚它是什么...

如果您对结果为何如此以及我如何更改它有任何建议,我将不胜感激。

非常感谢。

最好的火影

PS: 如果您需要更多信息,请告诉我它是什么,我会尽力回答。

代码中有错字,导致输入向量仅为零。现在它已修复并且代码可以正常工作。