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

为何相同结构的纯TensorFlow自编码器不收敛而Keras版拟合良好

问题核心原因

你纯TensorFlow实现的两处错误导致损失无法下降:

  1. 损失函数参数与输入不匹配
    你给BinaryCrossentropy设置了from_logits=True,这个参数的含义是传入损失的预测值是未经过sigmoid激活的原始logits,损失函数内部会自动完成sigmoid变换。但你的代码中传入损失的decoded是已经经过tf.nn.sigmoid激活的输出,相当于做了两次sigmoid变换,数值被过度压缩到接近0/1的区间,梯度几乎消失,所以损失一直卡在0.64附近。
  2. 损失函数参数顺序颠倒
    tf.keras.losses.BinaryCrossentropy的调用顺序是损失(真实标签, 预测值),你的代码写成了bin_cross(decoded, Y_pack),把预测值和真实标签的顺序搞反了,直接导致损失计算完全错误。

修复方案

你可以选择以下任意一种方案调整,同时修正参数顺序即可:

方案1:匹配激活与损失参数

保持输出层加sigmoid的逻辑,把损失函数的from_logits改为False:

# 把原来的损失定义替换为下面的代码
bin_cross = tf.keras.losses.BinaryCrossentropy(from_logits=False)

# 同时修正trainstep里的损失调用顺序
loss = bin_cross(Y_pack, decoded)

方案2(更推荐,数值稳定性更好)

保持from_logits=True的设置,去掉decoder输出的sigmoid激活,直接传原始logits给损失函数:

@tf.function
def trainstep(X_pack, Y_pack):
    with tf.GradientTape() as tape:
        tape.watch([encoder_W, encoder_b, decoder_W, decoder_b])
        encoded = tf.nn.sigmoid(tf.matmul(X_pack, encoder_W) + encoder_b)
        # 移除sigmoid,直接输出线性层结果作为logits
        decoded_logits = tf.matmul(encoded, decoder_W) + decoder_b
        # 修正参数顺序
        loss = bin_cross(Y_pack, decoded_logits)
    gradients = tape.gradient(loss, [encoder_W, encoder_b, decoder_W, decoder_b])
    optimizer.apply_gradients(zip(gradients, [encoder_W, encoder_b, decoder_W, decoder_b]))

另外补充说明:你原来的Keras代码也存在参数不匹配的问题——输出层设置了sigmoid激活,但损失函数用了from_logits=True,只是Keras内部做了兼容处理才没有出现异常,建议也同步调整保持逻辑一致。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.03 12:27:03