如何为RNN/LSTM模型重塑数据集?二进制分类维度错误求助
解决LSTM输入维度不匹配的问题
这个错误的核心原因是LSTM层要求输入是3维数组,形状为 (样本数, 时间步长, 特征数),但你当前的x_train是2维数组(1415684, 6)——你把每个时间步的数据都当成了独立样本,而没有按患者分组形成完整的时间序列样本。
针对你的患者时序数据集,我们需要先按患者编号分组,把每个患者的所有时间步数据打包成一个序列样本,再调整成LSTM需要的3维格式。下面是具体的修改方案:
步骤1:用Pandas加载并分组数据(更方便处理时序分组)
Pandas的分组功能可以轻松按患者ID聚合时间序列,替代原来的np.loadtxt:
import numpy as np import pandas as pd from keras.models import Sequential from keras.layers import Dense, LSTM from keras.preprocessing import sequence # 固定随机种子 np.random.seed(7) # 加载训练/测试数据,指定列名方便后续操作 train_df = pd.read_csv("featwithsignalsTRAIN.txt", header=None, names=["patient_id", "time", "X", "Y", "Z", "kurtosis", "skewness", "angle", "label"]) test_df = pd.read_csv("featwithsignalsTEST.txt", header=None, names=["patient_id", "time", "X", "Y", "Z", "kurtosis", "skewness", "angle", "label"])
步骤2:按患者ID生成时序样本
每个患者的所有时间步数据构成一个序列样本,标签取该患者的唯一标签(假设每个患者对应一个分类结果):
# 处理训练集 train_groups = train_df.groupby("patient_id") x_train = [] y_train = [] for _, patient_data in train_groups: # 提取你需要的6个特征列 features = patient_data[["X", "Y", "Z", "kurtosis", "skewness", "angle"]].values x_train.append(features) # 每个患者的标签唯一,取第一个即可 y_train.append(patient_data["label"].iloc[0]) # 处理测试集(和训练集逻辑一致) test_groups = test_df.groupby("patient_id") x_test = [] y_test = [] for _, patient_data in test_groups: features = patient_data[["X", "Y", "Z", "kurtosis", "skewness", "angle"]].values x_test.append(features) y_test.append(patient_data["label"].iloc[0])
步骤3:统一序列长度(关键!)
不同患者的时间步数量可能不同,LSTM要求所有样本的时间步长度一致,我们用pad_sequences补零(或截断)到最大时间步长:
# 找出训练集中最长的序列长度 max_time_steps = max([seq.shape[0] for seq in x_train]) # 统一训练/测试集的序列长度 x_train = sequence.pad_sequences(x_train, maxlen=max_time_steps, dtype="float32") x_test = sequence.pad_sequences(x_test, maxlen=max_time_steps, dtype="float32") # 把标签转成numpy数组 y_train = np.array(y_train) y_test = np.array(y_test)
步骤4:修改模型适配3维输入
调整LSTM层的输入参数,同时修正输出层(二进制分类只需要1个神经元+Sigmoid激活):
model = Sequential() # 输入形状为(时间步长, 特征数),对应我们处理后的3维数据 model.add(LSTM(20, dropout=0.2, input_shape=(max_time_steps, 6))) # 二进制分类输出层:1个神经元+Sigmoid激活 model.add(Dense(1, activation='sigmoid')) model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy']) # 查看模型结构确认输入输出 model.summary() # 开始训练 model.fit(x_train, y_train, epochs=2, validation_data=(x_test, y_test))
关键说明
- 为什么原来的代码报错?因为你把140多万个时间步当成了140多万个样本,但LSTM需要的是每个患者是一个样本,每个样本包含该患者的所有时间步数据,所以维度从2D变成了3D。
- 如果你的数据集里每个患者的时间步数量完全一致,可以跳过
pad_sequences步骤,直接把分组后的列表转成numpy数组即可。 - 输出层用
Dense(1, activation='sigmoid')是二进制分类的标准配置,原来的Dense(4)不符合任务需求。
内容的提问来源于stack exchange,提问作者Hadeer El-Zayat
相关产品推荐
相关产品推荐

