scikit learn中的样本权重和类别权重选项有什么区别?

30
我有一个类别不平衡的问题,想使用成本敏感学习来解决。
  1. 欠采样和过采样
  2. 为类别分配权重,使用修改后的损失函数
问题: Scikit learn 有2个选项叫做class weights 和 sample weights。sample weight 实际上是在执行选项二吗?class weight 是选项一吗?选项二是处理类别不平衡的推荐方式吗?

1
我认为这在很大程度上取决于问题。你能否提供一些关于数据不平衡程度的更多信息,以及你已经尝试过什么? - rabbit
3个回答

18

这是类似的概念,但是使用sample_weights可以强制评估器更多地关注一些样本,而使用class_weights可以强制评估器学习并关注某个特定类别。当sample_weight=0或class_weight=0时,评估器基本上不需要考虑这些样本/类别在学习过程中的影响。因此,分类器(例如)将永远不会预测某个类别,如果该类别的class_weight = 0。如果某些sample_weight/class_weight比其他样本/类别的sample_weight/class_weight大,评估器将首先尝试在那些样本/类别上最小化误差。您可以同时使用用户定义的sample_weights和class_weights。

如果您想使用简单的克隆/删除来对训练集进行欠采样/过采样-这将等同于增加/减少相应的sample_weights/class_weights。

在更复杂的情况下,您还可以尝试使用像SMOTE这样的技术人工生成样本。


2
澄清一下,在这个答案中,“/”表示“斜杠”,而不是“除法”。总的来说,解释得很好。 - DataMan
1
@DataMan,是的,这是真的。我同意sample_weight/class_weight=0看起来很奇怪。 - Ibraim Ganiev
@IbraimGaniev 假设我有一个数据集,有100k个样本。99%是0,1%是1。如何为这些数据指定样本权重?它会是1:100的比率还是其他什么?clf.fit(X, y, sample_weight=None)[source]和scikit文档说:每个样本的权重。每个样本重新缩放C。更高的权重会迫使分类器更加强调这些点。我不明白在这段代码中应该写入哪些值:sample_weight = {0:.01, 1:.90}或者它必须是一个向量吗?如果是,怎么做? - Chuck
关于SMOTE需要注意的一点是:如果你的样本太小,或者特征重叠,那么你无法可靠地生成样本。 - Sakthi K

8
sample_weightclass_weight有类似的功能,即使你的估算器更加关注某些样本。

实际样本权重将为sample_weight * class_weight中的权重

这与欠采样/过采样具有相同的目的,但行为可能不同:假设您有一个随机选择样本的算法(如随机森林),则是否进行过采样或欠采样很重要。

总之:
class_weightsample_weight都执行2)的功能,选项2)是处理类别不平衡的一种方法。 我不知道普遍推荐的方法,我会尝试在您特定的问题上尝试1)、2)和1)+2),以查看哪种方法最有效。


1
@Idrier 假设我有一个数据集,有100k个样本。99%是0,1%是1。如何为这些数据指定样本权重?它会是1:100的比率还是其他什么?clf.fit(X, y, sample_weight=None)[source]和scikit文档说:每个样本的权重。每个样本重新缩放C。更高的权重会迫使分类器更加强调这些点。我不明白在这段代码中应该写什么值:sample_weight = {0:.01, 1:.90}或者它必须是一个向量吗?如果是,怎么做? - Chuck
@Chuck,我也和你一样感到困惑。我很想知道应用于样本权重和类别权重计算的确切公式,Idirer给出了一个好的例子,但我也在寻找像你的问题一样的实际例子。 - Amith Adiraju

0
假设你有5个样本,其中前两个属于A类,后三个属于B类。为了"实现平衡",你可以给这两个类别分配权重(例如,class_weight=[0.6, 0.4]),或者给这五个样本分配权重(例如,sample_weight=[0.25, 0.25, 0.167, 0.167, 0.167])。因此,sample_weight允许在样本级别上进行更精细的加权,而不是在类别级别上。
如果同时使用这两种加权方法,样本的实际权重将是其sample_weight与其所属类别的class_weight的乘积,通常情况下你不希望这样。此外,有人会说,为了平衡类别而给样本分配权重在概念上很尴尬(特别是在多标签分类中,同一个样本可能属于一个非常频繁和一个稀疏的类别,那么你会给它分配什么样的样本权重?)或者至少是不必要地复杂。因此,通常情况下,你会通过class_weight来处理不平衡的类别,并且只在需要额外改变特定样本的权重时才使用sample_weight,例如将某些样本的权重设为零。
据我所知,sklearn中并不是所有的函数或指标都提供两个参数。如果你有一个二元分类器,并且真的需要通过sample_weight来平衡类别,因为该指标不接受class_weight(不确定是否存在这种情况,但以防万一...),那么你可以使用compute_sample_weight(class_weight='balanced', y=y_true)sklearn.utils.class_weight中获取平衡类别的样本权重。compute_sample_weight方法可以实现这一功能。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接