使用Sklearn中SVM与MLP分类器时少数类Precision等指标为0的问题求助
问题原因分析
出现这个问题的核心原因是:模型完全没有预测出少数类样本。在测试集中存在少数类的真实标签,但模型的预测结果里没有任何少数类的输出,导致少数类的Precision(TP/(TP+FP))、F1-score等指标因分母为0而无法计算,scikit-learn会自动将这些指标设为0并抛出警告。
这种情况通常发生在数据集严重不平衡的场景下,模型默认会偏向于多数类,忽略少数类的学习。
解决方案
1. 数据层面调整
类别权重平衡
直接给少数类样本赋予更高的权重,让模型在训练时更重视少数类的错误:
- SVM分类器:添加
class_weight='balanced'参数,该参数会根据类别的样本数量自动调整权重(与类频率成反比):SVM_classifier = svm.SVC(kernel="rbf", probability=True, random_state=1, class_weight='balanced') - MLP分类器:MLP没有直接的
class_weight参数,但可以通过sample_weight传递样本权重:from sklearn.utils.class_weight import compute_sample_weight # 计算平衡的样本权重 sample_weights = compute_sample_weight('balanced', y_train) # 训练时传入权重 MLP.fit(X_train, y_train, sample_weight=sample_weights)
训练集重采样
通过过采样少数类或欠采样多数类,平衡训练集的类别分布(注意:重采样只能在训练集上进行,避免数据泄露):
- 过采样少数类(推荐):使用SMOTE算法生成少数类的合成样本:
from imblearn.over_sampling import SMOTE sm = SMOTE(random_state=1) X_train_resampled, y_train_resampled = sm.fit_resample(X_train, y_train) # 用重采样后的数据集训练模型 SVM_classifier.fit(X_train_resampled, y_train_resampled) - 欠采样多数类:随机删除多数类样本,但可能丢失有效信息,仅适用于数据量极大的场景。
2. 模型参数调整
SVM参数优化
- 增大
C参数:C是正则化强度的倒数,增大C会让模型更关注分类错误,对少数类的敏感度更高(需结合交叉验证调参):SVM_classifier = svm.SVC(kernel="rbf", probability=True, random_state=1, class_weight='balanced', C=10) - 尝试不同核函数:如果数据是线性可分的,改用
kernel='linear'可能提升少数类的识别能力。
MLP参数优化
- 降低学习率:你当前设置的
learning_rate_init=0.3过高,容易导致模型训练不稳定,无法收敛到能识别少数类的最优解,建议调整为0.001或0.01:MLP = MLPClassifier(random_state=1, learning_rate="constant", learning_rate_init=0.001, momentum=0.2, max_iter=1000) - 增加训练迭代次数:默认
max_iter=200可能不足以让模型学习到少数类特征,可设置为1000或更高。 - 调整网络结构:增加隐藏层单元数或层数,提升模型的拟合能力,例如
hidden_layer_sizes=(128, 64)。
3. 评估指标优化
- 改用适合不平衡数据的指标:不要仅依赖分类报告的Precision/Recall/F1,可使用:
- AUC-PR(精确率-召回率曲线下面积):比AUC-ROC更适合不平衡数据:
from sklearn.metrics import precision_recall_curve, auc y_score = SVM_classifier.predict_proba(X_test)[:, 1] precision, recall, _ = precision_recall_curve(y_test, y_score) print(f"AUC-PR: {auc(recall, precision):.4f}") - F-beta分数:通过调整
beta值优先关注召回率(beta>1),更贴合少数类的识别需求:from sklearn.metrics import fbeta_score print(f"F-beta分数(beta=2): {fbeta_score(y_test, SVM_y_pred, beta=2):.4f}")
- AUC-PR(精确率-召回率曲线下面积):比AUC-ROC更适合不平衡数据:
- 抑制警告(仅用于临时处理):如果确认不需要修复预测问题,可添加
zero_division=1参数将未定义指标设为1,但这不会解决模型本身的性能问题:print(classification_report(y_test, SVM_y_pred, zero_division=1))
内容的提问来源于stack exchange,提问作者Encipher
相关产品推荐
相关产品推荐

