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

输出层加激活函数后训练停滞,如何修复国际象棋评估模型?

问题描述

我正在开发一款国际象棋引擎,用于评估棋局并输出胜(1)/平(0.5)/负(0)的概率值。使用TensorFlow框架,基于20万条均衡分布的自制棋盘状态数据训练,输入维度为70(64格棋盘信息+6项额外全局信息)。

遇到的问题:为输出层添加0-1范围的激活函数(如sigmoid或tf.clip_by_value)后,训练首轮结束后损失值就不再变化;移除该激活函数后,训练过程的损失能正常逐步下降。希望找到修复方法,让带激活函数的模型也能正常训练并获得更好的效果。

相关代码

数据加载部分

inp, out = loadData("pathname", 200000)
X_train, X_val, Y_train, Y_val = train_test_split(inp, out, test_size=0.1, random_state=42)

带激活函数的模型架构

model = tf.keras.Sequential([
    tf.keras.layers.Input(shape=(70,), dtype=tf.int8),
    tf.keras.layers.Dense(1000, 'relu'),
    tf.keras.layers.Dense(700, 'relu'),
    tf.keras.layers.Dense(500, 'relu'),
    tf.keras.layers.Dense(1, 'sigmoid'),
])

model.compile('adam', 'mae', ['mae'])

model.fit(x=X_train, y=Y_train, validation_data=[X_val, Y_val], epochs=20, batch_size=64, callbacks=tensorboard_callback)

训练输出对比

  • 带激活函数(损失停滞):

Epoch 1/20
4079/4079 [==============================] - 19s 4ms/step - loss: 0.4856 - mae: 0.4856 - val_loss: 0.4865 - val_mae: 0.4865
...(后续轮次损失无任何变化)

  • 移除激活函数(损失正常下降):

Epoch 1/20
4079/4079 [==============================] - 18s 4ms/step - loss: 0.3748 - mae: 0.3748 - val_loss: 0.2684 - val_mae: 0.2684
...(后续轮次损失逐步下降)

问题分析与修复方案

核心原因

  1. 损失函数与激活函数不匹配:MAE(平均绝对误差)的梯度是固定值,而sigmoid函数在输出接近0或1时梯度会趋近于0,两者结合容易导致梯度消失,模型无法更新。
  2. 输入数据未归一化:输入使用int8类型,数值范围未做归一化处理,会导致前层ReLU激活容易饱和,最终sigmoid输出集中在0.5附近,梯度无法推动参数更新。
  3. 模型规模过大:1000+700+500的神经元数量过多,容易引发梯度消失或过拟合,导致模型快速收敛到局部最优。

具体修复步骤

  • 更换损失函数:将MAE替换为MSE(均方误差)或Huber损失。MSE的梯度与误差值成正比,能在sigmoid输出偏离目标时提供更大的梯度,推动模型更新:
    model.compile('adam', 'mse', ['mse'])
    
  • 输入数据归一化:将int8类型的输入转换为float32并归一化到0-1范围,避免前层激活饱和:
    X_train = tf.cast(X_train, tf.float32) / 127.5  # 若int8范围为-128到127,归一化到-1到1也可
    X_val = tf.cast(X_val, tf.float32) / 127.5
    
  • 调整模型初始化策略:为全连接层指定适合sigmoid的初始化方式(如Xavier初始化),避免初始输出过度集中在0或1:
    tf.keras.layers.Dense(1000, 'relu', kernel_initializer='glorot_uniform'),
    # 后续全连接层同理
    
  • 缩小模型规模:减少神经元数量或层数,降低梯度消失风险,比如调整为:
    model = tf.keras.Sequential([
        tf.keras.layers.Input(shape=(70,), dtype=tf.float32),
        tf.keras.layers.Dense(512, 'relu', kernel_initializer='glorot_uniform'),
        tf.keras.layers.Dense(256, 'relu', kernel_initializer='glorot_uniform'),
        tf.keras.layers.Dense(128, 'relu', kernel_initializer='glorot_uniform'),
        tf.keras.layers.Dense(1, 'sigmoid'),
    ])
    
  • 调整学习率:适当调大Adam的学习率(比如从0.001改为0.005),或加入学习率调度器,帮助模型跳出局部最优:
    lr_scheduler = tf.keras.optimizers.schedules.ExponentialDecay(
        initial_learning_rate=0.005,
        decay_steps=10000,
        decay_rate=0.9
    )
    model.compile(optimizer=tf.keras.optimizers.Adam(learning_rate=lr_scheduler), loss='mse', metrics=['mse'])
    

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.23 00:47:49