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

不同TensorFlow/Keras版本下ResNet模型训练不收敛问题咨询

相同ResNet代码在TF2.0.8收敛、TF2.1.4不收敛的可能原因及排查方案

以下是针对该问题的具体分析:

可能的核心原因

  • 随机种子未固定:TF2.0与TF2.1默认随机实现存在差异,若未固定全局随机种子,模型初始化权重、数据shuffle的随机性可能导致新版本中初始状态极差,无法收敛。
  • Adam优化器实现细节变更:两个版本中tf.keras.optimizers.Adam的梯度计算、数值稳定性逻辑有细微调整,即使参数一致,也可能影响训练动态;若未显式指定beta_1、beta_2、epsilon等参数,新版本的默认值(或计算方式)可能与旧版本不符。
  • ResNet50V2初始化逻辑变化:当weights=None时,TF2.1可能调整了卷积层、BatchNorm层的默认初始化器(如核初始化、gamma/beta初始化),导致模型初始梯度分布异常。
  • 自定义损失函数兼容性问题:Custom_EUL_Loss中的某些操作(如除法、对数、自定义梯度)在TF2.1的自动求导机制下可能出现数值不稳定(如NaN、梯度消失),或损失计算结果与旧版本存在差异。
  • BatchNorm层行为调整:TF2.1对BatchNorm的滑动平均更新、训练/推理模式切换逻辑做了优化,若拼接模型未正确传递训练模式信号,可能导致特征提取器的BatchNorm在训练时未正常更新统计量。

排查步骤

  1. 固定全局随机种子
    在代码开头添加:

    import tensorflow as tf
    import numpy as np
    import random
    
    tf.random.set_seed(42)
    np.random.seed(42)
    random.seed(42)
    

    重新训练,确认是否是随机性导致的差异。

  2. 验证自定义损失函数

    • 在两个版本中,输入相同的train_x、train_y样本,打印损失值,确认结果一致。
    • 在TF2.1中用tf.GradientTape计算损失对模型参数的梯度,检查是否存在NaN或无穷大值:
      with tf.GradientTape() as tape:
          pred = trainer_model(train_x[:10])
          loss_val = au.Custom_EUL_Loss()(train_y[:10], pred)
      grads = tape.gradient(loss_val, trainer_model.trainable_variables)
      for g in grads:
          if tf.math.is_nan(g).any() or tf.math.is_inf(g).any():
              print("梯度存在异常值")
      
  3. 显式指定优化器参数
    替换优化器定义为:

    opt = tf.keras.optimizers.Adam(lr=1e-4, beta_1=0.9, beta_2=0.999, epsilon=1e-8)
    

    确保与TF2.0.8的Adam默认参数完全一致,再尝试训练。

  4. 检查模型初始化差异
    打印两个版本中ResNet50V2第一层卷积的权重统计值:

    first_conv = extractor_feature_model.layers[1]  # 根据模型结构调整索引
    print("权重均值:", tf.reduce_mean(first_conv.kernel).numpy())
    print("权重方差:", tf.math.reduce_variance(first_conv.kernel).numpy())
    

    若差异明显,手动指定初始化器:

    extractor_feature_model = tf.keras.applications.ResNet50V2(
        include_top=False,
        weights=None,
        input_shape=am.input_shape,
        pooling="avg",
        kernel_initializer='he_normal'
    )
    
  5. 验证BatchNorm行为
    训练过程中打印特征提取器第一个BatchNorm层的滑动均值:

    bn_layer = extractor_feature_model.layers[2]  # 根据结构调整索引
    print("训练前滑动均值:", bn_layer.moving_mean.numpy())
    trainer_model.fit(train_x[:100], train_y[:100], epochs=1)
    print("训练后滑动均值:", bn_layer.moving_mean.numpy())
    

    若滑动均值未更新,检查concat_model是否正确设置了模型的训练模式(如未禁用训练时的BatchNorm更新)。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 10:19:55