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

手动实现Keras二元交叉熵损失与官方实现结果不一致问题求解

问题原因排查及修复方案

核心错误1:输入语义与参数设置不匹配

你调用官方tf.keras.losses.BinaryCrossentropy时设置了from_logits=True,代表传入损失的是未经过sigmoid激活的原始logits输出,值域为(-∞, +∞);而你自定义的损失函数默认输入为0~1之间的概率值,直接对输入做K.clip、取对数的操作,完全不适用于logits输入:

  • 所有小于K.epsilon()的负logits会被强行截断为极小的概率值,所有大于1的正logits会被截断为接近1的概率值,原始输出语义被完全扭曲,损失计算自然和官方结果差异极大。

核心错误2:判别器损失逻辑完全错位

原始官方判别器损失的计算逻辑是分别计算两部分损失再求和:

  1. 真实样本输入判别器的输出与全1标签计算BCE(要求判别器把真样本判为真)
  2. 生成样本输入判别器的输出与全0标签计算BCE(要求判别器把假样本判为假)
    而你写的new_d_loss错误地将real_output作为标签、generated_output作为预测值,完全没有对应上述两部分损失的计算逻辑,结构本身就是错的。

核心错误3:生成器损失训练方向反转

原始官方生成器损失的逻辑是:生成样本输入判别器的输出与全1标签计算BCE,要求判别器把假样本判为真,对应公式为-log(y_pred);而你写的new_g_loss计算的是-log(1 - y_pred),刚好和目标相反,会引导生成器生成更容易被判别器识别的假样本,训练完全走偏。


修复后的自定义损失代码(与官方from_logits=True逻辑完全对齐)

import tensorflow.keras.backend as K

def custom_bce_from_logits(y_true, y_pred_logits):
    # 先将logits通过sigmoid转为概率值,和官方from_logits=True逻辑对齐
    y_pred = K.sigmoid(y_pred_logits)
    y_pred = K.clip(y_pred, K.epsilon(), 1 - K.epsilon())
    term_0 = (1 - y_true) * K.log(1 - y_pred)
    term_1 = y_true * K.log(y_pred)
    return -K.mean(term_0 + term_1)

def new_d_loss(real_output, generated_output):
    # 分别计算真实样本、生成样本的损失再求和,和官方逻辑对齐
    real_loss = custom_bce_from_logits(tf.ones_like(real_output), real_output)
    fake_loss = custom_bce_from_logits(tf.zeros_like(generated_output), generated_output)
    return real_loss + fake_loss

def new_g_loss(generated_output):
    # 生成样本要求判别器判为真,标签为全1
    return custom_bce_from_logits(tf.ones_like(generated_output), generated_output)

验证方法

你可以用随机生成的模拟logits输入,分别调用官方损失和自定义损失计算结果,两者数值误差在1e-6以内即为对齐成功。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.24 03:45:11