在R中训练LSTM模型时维度不匹配问题求助
R中LSTM预测每小时呼叫量的维度适配问题解决
问题背景
需在R中训练LSTM模型,预测未来两个月每小时呼叫量(Calls Count),指定call_day_of_week_name、call_month、Calls Count、call_year参与预测。初始尝试时因过滤未来日期的历史数据导致返回空数据集,触发报错:
Error in py_call_impl(callable, call_args$unnamed, call_args$named) : ValueError: cannot reshape array of size 0 into shape (1,1,1)
注释过滤代码后改用全量历史数据,又出现维度不匹配报错:
Error in py_call_impl(callable, call_args$unnamed, call_args$named) : ValueError: cannot reshape array of size 113472 into shape (1,1,1)
报错核心原因
- 第一个错误:未来日期无对应历史数据,过滤后
current_data为空,导致x_train/y_train是空数组,无法完成reshape操作。 - 第二个错误:
- 误用全量历史数据作为单天训练数据,
x_train长度为113472,reshape为(113472,1,1)本身合法,但后续预测结果长度与predicted_data单天24个时间槽的维度不匹配。 - 循环内重复训练模型完全不合理,既浪费计算资源,也不符合时间序列预测的逻辑。
- 误用全量历史数据作为单天训练数据,
分步解决方案
1. 重构数据准备逻辑
放弃“每天循环训练模型”的错误思路,用所有历史数据训练一次通用模型,再用模型对未来每个日期的小时级特征做预测。
2. 处理分类特征编码
call_day_of_week_name是分类变量,需转换为数值特征:
- 标签编码:将星期几映射为0-6的数值
- 独热编码:生成7个二进制特征(对应一周7天)
3. 正确构造LSTM输入维度
LSTM要求输入为三维数组:[样本数, 时间步长, 特征数]。这里的特征应包含:
- 编码后的
call_day_of_week_name call_monthcall_yearcall_hour
4. 生成未来日期的小时级特征
为未来两个月的每个日期生成24小时对应的特征矩阵,作为模型的预测输入。
修正后的代码示例
# 1. 预处理历史数据:编码分类特征 library(keras) library(dplyr) # 标签编码星期几 filtered_data <- filtered_data %>% mutate( day_of_week_num = as.integer(factor(call_day_of_week_name, levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))) - 1 ) # 构造特征矩阵与目标变量 features <- filtered_data %>% select(day_of_week_num, call_month, call_year, call_hour) %>% as.matrix() target <- filtered_data$`Calls Count` # 归一化特征(LSTM对数据尺度敏感) scaler_features <- scale(features) scaler_target <- scale(matrix(target)) # 2. 调整输入维度为LSTM要求的三维:[样本数, 时间步长, 特征数] # 这里时间步长设为1(单步预测),特征数为4 x_train <- array_reshape(scaler_features, dim = c(nrow(scaler_features), 1, ncol(scaler_features))) y_train <- scaler_target # 3. 构建并训练LSTM模型(仅训练一次) model <- keras_model_sequential() %>% layer_lstm(units = 64, input_shape = c(1, ncol(scaler_features))) %>% layer_dense(units = 1) model %>% compile( loss = 'mean_squared_error', optimizer = optimizer_adam(learning_rate = 0.001) ) # 训练模型 history <- model %>% fit( x_train, y_train, epochs = 50, batch_size = 64, validation_split = 0.2 ) # 4. 生成未来日期的小时级特征 future_hours <- expand.grid( date = dates, call_hour = 0:23 ) %>% mutate( call_day_of_week_name = weekdays(date), day_of_week_num = as.integer(factor(call_day_of_week_name, levels = c("Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"))) - 1, call_month = as.integer(format(date, "%m")), call_year = as.integer(format(date, "%Y")) ) %>% select(day_of_week_num, call_month, call_year, call_hour) %>% as.matrix() # 归一化未来特征(使用历史数据的scaler) future_features_scaled <- scale(future_hours, center = attr(scaler_features, "scaled:center"), scale = attr(scaler_features, "scaled:scale")) # 调整未来特征维度 x_pred <- array_reshape(future_features_scaled, dim = c(nrow(future_features_scaled), 1, ncol(future_features_scaled))) # 5. 预测并反归一化结果 predictions_scaled <- model %>% predict(x_pred) predictions <- predictions_scaled * attr(scaler_target, "scaled:scale") + attr(scaler_target, "scaled:center") # 6. 将预测结果填充到predicted_data # 按日期分组,将24小时预测值赋值到对应行 predicted_data[, 3:ncol(predicted_data)] <- matrix(predictions, nrow = length(dates), byrow = TRUE) # 处理银行假日 predicted_data[predicted_data$date == as.Date("2023-08-28"), 3:ncol(predicted_data)] <- NA
关键说明
- 不再在循环内重复训练模型,大幅提升效率;
- 完整使用指定的4个变量作为特征,符合预测需求;
- 解决了维度不匹配问题,预测结果与
predicted_data的时间槽维度完全对齐; - 添加数据归一化步骤,提升LSTM模型的训练稳定性与预测精度。
内容的提问来源于stack exchange,提问作者Vern
相关产品推荐
相关产品推荐

