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

TensorFlow二分类单层神经网络输出值不在预期[0,1]范围求助

二分类模型输出分数集中在低区间,无法覆盖[0,1]范围

我用TensorFlow训练一个二分类的简单神经网络,训练数据标签为0和1。训练过程看起来正常,准确率约80%,AUC约75%,但模型评估时输出的概率分数集中在[0.1, 0.35]区间,预期应该覆盖[0,1]范围。

以下是我的模型构建代码:

# initialize model
model = keras.models.Sequential()

# get input-dimension
arr = LoadTTree(self,file=self.TrainTreeDir,print=False)
self.InputDimension = len(arr[0][0])
  
# build the input layer
model.add(keras.Input(shape = (self.InputDimension), name = "inputlayer"))
# build the hidden layer
model.add(keras.layers.Dense(self.Nodes, name = "hiddenlayer", activation = self.ActivationFunction))
# build the output layer
model.add(keras.layers.Dense(self.OutputDimension, activation=self.OutputActivation, name="output_layer"))

# build KerasModel, compile and print model-summary 
self.KerasModel = model
self.KerasModel.compile(loss = Loss(self), optimizer = Optimizer(self), weighted_metrics = self.Metrics)
self.KerasModel.summary()

参数设置:

ActivationFunction = sigmoid, OutputActivation = sigmoid, Loss = binary_crossentropy, Optimizer = adam

训练代码:

hist = self.KerasModel.fit(self.data_train, self.labels_train, epochs=self.Epochs, batch_size=self.BatchSize, 
         verbose=self.Verbosity, sample_weight=self.weights_train, validation_data=(self.data_val,self.labels_val,self.weights_val))

其中Epochs = 50,我已经尝试调整损失函数和激活函数,但问题仍未解决。请问这是什么原因导致的?


可能的原因及解决方法

1. 训练数据标签分布严重不平衡

如果训练集中标签为1的样本占比极低,模型会倾向于输出低概率(偏向预测0),以此获得更高的整体准确率。

排查方法:
计算训练集标签的均值:

import numpy as np
print("训练集1类样本占比:", np.mean(self.labels_train))

如果占比远低于50%(比如低于10%),就说明存在数据不平衡问题。

解决方法:

  • 调整分类阈值:不要用0.5作为分界点,根据验证集的F1分数或召回率找到最优阈值;
  • 使用Focal Loss替代普通的binary crossentropy,降低易分类样本(0类)的权重,迫使模型关注少数类;
  • 对少数类进行过采样,或对多数类进行欠采样,平衡样本分布。

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

Sigmoid激活函数对输入数值范围非常敏感:如果输入特征的数值过大或过小,会导致隐藏层的输出落在Sigmoid的饱和区(两端),使得模型无法学习到有效的特征表示,最终输出层的概率也会集中在狭窄区间。

排查方法:
查看输入特征的统计信息:

print("特征均值:", np.mean(self.data_train, axis=0))
print("特征标准差:", np.std(self.data_train, axis=0))

如果特征之间数值差异极大(比如有的特征均值是1000,有的是0.01),就需要做归一化。

解决方法:
用StandardScaler或MinMaxScaler对输入特征做标准化/归一化,注意要只在训练集上拟合,再应用到验证集和测试集:

from sklearn.preprocessing import StandardScaler

scaler = StandardScaler()
self.data_train = scaler.fit_transform(self.data_train)
self.data_val = scaler.transform(self.data_val)

3. 隐藏层激活函数选择不当

隐藏层使用Sigmoid容易导致梯度消失:当输入数值较大时,Sigmoid的梯度趋近于0,模型参数更新缓慢,无法学到有效的特征映射,最终输出概率无法覆盖全范围。

解决方法:
将隐藏层的激活函数替换为ReLU(或LeakyReLU),避免梯度消失问题:

ActivationFunction = 'relu'  # 替换原来的sigmoid

4. 样本权重设置不合理

如果给标签为0的样本设置了过高的权重,模型会优先保证0类的预测正确,从而倾向于输出低概率值。

排查方法:
检查样本权重的分布:

# 查看0类和1类样本的平均权重
class_0_weights = self.weights_train[self.labels_train == 0]
class_1_weights = self.weights_train[self.labels_train == 1]
print("0类样本平均权重:", np.mean(class_0_weights))
print("1类样本平均权重:", np.mean(class_1_weights))

如果0类的平均权重远高于1类,就会导致模型偏向输出低概率。

解决方法:
调整样本权重,使两类的权重相对均衡,或者根据样本频率设置权重(比如1类权重=总样本数/(2*1类样本数),0类同理)。

5. 训练轮次不足

虽然设置了50个epochs,但模型可能还没有完全收敛,参数还在优化过程中,导致输出概率尚未覆盖全范围。

排查方法:
绘制训练和验证的loss曲线,观察是否还在下降:

import matplotlib.pyplot as plt

plt.plot(hist.history['loss'], label='训练loss')
plt.plot(hist.history['val_loss'], label='验证loss')
plt.legend()
plt.show()

如果loss曲线还在持续下降,说明模型还可以继续训练。

解决方法:
增加epochs数量(比如调到100或200),或者添加EarlyStopping回调,让模型在验证集loss不再下降时自动停止:

from keras.callbacks import EarlyStopping

early_stop = EarlyStopping(monitor='val_loss', patience=10, restore_best_weights=True)
hist = self.KerasModel.fit(..., callbacks=[early_stop])

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.28 00:47:38