使用sigmoid+二元交叉熵训练的模型如何输出类别概率而非0/1值?
问题原因
你遇到的现象本质是两个层面的问题:
- API认知误区
TensorFlow 2.6及以上版本中,model.predict_proba()方法已经被正式废弃,它和model.predict()的功能完全一致,都是直接返回模型最后一层的输出值,并不会额外做0/1的二值化处理,你看到的[1.]本身就是sigmoid激活层的输出结果,不是分类后的标签。 - 模型输出置信度过高
因为二分类任务常见的类别不平衡、模型过拟合等问题,最终全连接层输出的logits(sigmoid的输入值)绝对值通常会非常大,经过sigmoid激活后数值会被挤压到非常接近0或者1的边界:比如sigmoid(8)≈0.9997,sigmoid(10)≈0.99995,在默认的浮点数打印精度下就会显示为1.或者0.,但本质上还是(0,1)区间内的浮点数,只是数值太接近边界。
你可以用以下代码验证数值的真实值:
pred = model.predict(c) # 打印16位精度的概率值,就能看到不是严格的1 print(f"原始概率值:{pred[0][0]:.16f}")
解决方法
- 直接用现有输出做阈值调整
你当前拿到的pred本身就是你需要的类别概率,不需要额外修改获取逻辑,阈值判断可以直接写为:
threshold = 0.99 y_classes = (pred > threshold).astype(int).ravel()
- 如果需要获得更分散的概率分布(降低模型置信度)
- 增加数据增强策略,针对CT图像做随机翻转、旋转、裁剪、对比度调整等操作,降低过拟合风险
- 在卷积层、全连接层前增加正则化项,比如L2正则、Dropout层
- 替换损失函数为Focal Loss,或者在训练时传入
class_weight参数平衡类别权重,缓解类别不平衡导致的模型过度置信问题
内容的提问来源于stack exchange,提问作者Kenan Morani
相关产品推荐
相关产品推荐

