R功能慢,希望提高速度/性能

时间:2015-07-27 12:35:47

标签: r

我在R中构建了一个预测函数,但是当我运行它非常慢时,我只使用了我将在生产中使用的1%数据样本。该函数用于预测给定一系列ngrams(从我的语料库创建的两个单词,三个单词或四个单词组合)的下一个单词。

我将这些单词传递给函数,例如“我可以”,以及一系列三字组合。按顺序排列的输出将是“我能读”,数为4.

这里传递的双字ngram是一个矩阵,dim和示例数据来自位置100。

 dim(bigram_index)
 [1] 46201  3 
 bigram_index[,1][100]
 [1] "abandon"
 bigram_index[,2][100]
 [1] "contemporary"
 bigram_index[,3][100]
 [1] "1"

这是预测函数:

predict.next.word <- function(word, ng_matrix){
ngram_df <- data.frame(predicted=character(), count = numeric(), stringsAsFactors=FALSE)
    col_ng_matrix <- nrow(bigram_index)
if(ncol(ng_matrix)==3){
        for (i in 1:col_ng_matrix){
        first_word <- ng_matrix[,1][i]
        second_word <- ng_matrix[,2][i]
        count_word <- ng_matrix[,3][i]
        if (word[1] == first_word && !is.na(first_word)){
            matched_factor <- structure(c(second_word, count_word), .Names = c("predicted", "count"))
            ngram_df[i,] <- as.list(matched_factor)
            }
        }  
    }  else if(ncol(ng_matrix)==4){
        for (i in 1:col_ng_matrix){
            first_word <- ng_matrix[,1][i]
            second_word <- ng_matrix[,2][i]
            third_word <- ng_matrix[,3][i]
            count_word <- ng_matrix[,4][i]
            if (word[1] == first_word && !is.na(first_word) && word[2] == second_word && !is.na(second_word)){
                matched_factor <- structure(c(third_word, count_word), .Names = c("predicted", "count"))
                ngram_df[i,] <- as.list(matched_factor)
                } 
            } 
        }  else if(ncol(ng_matrix)==5){
        for (i in 1:col_ng_matrix){
                first_word <- ng_matrix[,1][i]
                second_word <- ng_matrix[,2][i]
                third_word <- ng_matrix[,3][i]
                fourth_word <- ng_matrix[,4][i]
                count_word <- ng_matrix[,5][i]
                if (word[1] == first_word && !is.na(first_word) && word[2] == second_word 
                    && !is.na(second_word) && word[3] == third_word && !is.na(third_word)){
                    ngram_df[i,] <- as.list(matched_factor)
                    } 
                } 
            }
ngram_df <- transform(ngram_df, count = as.numeric(count))
return (ngram_df[order(ngram_df$count, decreasing = TRUE),])  
}

这里使用最小的ngram(只有两个字)是时间结果:

system.time(predict.next.word(c("abandon"), bigram_index))
user  system elapsed 
92.125  59.395 152.149 

同样,再次传递的ngram只占生产数据的1%,当我进入三字和四字时,需要更长的时间。请提供您如何提高此功能的速度的见解。

1 个答案:

答案 0 :(得分:0)

我不是循环遍历列,而是编写一个执行for()循环键操作的函数,并使用apply()MARGIN=2表示列,1表示行; I认为你将使用后者)将该函数应用于每一列(FUN=参数集等于你的函数)。根据输出格式,apply可能不合适。此时,您可以查看plyr包,dplyr或我最喜欢的(但有点学习曲线,dplyr} data.table包。

一般情况下,请查看Hadley关于该主题的书籍章节:http://adv-r.had.co.nz/Performance.html

目前,你的代码没有利用这样一个事实,即所谓的“矢量化”R代码在C中执行循环,使它们更快(请原谅我,如果这种描述在技术上是不正确的;只是把想法推到一边)。

对于更具体的示例,查看输入(使用dput(data))和所需输出可能会有所帮助。然后我会更容易消化你想要的功能。

一些可以帮助的一般性观点,至少有一点:

  1. 你多次ncol(ng_matrix)次;相反,在开始时做nc.ngm < - ncol(ng_matrix)一次。节省的费用很少,但这个想法仍然有用。
  2. 不要定义first_word秒等,而是执行words <- ng_matrix[i,]之类的操作。然后使用前面提到的对象通过count_word获取count_word <- words[nc.ngm],并将其他单词作为numbered_words <- words[nc.ngm]。要将word对象元素与words元素进行比较,您甚至可以使用mapply来获取逻辑。同样,如果没有一个例子,这有点难以理解。但总的来说,做“散装”(矢量化)。