Sklearn模型校准曲线绘制问题求助:曲线异常、缺失及报错排查
机器学习模型校准曲线异常问题排查
问题概述
绘制Logistic Regression、Random Forest、Decision Tree等5个模型的校准曲线时,出现三类异常:
- Logistic Regression曲线未显示
- Decision Tree曲线完全贴合理想校准虚线,不符合模型特性
- 代码运行时抛出
invalid value encountered in true_divide警告,但仍生成图表
异常原因分析
1. Logistic Regression曲线未显示
scikit-plot的plot_calibration_curve函数要求传入单类别的一维概率数组,但原代码直接传入了predict_proba返回的二维数组(形状为[n_samples, 2],包含两类样本的概率)。函数无法正确解析二维输入,导致曲线无法渲染。
2. Decision Tree曲线完全贴合理想线
决策树的predict_proba特性决定:每个叶子节点对应单一类别,输出概率只能是0或1(样本被分到正类叶子节点则概率为1,反之为0)。这种硬分类的概率输出,会让每个分箱内的真实正例比例与预测概率完全一致,因此曲线完全重合于理想校准线。
3. invalid value encountered in true_divide警告
绘制校准曲线时,若某个分箱区间内无样本,或该区间内真实正例数为0,计算真实正例比例时会触发除以0的数值计算警告。
代码修复方案
核心修正点
- 提取正类概率:所有模型的概率输出取第二列(
[:, 1]),转为一维数组传入绘图函数 - 校准决策树:使用
CalibratedClassifierCV对决策树进行概率校准,生成更合理的概率输出 - 优化分箱策略:调整分箱数量或使用分位数分箱,避免空箱或极端分箱
修复后代码
import matplotlib.pyplot as plt import scikitplot as skplt from matplotlib.ticker import AutoMinorLocator from sklearn.linear_model import LogisticRegression from sklearn.tree import DecisionTreeClassifier from sklearn.svm import SVC from sklearn.ensemble import RandomForestClassifier from xgboost import XGBClassifier from sklearn.calibration import CalibratedClassifierCV # 训练模型并提取正类概率 # Logistic Regression lr = LogisticRegression().fit(X_train, y_train) lr_probas = lr.predict_proba(X_test)[:, 1] # Random Forest rf = RandomForestClassifier().fit(X_train, y_train) rf_probas = rf.predict_proba(X_test)[:, 1] # 校准后的Decision Tree dt = DecisionTreeClassifier().fit(X_train, y_train) calibrated_dt = CalibratedClassifierCV(dt, method='sigmoid', cv=5) calibrated_dt.fit(X_train, y_train) dt_probas = calibrated_dt.predict_proba(X_test)[:, 1] # SVM svm = SVC(probability=True).fit(X_train, y_train) svm_probas = svm.predict_proba(X_test)[:, 1] # XGBoost xgb = XGBClassifier().fit(X_train, y_train) xgb_probas = xgb.predict_proba(X_test)[:, 1] # 准备绘图数据 probas_list = [lr_probas, rf_probas, dt_probas, svm_probas, xgb_probas] clf_names = ["Logistic Regression", "Random Forest", "Calibrated Decision Tree", "Support Vector Machines", "XGBoost"] # 绘制校准曲线,使用分位数分箱避免空箱 ax = skplt.metrics.plot_calibration_curve(y_test, probas_list, clf_names, n_bins=10, strategy='quantile', figsize=(15,6)) # 设置网格细节 ax.xaxis.set_minor_locator(AutoMinorLocator(2)) ax.yaxis.set_minor_locator(AutoMinorLocator(2)) ax.grid(which='minor', linewidth=0.6) plt.show()
修复效果说明
- Logistic Regression曲线会正常显示,因为传入了正确的一维正类概率数组
- 校准后的Decision Tree曲线会偏离理想线,呈现模型真实的校准偏差
- 分位数分箱策略让每个分箱的样本量更均衡,避免空箱,消除
invalid value encountered in true_divide警告
内容的提问来源于stack exchange,提问作者codec_8888
相关产品推荐
相关产品推荐

