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

带加权损失的TensorFlow二分类器:训练准确率与历史记录不符

神经网络训练疑问解答

训练代码

model = tf.keras.Sequential([
    tf.keras.layers.InputLayer(input_shape=(input_length,)),
    tf.keras.layers.Dropout(0.8, seed=42),
    tf.keras.layers.Dense(units=200, activation='relu'),
    tf.keras.layers.Dropout(0.65, seed=42),
    tf.keras.layers.Dense(units=400, activation='relu'),
    tf.keras.layers.Dropout(0.65, seed=42),
    tf.keras.layers.Dense(units=300, activation='relu'),
    tf.keras.layers.Dropout(0.65, seed=42),
    tf.keras.layers.Dense(units=200, activation='relu'),
    #tf.keras.layers.Dense(units=2, activation='softmax')
    tf.keras.layers.Dense(units=1, activation='sigmoid')
])

#create weights for classes
weights = sklearn.utils.class_weight.compute_class_weight(class_weight='balanced',classes=np.unique(y_train),y=[x[0] for x in y_train])
my_weight={0:weights[0],1:weights[1]}

model.compile(optimizer='adam',
              #loss=tf.keras.losses.SparseCategoricalCrossentropy(from_logits=False),
              loss='binary_crossentropy',
              metrics=['accuracy'])

early_stop=tf.keras.callbacks.EarlyStopping(
    monitor='val_loss',
    patience=100,
    restore_best_weights=True
)

model_checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(
    filepath='./../../../data/models/',
    monitor='val_accuracy',
    mode='max',
    save_best_only=True
)

callbacks=[
    early_stop, 
    #model_checkpoint_callback
]

history=model.fit(x_train, y_train, 
                  batch_size= 16, 
                  epochs=500,
                  validation_data=(x_val,y_val),
                  callbacks=callbacks, 
                  class_weight=my_weight
                )

训练曲线

损失曲线

损失曲线

准确率曲线

准确率曲线

绘图代码

def plot_acc(history,eval_ret):
    plt.plot(history.history['accuracy'],label='train_acc', color='red')
    plt.plot(history.history['val_accuracy'],label='val_acc',color='blue')
    plt.axhline(eval_ret[1],label='test_acc',color='green')
    plt.title('Accuracy of the model over training epochs')
    plt.ylabel('Accuracy')
    plt.xlabel('Training epochs')
    plt.legend()
    plt.show()
    
def plot_loss(history,eval_ret):
    plt.plot(history.history['loss'],label='train_loss', color='red')
    plt.plot(history.history['val_loss'],label='val_loss',color='blue')
    plt.axhline(eval_ret[0],label='test_loss',color='green')
    plt.title('Loss of the model over training epochs')
    plt.ylabel('Loss')
    plt.xlabel('Training epochs')
    plt.legend()
    plt.show()

eval_ret=model.evaluate(x_test, y_test)
plot_loss(history,eval_ret)
plot_acc(history,eval_ret)

评估代码与结果

评估代码

print('train:',model.evaluate(x_train, y_train,verbose=None))
print('test:',model.evaluate(x_test, y_test,verbose=None))
print('validate:',model.evaluate(x_val, y_val,verbose=None))

评估结果

评估结果

疑问解答

1. 为何训练集的损失和准确率反而比测试/验证集更差?

有两个核心原因:

  • Dropout的开关差异:训练过程中Dropout层会随机丢弃部分神经元,刻意降低模型拟合能力防止过拟合;而model.evaluate()(验证、测试、最终训练集评估)时,Dropout层自动关闭,模型使用全部神经元计算,性能更强,因此准确率更高、损失更低。
  • 类权重的影响:训练时使用了class_weight=my_weight(平衡类别权重),计算的损失是加权后的值,会比不使用权重的验证/测试损失更高;评估阶段默认不应用类权重,损失是原始未加权值,进一步拉大了差距。

2. 最终模型的实测训练准确率为96%,但训练历史记录中的训练准确率始终低于60%,这是为什么?

  • 训练历史history.history['accuracy']记录的是每轮训练时启用Dropout状态下的准确率,此时模型因Dropout丢弃神经元,预测能力被限制,所以准确率较低。
  • 最终model.evaluate(x_train)是在关闭Dropout的状态下评估训练集,模型用全部神经元运行,加上EarlyStopping的restore_best_weights=True恢复了验证集表现最优的权重,因此能在训练集上达到远高于训练过程的准确率。

内容的提问来源于stack exchange,提问作者mat.tho

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 09:15:26