R:在字符串中获取每个单词排列的内存有效方法

问题描述 投票:4回答:3

我有一个包含单词列表的字符串,我希望从中获取所有可能的单词组合。

fruits <- "Apple Banana Cherry"

要获得此输出:

"Apple, Banana, Cherry, Apple Banana, Apple Cherry, Banana Cherry, Apple Banana Cherry"

使用定义的here函数,稍加修改:

f1 <- function(str1){
  v1 <- strsplit(str1, ' ')[[1]]
  paste(unlist(sapply(seq(length(v1)), function(i)
    apply(combn(v1, i), 2, paste, collapse=" "))), collapse= ', ')
}

f1(fruits)

当行数相对较少时,这样可以正常工作,但实际示例在3,350行中总共有93,300个字符,中间字符串长度为25个字符,导致类似于this:的错误

粘贴错误(unlist(sapply(seq(length(v1)),function(i)apply(combn(v1,:result将超过2 ^ 31-1个字节)

我尝试在函数中将utils::combn更改为RcppAlgos::comboGeneral,因为它显然是quicker,但仍然遇到了同样的问题。有什么方法可以解决这个问题?

r nlp out-of-memory permutation
3个回答
2
投票

我们在quanteda中有一个非常有效的矢量化skipgrams和ngrams函数。尝试这个,使用多线程提高效率(您可以将线程更改为系统的最大值):

library("quanteda")
## Package version: 1.4.3
## Parallel computing: 2 of 12 threads used.
## See https://quanteda.io for tutorials and examples.
## 
## Attaching package: 'quanteda'
## The following object is masked from 'package:utils':
## 
##     View
quanteda_options(threads = 4)

fruits <- "Apple Banana Cherry"
tokens(fruits) %>%
  tokens_skipgrams(., n = seq_len(ntoken(.)), skip = 0:ntoken(.), concatenator = " ") %>%
  as.character() %>%
  paste(collapse = ", ")
## [1] "Apple, Banana, Cherry, Apple Banana, Apple Cherry, Banana Cherry, Apple Banana Cherry"

2
投票

如果你有三个字

fruits <- "Apple Banana Cherry"

可以通过使用0或1来表示组合以表示每个单词的包含。这意味着有三个单词你有2 ^ 3 - 1 = 7个选项,不包括null:

001 Cherry
010 Banana
011 Banana, Cherry
100 Apple
101 Apple, Cherry
110 Apple, Banana
111 Apple, Banana, Cherry

所以我们可以把它想象成二进制数。所有三字组合可以用三位表示,并且有2 ^ 3 - 1 = 7个选项。

存储每个组合的问题在于,每个附加单词的列表长度将加倍。当你有80个单词时,需要80比特来表达每个可能的组合,但是会有2 ^ 80 - 1 =大约1,200,000,000,000,000,000,000,000,000(1.2E24)个不同的可能组合,这将占用比所有硬盘更多的空间。世界。

我并不是说暗示这是一个无法解决的问题,并且判断其他答案是否会以有效的方式完成你想做的事情并不是我的经验领域,但我只想观察到会有物理限制以问题提出的方式预先计算和存储所有可能的组合是不切实际的。


1
投票

为了使问题保持​​简单,我省略了我最终要做的是创建这些组合的列表。

我也不知道这个名字是用Skip-Gram标记化的。虽然最终仍然很慢,但这个解决方案避免了R内存错误并且具有足够的计算能力,它可以解决这个问题:

library(tokenizers)
unlist(tokenize_skip_ngrams(fruits, n = 3, n_min = 1, k = 3))
© www.soinside.com 2019 - 2024. All rights reserved.