如何使用新(测试)数据创建相同的文档术语矩阵

时间:2013-05-19 01:30:09

标签: r machine-learning nlp text-mining tm

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

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

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

但是,当我想在测试数据上评估/预测模型或未来可能出现的任何新数据时,我该如何处理?

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

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

任何想法/想法?

2 个答案:

答案 0 :(得分:14)

tm有很多陷阱......看到效率更高的text2vecvectorization vignette可以完全回答这个问题。

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

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

答案 1 :(得分:9)

如果我理解正确,你已经创建了一个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所述)。

这是否符合您的要求?