多分类任务中训练损失下降但测试损失上升,求优化建议
问题诊断与优化方案
这是典型的过拟合问题——模型在训练集上过度学习了数据里的噪声和细节,完全适配了训练数据,但没法泛化到从未见过的测试数据上。结合你的代码和曲线表现,给出以下针对性优化方案:
一、添加正则化与早停机制
1. 加入Dropout层
在全连接层之间插入Dropout层,随机丢弃部分神经元的输出,避免神经元之间过度依赖:
def buildModel(optimizer): model = tf.keras.models.Sequential([ Dense(100, activation='relu'), tf.keras.layers.Dropout(0.2), # 丢弃20%的神经元 Dense(82, activation='relu'), tf.keras.layers.Dropout(0.2), Dense(20, activation='relu'), tf.keras.layers.Dropout(0.1), Dense(20, activation='softmax') # 去掉冗余的6维压缩层 ]) model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) return model
2. L2正则化
给全连接层的权重添加L2正则化,限制权重的大小,防止模型过度拟合:
from tensorflow.keras import regularizers def buildModel(optimizer): model = tf.keras.models.Sequential([ Dense(100, activation='relu', kernel_regularizer=regularizers.l2(0.001)), Dense(82, activation='relu', kernel_regularizer=regularizers.l2(0.001)), Dense(20, activation='relu', kernel_regularizer=regularizers.l2(0.0005)), Dense(20, activation='softmax') ]) model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) return model
3. 早停(Early Stopping)
监控验证集损失,当验证损失连续多轮不再下降时,停止训练并恢复最优权重,避免无意义的训练加剧过拟合:
# 定义早停回调 early_stop = tf.keras.callbacks.EarlyStopping( monitor='val_loss', patience=5, # 连续5轮val_loss不下降就停止 restore_best_weights=True # 恢复到val_loss最低时的权重 ) # 训练时加入回调 history = model.fit( train_x,train_y_lst, validation_data=(test_x, test_y_lst), epochs=50, batch_size=32, verbose=0, callbacks=[early_stop] )
二、简化模型结构
你的模型存在冗余层(比如从20维压缩到6维再回到20维),增加了模型复杂度,反而容易过拟合。可以简化结构:
def buildModel(optimizer): model = tf.keras.models.Sequential([ Dense(64, activation='relu'), # 减少神经元数量 Dense(32, activation='relu'), Dense(20, activation='softmax') ]) model.compile(loss='categorical_crossentropy', optimizer=optimizer, metrics=['accuracy']) return model
三、数据层面优化
- 处理类别不平衡:从你的标签样例看,前几类样本占比很高,后面类别几乎为0,这会导致模型偏向多数类,测试集准确率差。可以给少数类设置更高的权重:
# 假设你有类别权重字典,比如给少数类更高权重 class_weights = {i: 1 for i in range(20)} class_weights[17] = 10 # 示例:给第18类(索引17)设置10倍权重 class_weights[18] = 10 class_weights[19] = 10 history = model.fit( train_x,train_y_lst, validation_data=(test_x, test_y_lst), epochs=50, batch_size=32, verbose=0, class_weight=class_weights, callbacks=[early_stop] )
- 确认标准化逻辑:确保测试集的标准化是用训练集的均值和标准差计算的,不能单独对测试集做标准化,否则会引入数据泄漏。
四、调整训练参数
- 优化器配置:你代码里定义了
tf.keras.optimizers.legacy.Adam()但没用到,应该传入实例并调整学习率(默认0.001可能偏大):
optimizer = tf.keras.optimizers.legacy.Adam(learning_rate=0.0001) model = buildModel(optimizer)
- 调整Batch Size:尝试增大batch size(比如64、128),让梯度更新更稳定,减少模型对训练集噪声的敏感度。
内容的提问来源于stack exchange,提问作者Whitedevil4648
相关产品推荐
相关产品推荐

