将Pandas DataFrame转换为Keras LSTM时序训练数据遇格式问题
解决Keras+Hyperas构建LSTM时的DataFrame转训练数据格式问题
嘿,我太懂你遇到的这个坑了——LSTM对输入格式的要求特别“挑剔”,稍不注意就会卡在数据维度上。先给你划个核心重点:Keras里的LSTM层期望输入是三维张量:(样本数, 时间步长, 特征数),而你的Pandas DataFrame是二维结构,必须做一步滑动窗口转换,同时还要注意时间序列数据绝对不能随机拆分!
结合你的现有代码,我帮你重构data()函数,完整解决数据格式问题:
from pandas import DataFrame import pandas as pd import numpy as np from sklearn.preprocessing import MinMaxScaler def data(): maxlen = 100 # 你设定的时间步长 feature_num = 1 # 这里只用到weightedAverage一个特征,所以设为1 # 读取数据 df = DataFrame(pd.read_json('eth_usd_polo.json')) # 归一化数据 scaler = MinMaxScaler(feature_range=(-1,1)) df['weightedAverage'] = scaler.fit_transform(df[['weightedAverage']]) # -------------------------- 关键:生成LSTM所需的序列数据 -------------------------- def create_time_sequences(raw_data, seq_length): X, y = [], [] # 遍历生成滑动窗口:每个窗口取seq_length个连续数据,对应下一个时间点的数值为标签 for i in range(len(raw_data) - seq_length): X.append(raw_data[i:i+seq_length]) y.append(raw_data[i+seq_length]) return np.array(X), np.array(y) # 提取归一化后的特征列,转成numpy数组 scaled_data = df['weightedAverage'].values.reshape(-1, 1) # 生成序列数据 X, y = create_time_sequences(scaled_data, maxlen) # -------------------------- 拆分训练测试数据:严格按时间顺序! -------------------------- # 用前80%数据做训练,后20%做测试(绝对不能随机打乱时间序列) train_split = int(len(X) * 0.8) x_train, x_test = X[:train_split], X[train_split:] y_train, y_test = y[:train_split], y[train_split:] # 调整为LSTM要求的三维格式:(样本数, 时间步长, 特征数) x_train = x_train.reshape(x_train.shape[0], x_train.shape[1], feature_num) x_test = x_test.reshape(x_test.shape[0], x_test.shape[1], feature_num) return x_train, y_train, x_test, y_test
几个必须注意的细节:
- 特征数修正:你原来写的
max_features=20000是文本任务里Embedding层的词汇量参数,这里是单特征价格预测,得改成feature_num=1,不然会和LSTM输入维度不匹配。 - 滑动窗口逻辑:
create_time_sequences函数专门把一维时间序列转成LSTM需要的样本序列,每个样本包含maxlen个连续时间步的特征,对应下一个时间点的价格作为预测目标。 - 训练集拆分规则:绝对不能用
train_test_split的默认随机拆分!时间序列数据必须保持先后顺序,直接按比例切割前半段为训练集、后半段为测试集才是正确做法。 - 维度调整:最后一步的
reshape是把二维的序列数组(样本数, 时间步长)转成三维张量(样本数, 时间步长, 特征数),这是LSTM层接收输入的硬性要求。
这样处理后,你的数据就能直接喂给Hyperas里的LSTM模型了。如果后续要加入更多特征(比如开盘价、成交量),只需要把scaled_data改成多列的数组,同时把feature_num改成对应的特征数量就行。
内容的提问来源于stack exchange,提问作者Gurkang
相关产品推荐
相关产品推荐

