如何使用新(测试)数据重新创建相同的 DocumentTermMatrix

Posted

技术标签:

【中文标题】如何使用新(测试)数据重新创建相同的 DocumentTermMatrix【英文标题】:How to recreate same DocumentTermMatrix with new (test) data 【发布时间】:2013-05-13 21:30:06 【问题描述】:

假设我有基于文本的训练数据和测试数据。更具体地说,我有两个数据集——训练和测试——它们都有一个包含文本的列,并且对手头的工作很感兴趣。

我使用 R 中的 tm 包来处理训练数据集中的文本列。在删除空格、标点符号和停用词之后,我对语料库进行词干处理,最后创建了一个 1 克的文档术语矩阵,其中包含每个文档中单词的频率/计数。然后,我采用了预先确定的截止值,例如 50,并且只保留那些计数大于 50 的术语。

在此之后,我使用 DTM 和因变量(存在于训练数据中)训练了一个 GLMNET 模型。到目前为止,一切都顺利而轻松。

但是,当我想根据测试数据或未来可能出现的任何新数据对模型进行评分/预测时,我该如何进行?

具体来说,我想知道的是如何在新数据上创建准确的 DTM?

如果新数据集没有任何与原始训练数据相似的单词,则所有术语的计数都应为零(这很好)。但我希望能够在任何新语料库上复制完全相同的 DTM(就结构而言)。

有什么想法/想法吗?

【问题讨论】:

如果我正确理解了您的问题(我不确定我是否正确,没有可重现的示例来演示您正在尝试做什么。),似乎最简单的方法是使用所有数据创建术语文档矩阵,然后将该矩阵拆分为测试和训练集。这样一来,即使一个矩阵的多个项只有零,您也可以在两个矩阵中表示所有项。您遇到了麻烦,因为您在创建术语文档矩阵之前拆分数据。 我同意 Schaun,但我只能使用我目前拥有的测试数据来做到这一点。我正在寻找一种在我明天获得新数据时可以使用的解决方案。否则,如果总是向现有数据添加新数据会很痛苦,那么每次都重新创建 DTM 并重新训练模型。 同样,使用示例数据可以更轻松地回答您的问题。怎么样:将您的新数据转换为术语文档矩阵,然后使用plyr 包的rbind.fill 函数将其绑定到旧数据,这将创建一个包含两个原始矩阵的所有列的新矩阵。您的训练数据将包含新数据中不在训练数据中的任何术语的 NA 列。然后,您可以删除这些列。您的新数据将包含训练数据中任何术语的 NA 列,但新数据中没有,您可以将这些 NA 替换为零。 谢谢肖恩;这确实有帮助。不幸的是,我没有任何样本数据。本质上,我试图弄清楚任何包中是否存在应该巧妙地执行此操作的函数。例如,创建了一个 dtm,它使用现有的结构在提供新数据时创建一个新的。在网上搜索并没有发现任何内容,所以我想在这里发布。 【参考方案1】:

tm 有很多陷阱...查看更高效的text2vec 和vectorization vignette,它们完全回答了这个问题。

对于tm,这里可能是为第二个语料库重构 DTM 矩阵的一种更简单的方法:

crude2.dtm <- DocumentTermMatrix(crude2, control = list
               (dictionary=Terms(crude1.dtm), wordLengths = c(3,10)) )

【讨论】:

这也很好用,但 Dictionary() 不再受支持,您必须改用 Terms() 很好的例子,肯定会试一试,一直在寻找一种本地的方式来做到这一点。我想我实际上应该阅读我使用的软件包的 vingietes :) 我认为这个解决方案要好得多,因为它不会从稀疏矩阵转换 这是最好/最短的解决方案。谢谢!那里有很多教程讨论 R 中的文本分析。但是,我看过的没有一个讨论如何对新文档进行“样本外”预测。【参考方案2】:

如果我理解正确,您已经制作了一个 dtm,并且您想从与第一个 dtm 具有相同列(即术语)的新文档中制作一个新的 dtm。如果是这种情况,那么它应该是通过第一个中的条款子设置第二个 dtm 的问题,也许是这样的:

首先设置一些可重现的数据...

这是你的训练数据...

library(tm)
# make corpus for text mining (data comes from package, for reproducibility) 
data("crude")
corpus1 <- Corpus(VectorSource(crude[1:10]))    
# process text (your methods may differ)
skipWords <- function(x) removeWords(x, stopwords("english"))
funcs <- list(tolower, removePunctuation, removeNumbers,
              stripWhitespace, skipWords)
crude1 <- tm_map(corpus1, FUN = tm_reduce, tmFuns = funcs)
crude1.dtm <- DocumentTermMatrix(crude1, control = list(wordLengths = c(3,10))) 

这是你的测试数据……

corpus2 <- Corpus(VectorSource(crude[15:20]))  
# process text (your methods may differ)
skipWords <- function(x) removeWords(x, stopwords("english"))
funcs <- list(tolower, removePunctuation, removeNumbers,
              stripWhitespace, skipWords)
crude2 <- tm_map(corpus2, FUN = tm_reduce, tmFuns = funcs)
crude2.dtm <- DocumentTermMatrix(crude2, control = list(wordLengths = c(3,10))) 

这是你想要的:

现在我们只保留训练数据中存在的测试数据中的术语...

# convert to matrices for subsetting
crude1.dtm.mat <- as.matrix(crude1.dtm) # training
crude2.dtm.mat <- as.matrix(crude2.dtm) # testing

# subset testing data by colnames (ie. terms) or training data
xx <- data.frame(crude2.dtm.mat[,intersect(colnames(crude2.dtm.mat),
                                           colnames(crude1.dtm.mat))])

最后将训练数据中不在测试数据中的术语的所有空列添加到测试数据中...

# make an empty data frame with the colnames of the training data
yy <- read.table(textConnection(""), col.names = colnames(crude1.dtm.mat),
                 colClasses = "integer")

# add incols of NAs for terms absent in the 
# testing data but present # in the training data
# following SchaunW's suggestion in the comments above
library(plyr)
zz <- rbind.fill(xx, yy)

所以zz 是测试文档的数据框,但与训练文档具有相同的结构(即相同的列,尽管其中许多包含 NA,如 SchaunW 所述)。

这符合你想要的吗?

【讨论】:

是的,本。这很有帮助。非常感谢。 :) 别担心!现在您知道如何制作示例数据以包含在您可能想问的任何相关问题中。 我一直在寻找解决方案,谢谢,虽然我也会尝试下面由 Dmitriy 提供的解决方案 这需要解构你的稀疏矩阵,考虑使用dictionary=Terms(crude1.dtm)的解决方案

以上是关于如何使用新(测试)数据重新创建相同的 DocumentTermMatrix的主要内容,如果未能解决你的问题,请参考以下文章

python测试开发django-72.删除表后如何重新生成表

按相同类别创建新数据时无法保存数据

创建具有相同类别的新数据时如何按类别计算数据

如何使用行的值作为新列重新格式化数据集?

卸载 Vue 实例或重新安装到新位置

如何测试网页代码?