我们应该在训练/测试拆分之前还是之后预处理文本数据?



我读过很多文本监督分类教程,并为我的数据实现了tidytext,qunateda,tm,text2vec,RTextTools。到目前为止,我有一个未解之谜。对于何时标记文本数据似乎没有普遍共识。在训练测试拆分之前还是之后?。在一个堆栈溢出帖子中,一些人认为在拆分之前进行标记化甚至是非法的。使用dfm_match函数,quanteda 包看起来像是在拆分数据后进行标记化而设计的。其他人建议在预处理后进行拆分。我看过Julia Silge和Emil Hvitfeldt.
对我来说,如果我在拆分之前执行预处理步骤,它将为我节省许多代码行。但是,有什么风险?数据泄露还是什么?是否有任何证据在分类性能、效度等方面比较两者?

"非法拆分"? 听起来很有趣(可能很有趣),但我从未听说过。

问题是:在什么情况下可以发挥作用,如何发挥作用? 训练-测试拆分对文档进行分区。 无论您是在拆分之前还是之后标记它们可能无关紧要,因为文档仍将包含相同的标记。

但是,一旦从这些标记构造矩阵,如果在拆分执行此操作,则模型矩阵的特征集可能与测试集中的特征集不同。 若要在测试集上进行预测,测试数据的特征必须与训练矩阵中的特征一致。 处理不匹配有几种可能性。

  • 特征在训练集中,但在测试集中不存在。 在quanteda.textmodels中,predict()中有一个(方便!)选项,可以使预测矩阵自动符合训练矩阵,这意味着测试集将添加此功能,但计为零。 这是合理的,因为考虑到特征向训练数据添加了信息,并且它的缺失可以在测试数据中计为信息量。

  • 功能不在训练集中,但在测试集中。 大多数情况下,您可能希望完全忽略此功能。 为什么? 由于在训练的模型中没有关于它的信息,因此它的效果要么是未定义的,要么完全是由于平滑。

回到问题,它如何才能有所作为? 我能看到的主要事情是当形成文档特征矩阵(dfm)然后拆分为行时,训练集中的某些特征完全为零(但在测试集中不为零)。 如果分割是以包含零频率特征的方式完成的,则某些监督方法将对此进行平滑处理,以便包括其平滑值。

下面是来自quanteda的示例,它使用 Naive Bayes 分类器,该分类器默认对所有要素使用 +1 平滑。

让我们用两个类组成一个简单的 dfm。

library("quanteda")
## Package version: 2.1.1
txt <- c(
d1 = "a a b b d",
d2 = "a a a b b",
d3 = "a b d d d",
d4 = "a a b c d"
)
y <- c("black", "black", "white", NA)
train <- c(TRUE, TRUE, TRUE, FALSE)
test <- !train

现在先标记,然后再拆分。 请注意,对于整个三个训练集文档,特征c为零,但如果在此组合的 dfm 上完成索引切片,则特征将出现在训练集中。

dfmat1 <- tokens(txt) %>%
dfm()
dfmat1
## Document-feature matrix of: 4 documents, 4 features (25.0% sparse).
##     features
## docs a b d c
##   d1 2 2 1 0
##   d2 3 2 0 0
##   d3 1 1 3 0
##   d4 2 1 1 1

在标记化和形成 dfm 之前完成切片时,不包括特征c

dfmat2 <- tokens(txt[train]) %>%
dfm()
dfmat2
## Document-feature matrix of: 3 documents, 3 features (11.1% sparse).
##     features
## docs a b d
##   d1 2 2 1
##   d2 3 2 0
##   d3 1 1 3

测试矩阵如下所示,并且具有比"黑色"相关d更多的"白色"相关a

dfmattest <- tokens(txt[test]) %>%
dfm()
dfmattest
## Document-feature matrix of: 1 document, 4 features (0.0% sparse).
##     features
## docs a b c d
##   d4 2 1 1 1

现在,当我们训练模型并进行预测时,当包含c时,我们会看到这一点:

library("quanteda.textmodels")
tmod1 <- textmodel_nb(dfmat1, y)
coef(tmod1)
##        black     white
## a 0.42857143 0.2222222
## b 0.35714286 0.2222222
## d 0.14285714 0.4444444
## c 0.07142857 0.1111111
predict(tmod1, newdata = dfmattest, force = TRUE, type = "prob")
##        black     white
## d4 0.5526057 0.4473943

但当它不是时,结果略有不同:

tmod2 <- textmodel_nb(dfmat2, y[train])
coef(tmod2)
##       black white
## a 0.4615385  0.25
## b 0.3846154  0.25
## d 0.1538462  0.50
predict(tmod2, newdata = dfmattest, force = TRUE, type = "prob")
## Warning: 1 feature in newdata not used in prediction.
##        black     white
## d4 0.6173551 0.3826449

警告消息告诉我们,测试集特征c未用于预测结果,因为它在训练集中不存在。

所以要问的问题是,您是否希望缺少功能被视为信息丰富? 对于默认多项式朴素贝叶斯,如果在从所有要素形成 dfm 后进行分割,则可以通过平滑对缺失进行建模,或者如果先分割并单独创建每个 dfm,则可以忽略缺失。 答案取决于你想如何处理零以及它们在你的问题中意味着什么。 这也部分取决于您的模型,因为(例如)对于伯努利朴素贝叶斯,零被认为是信息丰富的。

最新更新