如何解决LSTM模型仅输出概率分布、无法有效分类曲线极值的问题?
问题描述
我构建了一个用于预测曲线是否达到最大值/最小值或非极值的模型,数据集标签定义为:
- 0:非极值
- 1:最小值
- 2:最大值
使用scipy.signal.savgol_filter对数据进行平滑处理以消除噪声极值,但训练过程中模型仅按数据集类别比例输出固定概率分布,无法实现有效预测,训练损失也无改善。
预测示例代码及输出
predictions1 = model1.predict(trainX) i = 0 while (i < len(predictions1)): print(f'{predictions1[i]} - {trainY[i]}') i+=1 [0.3735279 0.3069231 0.31954893] - 2.0 [0.37347972 0.30695325 0.319567 ] - 0.0 [0.37339583 0.3070028 0.31960133] - 0.0 [0.3732677 0.30707628 0.31965607] - 1.0 [0.3731317 0.30715463 0.31971365] - 2.0 [0.37299597 0.30723253 0.31977156] - 0.0 [0.37281436 0.3073345 0.31985113] - 0.0 [0.37272096 0.30738777 0.3198912 ] - 0.0 [0.3726058 0.30745247 0.31994173] - 0.0 [0.37252814 0.30749673 0.31997514] - 0.0 [0.37248093 0.30752468 0.3199944 ] - 0.0 [0.37240618 0.3075688 0.320025 ] - 1.0
已尝试的方法
- 使用权重:仅减少了0类的预测占比,但训练无改善,预测仍为固定概率分布。
- 单独预测是否为0类:结果仍为类似的概率输出。
怀疑当前数据下这已是模型最准确的预测方式,但想询问是否有其他解决方案?
当前神经网络结构
model1 = Sequential() model1.add(LSTM(units=100, return_sequences=True, input_shape=(10, 2), activation="tanh")) model1.add(Dropout(0.2)) model1.add(LSTM(units=50, return_sequences=True, activation="tanh")) model1.add(Dropout(0.2)) model1.add(LSTM(units=50, return_sequences=False, activation="tanh")) model1.add(Dropout(0.2)) model1.add(Dense(32, activation="tanh")) model1.add(Dropout(0.2)) model1.add(Dense(3, activation='softmax')) model1.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=.000001), loss=['sparse_categorical_crossentropy'])
解决方案
1. 调整学习率
当前设置的1e-6学习率过低,模型参数更新幅度极小,几乎无法学习有效特征。建议先将学习率提升至1e-4或1e-3,观察损失变化;若训练不稳定,再逐步下调至合适值。
2. 简化模型结构
当前3层LSTM+2层Dense的结构过于复杂,易出现梯度消失或过拟合:
- 减少LSTM层数至1-2层,降低单元数量(比如从100→64→32)
- 降低Dropout比例或暂时移除部分Dropout层,避免模型无法捕捉有效特征
- 将
tanh激活函数替换为relu,缓解深层网络的梯度消失问题
3. 数据层面优化
补充特征工程
仅用原始曲线数据不足以区分极值点,可添加以下特征:
- 相邻点的一阶差分、二阶差分
- 当前点在滑动窗口内的相对极值状态(比如是否是窗口内的最大/最小值)
- 曲线的斜率、曲率计算值
核对标签准确性
检查savgol_filter的窗口大小是否合理,是否误过滤了真实极值,导致输入数据与标签不匹配。随机抽取样本人工核对,确保标签标注准确。
优化类别平衡
若数据集类别不平衡(比如0类占比过高),除类别权重外,还可尝试:
- 过采样少数类:复制1类、2类样本,提升其在训练集中的占比
- 欠采样多数类:随机删除部分0类样本
- 时序版SMOTE合成少数类样本,避免破坏时序特征
4. 调整训练策略
- 增加训练轮数,同时加入
EarlyStopping回调,防止过拟合 - 更换损失函数:尝试
categorical_crossentropy(需将标签转为one-hot编码),或用Focal Loss解决类别不平衡导致的模型偏向问题 - 更换优化器:尝试带动量的SGD,观察模型收敛情况
5. 模型诊断
- 查看中间层输出,确认LSTM是否提取到有效特征:若中间层输出趋近于0或1,说明存在梯度消失,需调整激活函数或模型结构
- 对比训练集与验证集的损失变化:若两者均不下降,说明模型无法学习;若验证集损失上升,说明过拟合
内容的提问来源于stack exchange,提问作者markb2575
相关产品推荐
相关产品推荐

