如何正确执行多标签数据集中训练/测试拆分的数据采样?

数据挖掘 数据集 多标签分类 采样
2022-01-25 22:38:05

问题陈述

我有一个文本多标签分类数据集,我发现数据集采样存在问题。

我面临两种不同的策略。第一个包括一起预处理语料库,然后在训练之前进行训练/测试拆分。第二个从预先制作的 train/test split开始,因此预处理是单独进行的。

预处理步骤只是将标签转换为 OneHot 表示并仅保留N个最频繁的表示。我期待类似(相同)的行为,但我得到了非常奇怪的结果。让我们仔细看看。

一起训练+测试然后拆分

从...开始:

|ID   |TEXT  |LABELS|
|-----|------|------|
|1.txt|the   |A:B   |
|2.txt|lazy  |B     |
|3.txt|fox   |C     |
|4.txt|jumps |B:C   |
|5.txt|over  |C:D   |
|6.txt|crazy |D     |

预处理和拆分后:训练

|ID   |TEXT|A|B|C|D|
|-----|----|-|-|-|-|
|1.txt|the |1|1|0|0|
|2.txt|lazy|0|1|0|0|
|3.txt|fox |0|0|1|0|

测试

|ID   |TEXT |A|B|C|D|
|-----|-----|-|-|-|-|
|4.txt|jumps|0|1|1|0|
|5.txt|over |0|0|1|1|
|6.txt|crazy|0|0|0|1|

结果很好让我们以此作为参考。F1-Score = 0.61.

预制训练/测试拆分

从...开始:

火车

|ID   |TEXT|LABELS|
|-----|----|------|
|1.txt|the |A:B   |
|2.txt|lazy|B     |
|3.txt|fox |C     |

测试

|ID   |TEXT |LABELS|
|-----|-----|------|
|4.txt|jumps|B:C   |
|5.txt|over |C:D   |
|6.txt|crazy|D     |

预处理和拆分后:

火车

|ID   |TEXT|A|B|C|
|-----|----|-|-|-|
|1.txt|the |1|1|0|
|2.txt|lazy|0|1|0|
|3.txt|fox |0|0|1|

测试

|ID   |TEXT |B|C|D|
|-----|-----|-|-|-|
|4.txt|jumps|1|1|0|
|5.txt|over |0|1|1|
|6.txt|crazy|0|0|1|

结果完全退化了。F1-Score = 0.15.

到底是怎么回事?什么可能导致结果的差异?

额外的信息

  • 在预测步骤预测的标签与测试集上的标签不兼容。我已经考虑到这一点并且得到了正确的管理,这不是问题。
  • 分裂是完全一样的。train/test 中的文档在两种情况下都是相同的。
1个回答

我面临两种不同的策略。第一个包括一起预处理语料库,然后在训练之前进行训练/测试拆分。第二个从预先制作的训练/测试拆分开始,因此预处理是单独进行的。

从“不要重复使用数据”的角度来看,策略 2 是“正确的”。数据预处理是训练的一部分。原则上,您的训练/测试管道应该考虑到这一点。例如,如果您有一个功能A有 5 个类别,但其中只有 4 个类别出现在数据中,正确的做法是在 one-hot 编码中仅使用 4 个类别,并将第 5 个类别视为“未知”值。

然而,在实践中,这并不总是可行的。在某些情况下,预处理管道是计算密集型的(例如训练词向量)或需要处理大量数据(例如从 AWS 中摄取 5 GB 的图像)。在这些情况下,您必须接受这样一个事实,即您的测试集的一些知识会通过您的预处理步骤“泄漏”到您的训练集中,但这通常还不错。

其他时候,您在训练/测试拆分后没有足够的数据来正确进行预处理。或者你没有对你的分裂进行分层,所以你最终得到了不完整的类表示,或者其他不平衡的训练集。这是你发现自己的地方。只需查看标题即可了解原因:

火车:

|ID   |TEXT |A|B|C|

测试:

|ID   |TEXT |B|C|D|

您的测试集中缺少“A”类,而您的训练集中缺少“D”类。这将破坏几乎任何模型。

对多标签数据的分层进行了一些研究。值得注意的是,“关于多标签数据的分层”(Sechidis、Tsoumakas 和 Vlahavas;ECML PKDD 2011)引入了“迭代分层”。在scikit-multilearn Python 库中有这种技术的实现。