在训练中使用 class_weight 转换 predict_proba 结果

数据挖掘 分类 scikit-学习 随机森林 阶级失衡 概率校准
2021-10-01 03:46:54

由于我的数据集不平衡(1 类:5%,0 类:95%),我使用了 class_weight="balanced" 参数来训练随机森林分类模型。通过这种方式,我惩罚了对罕见阳性病例的错误分类。

rf = RandomForestClassifier(max_depth=m, n_estimators=n_estimator,class_weight = "balanced")
rf.fit(X_train, y_train)

“平衡”模式使用 y 的值自动调整权重,与输入数据中的类频率成反比,如 n_samples / (n_classes * np.bincount(y))

就我而言,课程频率是:

fc = len(y_train)/(len(np.unique(y_train))*np.bincount(y_train))

10000/(2*np.array([9500,500])) array([ 0.52631579, 10. ])

我使用预测概率函数将我的模型应用于测试数据集:

y_predicted_proba = rf.predict_proba(X_test)

输出截图

第二列表示输入样本为 1 的概率。但是我知道这个概率必须被纠正为真实的。

如果我将它们除以 class_weight 值,这些新概率不会相加...

新输出的屏幕截图

如何实现这种校正?

2个回答

您正在谈论的校正称为概率校准-您希望观察到每个类别的“真实”概率,对吗?

两种最常见的概率校准方法是 Platt Scaling 和 Isotonic 回归。由于您正在一个平衡的训练集上进行训练(在您的情况下这是正确的做法,因为原始数据集是不平衡的),您可以在之后将这些技术应用于您的测试集。

抱歉,我无法在这里完全解释这些技术,但希望知道这些术语的名称可以为您提供一个起点。

首先,您应该考虑不平衡数据集。这个问题可能没有必要。


现在到你的实际问题。sklearn中,每棵决策树报告概率,并且这些概率在树上取平均值(与树报告它们的决策和投票相反)。所以我们可以理解权重是如何影响这些概率的。在训练期间的每个叶子中,给出的分数是

# positives in leaf / # total in leaf.
用速记n1n0作为叶子中正面和负面的数量,我们可以重写为
p=n1n0+n1=11+n0n1.
而加权具有将这个数量转换为
p=11+0.526n010n1.

(参见例如[1][2]。)只需一点代数,然后给出

p=11+100.526(1p1).

值得注意的是,这意味着

Adjusted odds=p1p=0.52610(p1p)=0.52610Weighted model's odds.
这与以逻辑回归模型而闻名的重采样调整一致,但对于其他模型则不那么如此。至于一般的类权重:有没有办法在使用类权重后重新校准预测概率?


最后,随机森林通常没有经过良好校准,即您得到的概率分数不一定与真实比例一致。(特别是,预测倾向于回避 0 和 1。)为此,您可以应用 @Maia 提到的校准方法(这避免了上述调整)。