假设我有基于文本的训练数据和测试数据。更具体地说,我有两个数据集——训练集和测试集——它们都有一个包含文本的列,并且这个列是当前任务所关注的对象。
我使用R语言中的tm包处理训练数据集中的文本列。在去除空格、标点符号和停用词后,我对语料库进行了词干提取,最终创建了一个包含每个文档中单词频率/计数的1-gram文档术语矩阵。然后,我设定了一个预定的截止值,例如50,只保留计数大于50的术语。
接下来,我使用DTM和训练数据中存在的因变量训练了一个GLMNET模型。到目前为止,一切顺利且简单。
然而,当我想在测试数据或未来可能出现的任何新数据上评分/预测模型时,我该如何进行呢?
具体来说,我试图找出如何在新数据上创建完全相同的DTM?
如果新数据集中没有与原始训练数据类似的词,那么所有术语的计数都应该是零(这是可以接受的)。但我想能够在任何新的语料库上复制完全相同的DTM(在结构上)。
有什么想法或建议吗?
回答:
如果我理解正确的话,你已经创建了一个dtm,并且你想从新的文档中创建一个新的dtm,这个新的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 subsettingcrude1.dtm.mat <- as.matrix(crude1.dtm) # trainingcrude2.dtm.mat <- as.matrix(crude2.dtm) # testing# subset testing data by colnames (ie. terms) or training dataxx <- 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 datayy <- 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 abovelibrary(plyr)zz <- rbind.fill(xx, yy)
所以zz
是一个测试文档的数据框,但具有与训练文档相同的结构(即相同的列,尽管其中许多包含NA,正如SchaunW所指出的)。
这是你想要的方向吗?