【问题标题】:performance issue for loop in RR中循环的性能问题
【发布时间】:2013-09-22 05:48:10
【问题描述】:

我有两个矩阵 A 和 B。两者都包含一个名称列表。问题基于相似性度量。我找到 A 的元素与 B(整个矩阵)的最小距离。如果汉明距离更大大于 3 ,则将数据添加到矩阵 B 中,否则不添加。那我给你举个例子吧

 A<-c("cvombiflam","combiflam")
 A<-as.matrix(A)

 B<-c("windfall","computer","baseball")
 B<-as.matrix(B)

现在 A1 将搜索 B 并找到 B 中关于汉明距离最近的成员。最近的是 B2。它将找到与 B[2] 的距离。由于最近距离大于 3,因此将 cvomiflam 添加到 B。现在 B 将是

 B<-c("windfall",
      "computer",
      "baseball",
      "cvombiflam")

现在 A("combiflam") 的第二个元素将搜索 B。最接近的是 B 的第四个元素 (cvombiflam ),距离为 1。因此 combiflam 不会添加到 B 中。我希望更新最终的 B 列表

我写的代码是:

 for(i in 1:length(A))
 {    
      d<-min(stringdistmatrix(A[i],B)
      if(d>3)
      {            
           B<-rbind(B,A[i])
      }
 }   

现在我有大约 140,000 的矩阵和 200,000 的 B。代码运行良好,但运行需要很长时间。请告诉我一个更快的方法来做到这一点。

【问题讨论】:

  • 你不小心重复了这个吗?这是另一个:stackoverflow.com/questions/18940635/…
  • 是的,但我刚刚标记了另一个帖子以将其删除
  • strindist 可以利用多个内核(如果可用)。
  • 嗨,Ricardo,请您澄清一下
  • 请务必提及任何使用过的软件包,这里是stringdist。此外,您提到了汉明距离,但似乎 stringdistmatrix 函数中使用的默认距离是 osa: Optimal string aligment, (restricted Damerau-Levenshtein distance).

标签: r performance for-loop matrix distance


【解决方案1】:

您可以只存储和更新TRUEFALSE 的向量,指示A 的元素是否应该是否添加到B。然后,仅在最后,将这些选定的元素附加到B

要注意的另一件事是,当您只需要向量时,您在任何地方都使用矩阵。我为你解决了这个问题。

A <- as.vector(A)
B <- as.vector(B)

add.A <- rep(FALSE, length(A))

for(i in 1:length(A)) {
  if (i %% 1000L == 0L) cat(sprintf("%.2f percent completed", 100 * i / length(A)))
  d.B <- stringdist(A[i], B)
  d.A <- stringdist(A[i], A[add.A])
  d <- min(c(d.B, d.A))
  if (d > 3) {            
    add.A[i] <- TRUE
  }
}

B <- c(B, A[add.A])

正在解决的问题,您的问题规模仍然很大。需要计算很多距离(至少length(A) * length(B)),这将花费很多时间。我在循环中添加了cat,让您了解它运行需要多长时间。请试一试并评论它有多慢或多快。

另外,如果 AB 有共同的项目,您最初可以通过以下方式减少问题维度:

A <- unique(A)
B <- unique(B)
A <- setdiff(A, B)

【讨论】:

  • 我需要迭代增长B,然后与A检查
  • @user2678307。如果你仔细阅读我的代码,在每一步,A 中的当前元素都会与B 中的所有元素以及迄今为止从A 中选择的所有元素进行比较。换句话说,我完全复制了你的算法,除了以更有效的方式。
【解决方案2】:

您的代码建议您迭代地增长对象B (B = rbind(B, A[i])。这非常慢,因为B 的内存大小要求不断增长。不断扩展B 内存需要很长时间,导致循环变得非常慢。你可以做一些事情来解决这个问题:

  • 在循环之前将B 预分配到正确的大小并填充到循环中。
  • 使用apply 样式循环,并在最后使用rbind

    list_of_results = lapply(A, stringdistmatrix, b = B)
    big_data_frame = do.call('rbind', list_of_results)
    

加快计算速度的其他选项:

  • 使用多个内核,请参阅 ncores 参数到 stringdistmatrix
  • 用不同的距离度量(method 参数)进行实验,看看这是否会产生影响。

【讨论】:

  • 看他的问题大小,一次计算所有距离会炸毁内存使用...
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-09-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多