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

Keras概率分布预测模型异常求助:输出趋近0/1且损失值不变

问题排查与解决方案

咱们先梳理下你遇到的核心问题:模型输出要么是0要么接近1,完全不符合「0-1且总和为1」的概率分布要求,同时训练时loss和验证loss全程没变化。下面一步步拆解问题根源,给出对应的修复方案:

1. 最后一层激活函数用错了

你当前最后一层用的是sigmoid,这个激活函数只会让每个神经元独立输出0-1的值,但不会强制所有输出的总和为1——这恰恰是概率分布的核心要求。对于概率分布预测任务,正确的激活函数应该是softmax,它会自动把输出向量归一化,确保所有元素加起来等于1,每个元素对应类别的概率。

2. 损失函数不匹配任务场景

你用了mae(平均绝对误差)来优化概率分布拟合,这不是最佳选择。MAE更适合普通回归任务,而对于概率分布的拟合,我们需要用专门衡量分布差异的损失:

  • 如果你的目标输出Y是概率分布向量(比如示例里的(0.25, 0, 0, 0.0833, 0.5833, 0.0833)),推荐使用kl_divergence(KL散度),它能精准衡量预测分布和真实分布之间的差异;
  • 如果Y是one-hot编码的类别标签,那用categorical_crossentropy更合适,但从你的示例来看显然是前者。

3. 输入特征未做归一化/标准化

看你的输入示例,数值范围差异极大:有1444997、154536这种超大数,也有4.26E-04这种极小值。这种情况下,模型的梯度更新会非常不稳定,很容易陷入局部最优或者梯度消失,直接导致loss停滞不动。

你必须对输入特征X做标准化处理,比如用StandardScaler把每个特征缩放到均值为0、方差为1的范围,或者用MinMaxScaler缩放到0-1区间。

4. 模型结构的小优化点

  • 你在最后一层softmax之前用了relu激活的Dense层,relu可能导致神经元饱和,建议把倒数第二层的激活换成LeakyReLU(你已经导入了但没用到),避免梯度消失;
  • 旧版本Keras的init='normal'写法已经过时,现在应该用kernel_initializer='normal',虽然这不是核心问题,但规范写法更利于维护。

修复后的完整代码

下面是整合了所有修复点的代码:

from keras.models import Sequential
from keras.layers import Dense
from keras.layers.advanced_activations import LeakyReLU
from sklearn.preprocessing import StandardScaler
import numpy as np

# 加载数据
X = np.loadtxt("compiledFeatures.csv", delimiter=",")
Y = np.loadtxt("naive_compiledDate.csv", delimiter=",")

# 对输入特征做标准化处理
scaler = StandardScaler()
X_scaled = scaler.fit_transform(X)

# 创建模型
model = Sequential()
model.add(Dense(20, input_dim=28, kernel_initializer='normal', activation='relu'))
model.add(Dense(15, kernel_initializer='normal', activation='relu'))
# 倒数第二层用LeakyReLU避免神经元饱和
model.add(Dense(6, kernel_initializer='normal'))
model.add(LeakyReLU())
# 最后一层用softmax输出符合要求的概率分布
model.add(Dense(6, kernel_initializer='normal', activation='softmax'))

# 编译模型:用KL散度衡量分布差异
model.compile(optimizer="adam", loss='kl_divergence')

# 用标准化后的输入训练模型
model.fit(X_scaled, Y, epochs=1000, verbose=2, validation_split=0.15, batch_size=32)

# 生成预测并验证总和
predictions = model.predict(X_scaled)
print("预测结果总和示例:", predictions[0].sum())  # 应该接近1

额外小建议

  • 可以加入EarlyStopping回调函数,当验证loss连续多轮不下降时自动停止训练,避免无效的epochs(比如2000轮可能太多了);
  • 可以尝试调整模型的神经元数量,比如试试32/16/8的结构,看看效果有没有提升;
  • 训练时指定batch_size(比如batch_size=32),能让梯度更新更稳定。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.29 07:14:40