You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

使用Keras进行二分类时测试损失与精度无提升,求优化方案

针对二分类模型优化的建议

从你提供的训练/测试损失、精度曲线,再结合数据集1:30的类别不平衡问题来看,目前模型的核心问题应该是过拟合+类别不平衡导致的无效高准确率——训练集表现持续提升,但测试集停滞不前,再加上极端的类别比例,模型大概率一直在“偷懒”预测多数类,看起来准确率不错,但完全没学到少数类的特征。下面给你梳理几个优化方向:

一、先解决类别不平衡问题

这是最核心的前提,因为不平衡的数据集会让模型偏向多数类,所有后续优化都要围绕这个展开:

  • 数据重采样
    • 对少数类做过采样:推荐用SMOTE算法(生成合成的少数类样本,而非简单复制),避免过拟合;
    • 对多数类做欠采样:随机剔除部分多数类样本,但要注意保留关键特征,别丢了重要信息;
    • 也可以试试混合采样,结合两者的优势。
  • 设置类别权重
    在训练时给少数类分配更高的权重,让模型更重视少数类的错误。Keras里可以用class_weight参数实现,比如用sklearn计算权重:
    from sklearn.utils.class_weight import compute_class_weight
    class_weights = compute_class_weight('balanced', classes=np.unique(y_train), y=y_train)
    class_weight_dict = dict(zip(np.unique(y_train), class_weights))
    # 然后在fit时传入
    model.fit(X_train, y_train, class_weight=class_weight_dict, ...)
    
  • 更换评估指标
    别再只看准确率(acc)了!它在不平衡数据集里完全是误导性指标——模型全预测多数类就能拿到97%左右的acc,但根本没用。换成这些更靠谱的指标:
    model.compile(loss='binary_crossentropy', optimizer='adam',
                  metrics=['AUC', tf.keras.metrics.Precision(), tf.keras.metrics.Recall()])
    
    重点监控AUC-ROC和召回率(Recall),这两个能真实反映模型对少数类的识别能力。

二、优化模型结构与训练,解决过拟合

从曲线看,训练集和测试集的表现差距明显,说明模型过拟合了,咱们可以这么调整:

  • 调整模型复杂度与输出层
    你当前的模型只有一层10神经元的隐藏层,对于65个特征来说可能偏简单,但也可能是正则化不够。另外,二分类任务用sigmoid输出单个神经元比softmax输出2个神经元更简洁标准,试试这个结构:
    from tensorflow.keras import Sequential
    from tensorflow.keras.layers import Dense, Dropout
    from tensorflow.keras.regularizers import l2
    
    model = Sequential()
    model.add(Dense(64, activation='relu', input_dim=n_features, kernel_regularizer=l2(0.01)))
    model.add(Dropout(0.5))
    model.add(Dense(32, activation='relu', kernel_regularizer=l2(0.01)))
    model.add(Dropout(0.5))
    model.add(Dense(1, activation='sigmoid'))  # 二分类用sigmoid更合适
    
  • 增强正则化
    除了Dropout,加入L2正则化限制权重大小,避免模型过度拟合训练集的噪声;也可以试试L1正则化,或者两者结合。
  • 加入早停机制
    当验证集的性能不再提升时,自动停止训练,防止模型过拟合。用Keras的EarlyStopping回调:
    from tensorflow.keras.callbacks import EarlyStopping
    
    early_stopping = EarlyStopping(monitor='val_AUC', patience=10, restore_best_weights=True)
    # fit时加入callbacks参数
    model.fit(..., callbacks=[early_stopping])
    
  • 调整学习率
    Adam默认的0.001学习率可能有点高,试试降到0.0001,让模型学习更平缓,更容易找到全局最优解。

三、数据预处理优化

  • 特征标准化/归一化
    神经网络对特征尺度非常敏感,把所有特征缩放到同一范围(比如用StandardScaler标准化为均值0方差1),能帮助模型更快收敛,也能减少过拟合的概率。
  • 特征选择/降维
    65个特征里可能有冗余或无关特征,试试用PCA降维、互信息法或者方差选择法,去掉不重要的特征,降低模型的学习难度,缓解过拟合。

四、尝试特殊损失函数

比如Focal Loss,它能降低易分类样本(多数类)的权重,让模型更专注于难分类的少数类样本。你可以在Keras里自定义这个损失函数:

import tensorflow as tf

def focal_loss(y_true, y_pred, alpha=0.25, gamma=2):
    y_true = tf.cast(y_true, tf.float32)
    y_pred = tf.clip_by_value(y_pred, 1e-7, 1 - 1e-7)
    cross_entropy = -y_true * tf.math.log(y_pred) - (1 - y_true) * tf.math.log(1 - y_pred)
    weight = alpha * y_true * tf.math.pow(1 - y_pred, gamma) + (1 - alpha) * (1 - y_true) * tf.math.pow(y_pred, gamma)
    loss = weight * cross_entropy
    return tf.reduce_mean(loss)

# 编译时用这个损失
model.compile(loss=focal_loss, optimizer='adam', metrics=['AUC'])

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

火山引擎 最新活动