scikit-learn中的class_weight参数如何工作?
我很难理解scikit-learn的Logistic回归中的class_weight
参数是如何运作的。
情况
我想用逻辑回归来对非常不平衡的数据集进行二元分类。 这些类别被标记为0(负)和1(正),并且观察到的数据与大多数样品具有负面结果的比率约为19:1。
第一次尝试:手动准备培训数据
我将这些数据分成了不相交的集合,用于训练和testing(约80/20)。 然后我手工对训练数据进行随机抽样,得到不同比例的训练数据,比例为19:1; 从2:1 – > 16:1。
然后,我对这些不同的训练数据子集进行逻辑回归训练,并作为不同训练比例的函数绘制回忆(= TP /(TP + FN))。 当然,召回是在不相交的TEST样品上计算出来的,其比例为19:1。 请注意,尽pipe我在不同的训练数据上训练了不同的模型,但我还是在相同的(不相交的)testing数据上计算了所有的模型。
结果如预期:在2:1的训练比例下,回收率约为60%,到达16:1时相当快地下降。 召回率在5%以上的比例为2:1 – > 6:1。
第二次尝试:网格search
接下来,我想testing不同的正则化参数,所以我使用了GridSearchCV,并创build了一个包含C
参数的几个值以及class_weight
参数的网格。 把我的n:m比例的负面:正面训练样本翻译成class_weight
的字典语言我以为我只是指定了几个字典,如下所示:
{ 0:0.67, 1:0.33 } #expected 2:1 { 0:0.75, 1:0.25 } #expected 3:1 { 0:0.8, 1:0.2 } #expected 4:1
我也包括None
和auto
。
这一次结果完全被摧毁了。 除了auto
之外,我所有的召回都是很小的(<0.05)。 所以我只能假设我对如何设置class_weight
字典的理解是错误的。 有趣的是,在网格search中,“auto”的class_weight
值对于C
所有值都大约为59%,我猜想它平衡到1:1。
我的问题
1)您如何正确使用class_weight
来实现您实际给予的训练数据的不同平衡? 具体来说,我传递给class_weight
字典使用n:m比例的否定:正面训练样本?
2)如果您将各种class_weight
字典传递给GridSearchCV,那么在交叉validation期间,它将根据字典重新平衡训练折叠数据,但是使用真实的给定样本比例来计算testing折叠上的评分函数? 这是至关重要的,因为任何度量标准对于我来说都是有用的,如果它来自于观察比例的数据。
3) class_weight
的auto
价值是什么比例? 我阅读文档,我假设“平衡数据与其频率成反比”就意味着它使它成为1:1。 它是否正确? 如果没有,有人可以澄清?
非常感谢,任何澄清将不胜感激!
首先,单单回顾可能并不好。 您可以简单地通过将所有内容归类为正面类来实现100%的回忆。 我通常build议使用AUC来select参数,然后find您感兴趣的操作点(比如给定的精确度)的阈值。
对于class_weight
是如何工作的:它用class_weight[i]
而不是1来惩罚class[i]
样本中的错误。因此,更高的类别权重意味着您希望更强调类。 从你所说的看来,类0比类1的频率高19倍。所以你应该增加类1相对于类0的class_weight
,比如说{0: class_weight
:.9}。 如果class_weight
不等于1,它将基本上改变正则化参数。
关于class_weight="auto"
作用,你可以看看这个讨论 。 在开发版本中,您可以使用class_weight="balanced"
,这更容易理解:它基本上意味着复制较小的类,直到您拥有与较大的样本一样多的样本,但以隐式的方式。