edit: Новый пакет text2vec отлично подходит и решает эту проблему (и многие другие) очень хорошо.Действительно быстрая векторизация вектора вектора в R
text2vec on CRAN text2vec on github vignette that illustrates ngram tokenization
У меня есть довольно большой текстовый набор данных в R, который я импортируемого как вектор символов:
#Takes about 15 seconds
system.time({
set.seed(1)
samplefun <- function(n, x, collapse){
paste(sample(x, n, replace=TRUE), collapse=collapse)
}
words <- sapply(rpois(10000, 3) + 1, samplefun, letters, '')
sents1 <- sapply(rpois(1000000, 5) + 1, samplefun, words, ' ')
})
я могу преобразовать эти символьные данные в bag- из следующих слов:
library(stringi)
library(Matrix)
tokens <- stri_split_fixed(sents1, ' ')
token_vector <- unlist(tokens)
bagofwords <- unique(token_vector)
n.ids <- sapply(tokens, length)
i <- rep(seq_along(n.ids), n.ids)
j <- match(token_vector, bagofwords)
M <- sparseMatrix(i=i, j=j, x=1L)
colnames(M) <- bagofwords
Таким образом, R может v ectorize 1,000,000 миллионов коротких предложений в мешок из-слов представления в течение примерно 3 секунд (не плохо!):
> M[1:3, 1:7]
10 x 7 sparse Matrix of class "dgCMatrix"
fqt hqhkl sls lzo xrnh zkuqc mqh
[1,] 1 1 1 1 . . .
[2,] . . . . 1 1 1
[3,] . . . . . . .
я могу бросить эту разреженную матрицу в glmnet или irlba и сделать некоторые довольно удивительный количественный анализ текстовых данных , Ура!
Теперь я хотел бы распространить этот анализ на матрицу мешков, а не на матрицу слов. До сих пор самый быстрый способ я нашел, чтобы сделать это следующим образом (все функции Ngram я смог найти на CRAN подавился этого набора данных, так I got a little help from SO):
find_ngrams <- function(dat, n, verbose=FALSE){
library(pbapply)
stopifnot(is.list(dat))
stopifnot(is.numeric(n))
stopifnot(n>0)
if(n == 1) return(dat)
pblapply(dat, function(y) {
if(length(y)<=1) return(y)
c(y, unlist(lapply(2:n, function(n_i) {
if(n_i > length(y)) return(NULL)
do.call(paste, unname(as.data.frame(embed(rev(y), n_i), stringsAsFactors=FALSE)), quote=FALSE)
})))
})
}
text_to_ngrams <- function(sents, n=2){
library(stringi)
library(Matrix)
tokens <- stri_split_fixed(sents, ' ')
tokens <- find_ngrams(tokens, n=n, verbose=TRUE)
token_vector <- unlist(tokens)
bagofwords <- unique(token_vector)
n.ids <- sapply(tokens, length)
i <- rep(seq_along(n.ids), n.ids)
j <- match(token_vector, bagofwords)
M <- sparseMatrix(i=i, j=j, x=1L)
colnames(M) <- bagofwords
return(M)
}
test1 <- text_to_ngrams(sents1)
Это занимает около 150 секунд (не плохо для чистой функции r), но я бы хотел пойти быстрее и расширить до больших наборов данных.
Есть ли очень быстро функции в R для векторизации текста n-грамм? В идеале я ищу функцию Rcpp, которая принимает вектор символов в качестве входных данных и возвращает разреженную матрицу документов x ngrams в качестве выходных данных, но также будет рада иметь некоторые рекомендации, непосредственно записывающие функцию Rcpp.
Даже более быстрая версия функции find_ngrams
была бы полезна, так как это основное узкое место. R на удивление быстро наступает при токенизации.
Edit 1 Вот еще один пример набор данные:
sents2 <- sapply(rpois(100000, 500) + 1, samplefun, words, ' ')
В этом случае, мои функции для создания сумки-из-слов матрицы занимает около 30 секунд, и моих функции для создания сумки-of ngrams занимает около 500 секунд. Опять же, существующие н-граммовые vectorizers в R, кажется, задушить этот набор данных (хотя я хотел бы быть опровергнуты!)
Edit 2 Timings против тау:
zach_t1 <- system.time(zach_ng1 <- text_to_ngrams(sents1))
tau_t1 <- system.time(tau_ng1 <- tau::textcnt(as.list(sents1), n = 2L, method = "string", recursive = TRUE))
tau_t1/zach_t1 #1.598655
zach_t2 <- system.time(zach_ng2 <- text_to_ngrams(sents2))
tau_t2 <- system.time(tau_ng2 <- tau::textcnt(as.list(sents2), n = 2L, method = "string", recursive = TRUE))
tau_t2/zach_t2 #1.9295619
Хм вы считали «tau :: textcnt (as.list (sents), n = 2L, method =« string », recursive = TRUE) 'вместо' find_ngrams'? Выполняется в течение половины времени, но поставляет только битрамы (n = 2). – lukeA
Я не пробовал это и не буду. Bigrams будет работать, если это быстрее, чем мой код выше для обоих наборов данных. – Zach
@lukeA На обоих наборах данных tau :: textct на моей системе на 50% медленнее. Я обновлю свой вопрос с помощью таймингов и кода примера, попробуйте его в своей системе и сравните результаты. – Zach