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

Python RNN LSTM模型准确率极低问题求助

解决LSTM模型训练无进展、准确率极低的问题

从你的描述和代码来看,模型训练时损失和准确率完全没有变化,核心原因是时间序列构造错误,再加上几个其他的小问题,导致模型根本无法学习。下面一步步帮你修正:


先回顾你的问题背景

你使用的数据集包含以下字段:

患者编号、时间(毫秒)、X/Y/Z归一化值、峰度、偏度、俯仰角(pitch)、翻滚角(roll)、偏航角(yaw)、标签

数据集样例:

1,15,-0.248010047716,0.00378335508419,-0.0152548459993,-86.3738760481,0.872322164158,-3.51314800063,0
1,31,-0.248010047716,0.00378335508419,-0.0152548459993,-86.3738760481,0.872322164158,-3.51314800063,0
1,46,-0.267422664673,0.0051143782875,-0.0191247001961,-85.7662354031,1.0928406847,-4.08015176908,0
1,62,-0.267422664673,0.0051143782875,-0.0191247001961,-85.7662354031,1.0928406847,-4.08015176908,0

你的训练日志显示完全没有进展:

Epoch 1/20 - 63s - loss: 15.0343 - acc: 0.0570
Epoch 2/20 - 60s - loss: 15.0343 - acc: 0.0570
Epoch 3/20 - 60s - loss: 15.0343 - acc: 0.0570
Epoch 4/20 - 60s - loss: 15.0343 - acc: 0.0570


1. 最关键的问题:时间序列维度构造错误

LSTM的核心是捕捉时间序列的依赖关系,但你现在把每个单独的时间步作为一个样本(reshape((-1,1,6))),相当于每个样本只有1个时间点,LSTM完全没法学习时间上的规律,这就失去了用LSTM的意义。

你需要按患者分组,把连续的时间步组合成序列样本(比如每个序列包含20个连续时间点),代码示例:

def create_sequences(data, time_steps=20):
    X, y = [], []
    # 按患者ID分组,不同患者的序列不能混在一起
    patient_ids = np.unique(data[:, 0])
    for pid in patient_ids:
        patient_data = data[data[:, 0] == pid]
        # 提取特征和标签
        features = patient_data[:, [2,3,4,5,6,7]]
        labels = patient_data[:, 8]
        # 为当前患者生成序列样本
        for i in range(len(features) - time_steps):
            X.append(features[i:i+time_steps])
            # 这里用序列最后一个时间步的标签作为样本标签,可根据任务调整
            y.append(labels[i+time_steps])
    return np.array(X), np.array(y)

# 重新构造训练和测试序列
x_train, y_train = create_sequences(train, time_steps=20)
x_test, y_test = create_sequences(test, time_steps=20)

# 此时x_train的形状应为 (样本数, 时间步长, 特征数),比如 (N,20,6)
print(x_train.shape)

2. 输出层激活函数与任务不匹配

你的任务是二分类(标签0/1),但你用了softmax激活函数(这是多分类任务用的),二分类应该用sigmoid激活,同时要确保标签是浮点型:

# 转换标签为浮点型
y_train = y_train.astype(float)
y_test = y_test.astype(float)

# 重构模型
model = Sequential()
# 输入形状改为 (时间步长, 特征数)
model.add(LSTM(64, activation='relu', input_shape=(x_train.shape[1], x_train.shape[2])))
model.add(Dense(1, activation='sigmoid'))  # 替换为sigmoid
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

3. 特征尺度不一致导致训练不稳定

你的特征尺度差异极大:X/Y/Z是接近0的小数,而峰度值在-86左右,姿态角也有不同尺度,这会导致模型梯度不稳定,难以收敛。需要用标准化处理特征:

from sklearn.preprocessing import StandardScaler

# 用训练+测试的所有特征拟合标准化器,避免数据泄露
all_features = np.vstack([train[:,[2,3,4,5,6,7]], test[:,[2,3,4,5,6,7]]])
scaler = StandardScaler()
scaler.fit(all_features)

# 对训练和测试特征做标准化
train_scaled = train.copy()
train_scaled[:,[2,3,4,5,6,7]] = scaler.transform(train[:,[2,3,4,5,6,7]])
test_scaled = test.copy()
test_scaled[:,[2,3,4,5,6,7]] = scaler.transform(test[:,[2,3,4,5,6,7]])

# 用标准化后的数据重新构造序列
x_train, y_train = create_sequences(train_scaled, time_steps=20)
x_test, y_test = create_sequences(test_scaled, time_steps=20)

4. 检查数据集的类别平衡

从你的准确率0.057来看,大概率存在严重的类别不平衡(比如94.3%的样本是标签1),模型直接输出多数类就能得到这个准确率,根本不需要学习。先统计标签分布:

print("训练集标签分布:")
print(np.bincount(y_train.astype(int)))
print("测试集标签分布:")
print(np.bincount(y_test.astype(int)))

如果确实不平衡,可以尝试:

  • 过采样少数类/欠采样多数类
  • 在model.fit中加入class_weight参数,给少数类更高的权重,比如class_weight={0:18, 1:1}(假设0类占比5%)

5. 可选:调整模型结构提升性能

如果前面的问题都解决了,还可以尝试优化模型结构,比如增加LSTM层或Dropout防止过拟合:

model = Sequential()
model.add(LSTM(64, activation='relu', return_sequences=True, input_shape=(x_train.shape[1], x_train.shape[2])))
model.add(Dropout(0.2))
model.add(LSTM(32, activation='relu'))
model.add(Dense(1, activation='sigmoid'))
model.compile(loss='binary_crossentropy', optimizer='adam', metrics=['accuracy'])

把这些步骤逐一修正后,再训练模型,应该能看到损失下降和准确率提升的过程。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 07:16:23