我在R中使用Keras训练了一个全连接神经网络,用于时间序列预测(二元分类)。为了使用标准的多层感知器来完成这项任务,我使用了滑动窗口方法对时间序列数据进行转换(添加滞后输入特征到数据中)。因此,假设有一个二元标签,两个输入时间序列,查看回溯期为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
...
在接下来的步骤中,我为数据划分创建了两个阈值,用于将数据划分为训练集、验证集和测试集,并基于这些阈值进行实际的划分:
## 阈值
train_valid_split = 1700
valid_test_split = 1800
## 特征数量(数据矩阵的列数减去第一个标签列)
features = ncol(data_mlp) - 1
## 用于存放训练集、验证集和测试集的容器(包括输入x和标签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)))
## 使用数据填充容器
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模型:
## 验证步骤
valid_steps = valid_test_split - train_valid_split
## Keras顺序模型
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)
然而,在通过预测所有测试输入的类概率来评估模型时,所有概率都完全相同。因此,对于每个输入都预测了相同的类别。
> 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
...
我不明白为什么概率会相同。我尝试了不同的输入数据、不同的回溯期(更多或更少的滞后)、更多的epoch、更多的steps_per_epoch、不同的优化器、不同的单位数量等。预测的概率确实发生了变化,但它们始终对所有输入都是相同的。
有趣的是,在相同的数据上使用相同的验证和测试划分以及相同的回溯期的LSTM模型不会产生相同的概率。LSTM的结果要合理得多。但我也想尝试MLP + 滑动窗口方法,因为我读到它在某些任务上可能会带来更好的预测性能。所以我猜测我的数据准备(滑动窗口)或模型架构中可能存在错误,但我无法找出问题所在…
如果你有任何关于结果为何如此以及我如何能改变它的建议,我将非常感激。
非常感谢。
最好的祝愿,hokage
附注:如果你需要更多信息,请告诉我需要什么,我会尽力回答。
回答:
代码中有一个拼写错误,导致输入向量只有零。现在已修复,代码正常工作。