You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Keras(R语言版):二分类任务中所有输入的预测概率为何相同?

用R语言Keras实现滑动窗口式时间序列二分类(全连接神经网络)

我来分享一套完整的实现方案,刚好匹配你提到的「多输入时间序列+滑动窗口转结构化数据+MLP二分类」的需求,一步步来拆解:

1. 先明确滑动窗口的转换逻辑

就像你举的例子:1个二分类标签、2条输入序列(a、b)、回溯步长为2的情况下,转换后的数据结构会是这样(我补全了完整的样本逻辑):

labelaba.1b.1a.2b.2
11.00.1NANANANA
10.20.21.00.1NANA
00.50.30.20.21.00.1
.....................

这里的a.1是a序列的前1步值,a.2是前2步值;前回溯步长个样本因为没有足够的历史数据会出现NA,后续我们可以直接丢弃这些样本,或者用填充法处理。

2. 实现滑动窗口数据转换(R代码)

首先我们先构造模拟数据,然后写一个通用的滑动窗口转换函数:

# 构造模拟时间序列数据(替换成你的真实数据即可)
set.seed(123)
n <- 100 # 样本量
df <- data.frame(
  label = sample(c(0,1), n, replace = TRUE), # 二分类标签
  a = rnorm(n, mean = 0, sd = 1),            # 输入序列a
  b = rnorm(n, mean = 1, sd = 0.5)           # 输入序列b
)

# 滑动窗口转换函数:生成滞后特征
create_sliding_window <- function(data, input_cols, label_col, window_size) {
  result <- data.frame()
  
  # 从第window_size+1个样本开始,因为前window_size个没有足够历史数据
  for(i in (window_size + 1):nrow(data)) {
    # 提取当前样本的标签
    current_label <- data[i, label_col]
    # 提取当前样本的原始输入特征
    current_inputs <- data[i, input_cols]
    # 提取window_size步的滞后特征,按步长命名(比如a.1、a.2)
    lag_features <- do.call(cbind, lapply(input_cols, function(col) {
      lag_vals <- rev(data[(i - window_size):(i - 1), col])
      names(lag_vals) <- paste0(col, ".", 1:window_size)
      lag_vals
    }))
    # 合并当前样本的所有特征和标签
    current_row <- cbind(current_label, current_inputs, lag_features)
    result <- rbind(result, current_row)
  }
  
  # 重命名标签列
  colnames(result)[1] <- label_col
  return(result)
}

# 调用函数:输入列是c("a","b"),标签列是"label",窗口大小2
window_df <- create_sliding_window(df, input_cols = c("a","b"), label_col = "label", window_size = 2)

运行完后,window_df就是适合MLP输入的结构化数据,已经自动跳过了前2个有NA的样本。

3. 数据预处理:标准化+划分数据集

全连接神经网络对数据尺度很敏感,必须做标准化,同时划分训练/测试集:

library(keras)

# 分离特征矩阵和标签向量
X <- as.matrix(window_df[, !colnames(window_df) %in% "label"])
y <- as.matrix(window_df$label)

# 按7:3划分训练测试集
train_idx <- sample(1:nrow(X), 0.7*nrow(X))
X_train <- X[train_idx, ]
X_test <- X[-train_idx, ]
y_train <- y[train_idx]
y_test <- y[-train_idx]

# 标准化特征(只用训练集的统计量,避免数据泄露)
scaler <- preprocessing_scale()
X_train_scaled <- fit_transform(scaler, X_train)
X_test_scaled <- transform(scaler, X_test)

4. 构建并训练全连接神经网络

接下来用Keras搭建MLP模型,针对二分类任务做配置:

# 构建MLP模型
model <- keras_model_sequential() %>%
  # 输入层+第一个隐藏层:32个神经元,ReLU激活
  layer_dense(units = 32, activation = "relu", input_shape = ncol(X_train_scaled)) %>%
  # Dropout层:随机丢弃20%神经元,防止过拟合
  layer_dropout(rate = 0.2) %>%
  # 第二个隐藏层:16个神经元,ReLU激活
  layer_dense(units = 16, activation = "relu") %>%
  # 输出层:1个神经元,Sigmoid激活(二分类专属)
  layer_dense(units = 1, activation = "sigmoid")

# 编译模型:用Adam优化器,二元交叉熵损失,监控准确率
model %>% compile(
  optimizer = optimizer_adam(learning_rate = 0.001),
  loss = "binary_crossentropy",
  metrics = c("accuracy")
)

# 查看模型结构
summary(model)

# 训练模型:用训练集的20%做验证,训练50轮
history <- model %>% fit(
  x = X_train_scaled,
  y = y_train,
  batch_size = 8,
  epochs = 50,
  validation_split = 0.2,
  verbose = 1
)

# 绘制训练曲线(查看训练/验证集的损失和准确率变化)
plot(history)

5. 模型评估与预测

最后在测试集上验证模型效果,并生成预测结果:

# 在测试集上评估模型性能
model %>% evaluate(X_test_scaled, y_test)

# 生成预测概率
y_pred_prob <- model %>% predict(X_test_scaled)
# 转换为类别标签(阈值设为0.5,可根据需求调整)
y_pred <- ifelse(y_pred_prob > 0.5, 1, 0)

# 生成混淆矩阵,查看分类效果
table(Actual = y_test, Predicted = y_pred)

几个关键注意事项

  • 滑动窗口大小选择:别凭感觉定,建议用交叉验证尝试不同的窗口大小(比如1、2、5、10),选验证集性能最好的。
  • 缺失值处理:如果不想丢弃前window_size个样本,可以用滚动均值、中位数或者前向填充(比如zoo包的na.locf()函数)来补NA。
  • 过拟合应对:除了Dropout层,还可以加L2正则化(比如layer_dense(..., kernel_regularizer = regularizer_l2(0.001))),或者用早停法(callback_early_stopping(patience = 5)),防止模型在训练集上过拟合。

内容的提问来源于stack exchange,提问作者hokage555

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:32:14