R 使用多核时,tm_映射转换函数的行为不一致

R 使用多核时,tm_映射转换函数的行为不一致,r,parallel-processing,text-mining,tm,doparallel,R,Parallel Processing,Text Mining,Tm,Doparallel,这篇文章的另一个潜在标题可能是“在中进行并行处理时,内核数量、循环块大小和对象大小之间的比率是否重要?” 我有一个语料库,我正在使用tm包运行一些转换。由于语料库很大,我使用并行处理和doparallel软件包 有时转换完成了任务,但有时没有。例如,tm::removeNumbers()。语料库中的第一个文档的内容值为“n417”。因此,如果预处理成功,则此文档将转换为“n” 下面显示了用于复制的样本语料库。以下是代码块: library(tidyverse) library(qdap) lib

这篇文章的另一个潜在标题可能是“在中进行并行处理时,内核数量、循环块大小和对象大小之间的比率是否重要?”

我有一个语料库,我正在使用tm包运行一些转换。由于语料库很大,我使用并行处理和doparallel软件包

有时转换完成了任务,但有时没有。例如,
tm::removeNumbers()
。语料库中的第一个文档的内容值为“n417”。因此,如果预处理成功,则此文档将转换为“n”

下面显示了用于复制的样本语料库。以下是代码块:

library(tidyverse)
library(qdap)
library(stringr)
library(tm)
library(textstem)
library(stringi)
library(foreach)
library(doParallel)
library(SnowballC)

  corpus <- (see below)
  n <- 100 # This is the size of each chunk in the loop

  # Split the corpus into pieces for looping to get around memory issues with transformation
  nr <- length(corpus)
  pieces <- split(corpus, rep(1:ceiling(nr/n), each=n, length.out=nr))
  lenp <- length(pieces)

  rm(corpus) # Save memory

  # Save pieces to rds files since not enough RAM
  tmpfile <- tempfile()
  for (i in seq_len(lenp)) {
    saveRDS(pieces[[i]],
            paste0(tmpfile, i, ".rds"))
  }

  rm(pieces) # Save memory

  # Doparallel
  registerDoParallel(cores = 12)
  pieces <- foreach(i = seq_len(lenp)) %dopar% {
    piece <- readRDS(paste0(tmpfile, i, ".rds"))
    # Regular transformations
    piece <- tm_map(piece, content_transformer(removePunctuation), preserve_intra_word_dashes = T)
    piece <- tm_map(piece, content_transformer(function(x, ...)
      qdap::rm_stopwords(x, stopwords = tm::stopwords("english"), separate = F)))
    piece <- tm_map(piece, removeNumbers)
    saveRDS(piece, paste0(tmpfile, i, ".rds"))
    return(1) # Hack to get dopar to forget the piece to save memory since now saved to rds
  }

  stopImplicitCluster()

  # Combine the pieces back into one corpus
  corpus <- list()
  corpus <- foreach(i = seq_len(lenp)) %do% {
    corpus[[i]] <- readRDS(paste0(tmpfile, i, ".rds"))
  }
  corpus_done <- do.call(function(...) c(..., recursive = TRUE), corpus)
但是,如果我将块大小(“n”变量的值)更改为100:

这些数字已被删除

但是,这是不一致的。我试着缩小范围,测试了150,然后是125。。。并且发现它在120到125块大小之间不会起作用。然后,在120:125之间迭代函数之后,它有时会起作用,但对于相同的块大小,它就不起作用了

我认为这一问题可能与三个变量有关:语料库的大小、语块大小和
registerdoparallel()中的核心数。我只是不知道那是什么

解决办法是什么?这个问题可以通过链接的样本语料库重现吗?我很担心,因为有时我可以重现错误,有时我不能。更改块大小可以查看带有删除编号的错误,但并不总是这样


更新

今天我恢复了会话,无法复制错误。我创建了一个模型,并对语料库大小、核心数量和块大小的不同值进行了实验。在每一个案例中,一切都是成功的。所以,我试着用完整的数据运行,一切都正常。然而,为了我的理智,我尝试在完整数据上再次运行,但失败了。现在,我又回到了昨天的状态

似乎在更大的数据集上运行该函数已经改变了某些内容。。。我不知道是什么!也许是某种会话变量

因此,新的信息是,只有在非常大的数据集上运行函数后,才会发生此错误。重新启动会话并没有解决问题,但在离开几个小时后恢复会话确实解决了问题


新资料:


在一个更大的语料库上重现这个问题可能更容易,因为这似乎触发了这个问题
语料库我不明白你所说的语料库是什么。你只给了我们一个字符向量。@DougFir尽管我对
tm
很尊重,但我还是建议1)创建你自己的预处理函数(学习一些正则表达式)2)跳转到另一个包-
text2vec
quanteda
,速度会更快,也更安全easier@DougFir同时给您一个机会
text2vec
(我是作者:-)。请查看上的教程,并同意上面的评论,即
tm_map
很难调试,有许多记录不良的特性,从短期和长期来看,使用
apply
方法与您自己的自定义函数相比,使用另一个包可能要好得多。我投票结束这个问题,因为这个问题已经超过3年了,没有答案,而且作者在评论中已经给出了明确的备选方案,显然不再对回答
corpus <- VCorpus(VectorSource([paste the chr vector from link above]))
> lapply(1:10, function(i) print(corpus_done[[i]]$content)) %>% unlist
[1] "n417"
[1] "disturbance"
[1] "grand theft auto"
> lapply(1:10, function(i) print(corpus_done[[i]]$content)) %>% unlist
[1] "n"
[1] "disturbance"
[1] "grand theft auto"