You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

如何将Conv1D与LSTM结合处理时间序列预测任务?

解决Conv1D+LSTM时间序列预测的维度不匹配问题

首先咱们先拆解你遇到的错误根源:ValueError: Error when checking input: expected conv1d_1_input to have shape (None, 12, 1) but got array with shape (1, 64, 1)

这个错误暴露出两个核心问题:

  1. 输入维度完全错误:Conv1D要求输入格式是(样本数, 时间步长, 特征数),但你通过X_train_t = X_train[None,:]得到的是(1, 64, 1)——相当于把整个训练集当成了1个样本,时间步长变成了64,和你定义的input_shape=(12,1)完全不匹配。
  2. 未正确构造时间序列样本:时间序列预测需要用滑动窗口生成输入序列(比如用过去12个时间点的数据预测下一个点),而不是简单把一维数据直接丢给模型。

接下来我给你修正完整的代码,每一步都加注释说明:

1. 数据预处理与滑动窗口构造

首先要把原始数据转换成Conv1D和LSTM需要的序列格式:

import pandas as pd
import numpy as np
from pandas.tseries.offsets import MonthEnd
from sklearn.preprocessing import MinMaxScaler
from tensorflow.keras.models import Sequential
from tensorflow.keras.layers import Conv1D, LSTM, Dense
from tensorflow.keras import backend as K

# 1. 读取并预处理数据
df = pd.read_csv('D://data.csv', engine='python')
df['DATE_'] = pd.to_datetime(df['DATE_']) + MonthEnd(1)
df = df.set_index('DATE_')

# 2. 划分训练测试集(保持你原来的划分逻辑,对应后6个测试样本)
split_date = pd.Timestamp('03-01-2015')
train = df.loc[:split_date, ['COLUMN3DATA']]
test = df.loc[split_date:, ['COLUMN3DATA']]

# 3. 数据归一化
sc = MinMaxScaler()
train_sc = sc.fit_transform(train)
test_sc = sc.transform(test)

# 4. 定义滑动窗口函数,生成序列样本
def create_sequences(data, time_steps=12):
    """
    将一维时间序列转换成 (样本数, 时间步长, 特征数) 的格式
    data: 归一化后的一维数组
    time_steps: 每个输入序列包含的时间点数量(比如用过去12个点预测下一个点)
    """
    X, y = [], []
    for i in range(len(data) - time_steps):
        # 取过去time_steps个时间点作为输入
        X.append(data[i:i+time_steps])
        # 取第i+time_steps个时间点作为目标值
        y.append(data[i+time_steps])
    return np.array(X), np.array(y)

# 设置时间步长为12(和模型input_shape对应)
TIME_STEPS = 12

# 生成训练集和测试集的序列
X_train, y_train = create_sequences(train_sc, TIME_STEPS)
X_test, y_test = create_sequences(test_sc, TIME_STEPS)

# 检查形状:X_train应该是 (样本数, 12, 1),y_train是 (样本数, 1)
print("X_train形状:", X_train.shape)
print("y_train形状:", y_train.shape)

2. 正确搭建Conv1D+LSTM模型

Conv1D的输出格式是(样本数, 新时间步长, 滤波器数量),和LSTM要求的(样本数, 时间步长, 特征数)完全匹配,可以直接衔接:

K.clear_session()

model = Sequential()
# Conv1D层:输入形状是(TIME_STEPS, 1),6个滤波器,卷积核大小3,激活relu
model.add(Conv1D(filters=6, kernel_size=3, activation='relu', input_shape=(TIME_STEPS, 1)))
# LSTM层:接收Conv1D的输出,6个神经元,返回序列给下一层LSTM
model.add(LSTM(6, return_sequences=True))
# 第二层LSTM:3个神经元,不返回序列
model.add(LSTM(3))
# 输出层:预测单值
model.add(Dense(1))

# 编译模型
model.compile(loss='mean_squared_error', optimizer='adam')
model.summary()

# 训练模型
model.fit(X_train, y_train, epochs=400, batch_size=10, verbose=1)

# 预测并反归一化回原始尺度
y_pred = model.predict(X_test)
y_pred_actual = sc.inverse_transform(y_pred)
y_test_actual = sc.inverse_transform(y_test)

关键细节补充

  • 滑动窗口的必要性:时间序列预测的核心是用历史序列预测未来,必须把一维数据转换成(样本数, 时间步长, 特征数)的格式,每个样本对应一段连续的历史数据。
  • Conv1D与LSTM的优势结合:Conv1D负责提取局部时间特征(比如短期波动模式),LSTM负责捕捉长期时序依赖,两者结合能同时兼顾局部和全局的时间规律。
  • 测试集样本数调整:如果你的测试集只有6个样本,时间步长12会导致无法生成测试样本,此时可以把TIME_STEPS改成3或6,确保测试集能生成足够的预测样本。

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

火山引擎 最新活动