如何为多标签多类分类执行分层抽样?

数据挖掘 分类 数据挖掘 数据清理 阶级失衡
2021-10-03 04:49:18

我问这个问题有几个原因:

  • 手头的数据集不平衡
  • 我用下面的代码

    x = dataset[['Message']] 
    y = dataset[['Label1', 'Label2']]
    train_data, test_data = train_test_split(x, test_size = 0.1, stratify=y, random_state = 73)
    

    但我得到的错误消息是The least populated class in y has only 1 member, which is too few. The minimum number of labels for any class cannot be less than 2.我删除了每个单独标签中类数 < 2 的类。

我不确定为什么会弹出此错误。

所以,我想自己去实施分层抽样。在这里,我需要帮助来破译这里问题的原因以及在多标签分类中实施分层抽样,以便在训练时它也适用于单个批次。

3个回答

这里的错误似乎是因为您想要训练和测试数据(所以两个数据集),这意味着每个类都必须存在于每个数据集中。这意味着每个类必须至少有两个样本。这是实施者的设计选择train_test_split我想从技术上讲可能不是这样stratified

你可以看到它在SciKit Learn 源代码中的实现位置,在class StratifiedShuffleSplit

classes, y_indices = np.unique(y, return_inverse=True)
n_classes = classes.shape[0]

class_counts = np.bincount(y_indices)

if np.min(class_counts) < 2:
    raise ValueError("The least populated class in y has only 1"
                     " member, which is too few. The minimum"
                     " number of groups for any class cannot"
                     " be less than 2.")

np.unique查找 中的每个类的索引y因为return_inverse=True传递了选项,所以它返回一个索引数组,允许完全重建输入数组y这意味着,要获得存在的类的总数,您需要使用np.bincount; 创建class_counts.

最后的检查是是否class_counts少于您要创建的数据集的数量。如果是这样,那么您将无法创建正确分层的数据拆分 - 因此您会收到错误消息。


至于如何创建自己的版本:我实现分层抽样的一种方法是使用直方图,更具体地说是 NumPy 的histogram函数。它适用于连续标签(即不是离散类) - 而且我没有考虑多标签问题,因此您可能需要调整我的建议以使其满足您的需求。

主要思想是将标签拆分为直方图的箱,然后从这些箱中随机抽样,并可选择允许重复这确实是解决您在一个类中 < 2 个标签的具体问题的部分。我意识到这并没有具体回答你的问题,但也许它会给你一些新的想法。

如果在您的实验中重复没有意义或严格不允许,那么您可以考虑以某种方式将较小的类合并在一起,这样每个类将有 > 2 个标签。这可能比删除它们更有用,但是否可行将取决于您的数据。

您可以在skmultilearn 库中使用多标签数据分层

这是因为分层的性质。该参数将其设置为以将数据量分配给每个类stratify的方式拆分数据。test_size在这种情况下,您的一个(或多个)类没有足够的类标签来保持数据拆分率等于test_size.