如何进行MultiLabel分层抽样?

时间:2018-11-19 16:31:10

标签: python scikit-learn

我正在处理多标签数据,我想使用分层抽样。假设我有10个班级,我们称之为“ ABCDEFGHIJ”。我有一个带有10列的数据框,对应于每个标签,其中包含有关条目的其余信息。我可以在n_entry * 10矩阵中提取这10列,我将其称为label_values

例如,一行label_values看起来像[0,0,1,1,0,0,0,0,0,0],而这一特定行意味着该条目具有Label C和Label D。

我想在训练和验证集中进行数据拆分,并且我希望每个标签在训练和验证中的比例相同。为了执行拆分,我使用了Sklearn train_test_split函数(在我需要分层之前),该函数碰巧有一个分层的参数。当前的行为是使multi_label行为成为一个多类行为(我们认为[A,B]是与A类和B类完全不同的全新类)。结果,有些类只有1个元素,这会触发错误:

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.")

来自StratifiedShuffleSplit类的_iter_indices中的sklearn / model_selection / _split.py:

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.")

我的解决方法是重写此方法以删除此检查。这行得通,我可以更好地在训练和验证之间重新分配标签。但是,我的带有2个元素的标签之一完全在火车中。正常吗?

其他问题:这是进行此操作的好方法,还是您认为有一个更好的方法可以在multi_label中对train_test_split进行分层?

2 个答案:

答案 0 :(得分:1)

您已经注意到,scikit-learn's train_test_split()的分层不会单独考虑标签,而是将其视为“标签集”。这对于多标签数据根本不起作用,因为唯一组合的数量随标签的数量呈指数增长。在您的示例中,有1024种可能的标签组合。要进行双向拆分,您至少需要有两次拆分,即使那样,每次拆分也只能得到一个示例。

由于禁用了重复的标签集,所以禁用检查的拆分可能会有些效果,但是对于唯一的标签集,您只是允许scikit-learn随机拆分它们,这没有用或无效。

Sechidis,Tsoumakas和Vlahavas于2011年提出了一种算法,称为Iterative Stratification,该算法通过分别考虑每个标签,从拥有最少阳性样本的标签开始,一直到最好的方式,分割多标签数据集。代表一个。

您目前可以使用两种实现方式:

  1. iterative-stratification
  2. scikit-multilearn的iterative_train_test_split()

假设您要对这3个标签(L1,L2,L3)样本进行双向拆分:

L1 L2 L3
--------
0  0  0
0  0  1
0  1  0
0  1  1
1  0  0 
1  0  1
1  1  0
1  1  1

有8个唯一的标签集,但每个标签都有4个正面示例。迭代分层而不是随机拆分,而是尝试为您提供两个拆分,每个拆分包含来自每个标签的均衡数量的示例。拆分示例如下所示:

Split 1
-------
L1 L2 L3
0  0  1
0  1  0
1  0  1
1  1  0

Split 2
-------
L1 L2 L3
0  0  0
0  1  1
1  0  0
1  1  1

请注意,即使每个标签集保持唯一,现在每个标签在拆分之间也具有很好的均匀平衡。

答案 1 :(得分:1)

对您来说最简单的解决方案是使用带有 skmultilearn 的多标签分层。快速示例:

from skmultilearn.model_selection import iterative_train_test_split
t_train, y_train, t_test, y_test = iterative_train_test_split(X, y, test_size = 0.2)

请注意,迭代分层很慢,对于大型数据集可能会非常耗时。