【问题标题】:Large distance matrix in clustering聚类中的大距离矩阵
【发布时间】:2016-03-20 19:02:12
【问题描述】:

我在具有 16 GB RAM 的机器上运行 R 3.2.3。我有一个 3,00,000 行 x 12 列的大矩阵。我想在 R 中使用层次聚类算法,所以在我这样做之前,我正在尝试创建一个距离矩阵。由于数据是混合类型的,我对不同的类型使用不同的矩阵。我收到有关内存分配的错误:

df <- as.data.frame(matrix(rnorm(36*10^5), nrow = 3*10^5))
d1=as.dist(distm(df[,c(1:2)])/10^5)
d2=dist(df[,c(3:8)], method = "euclidean") 
d3= hamming.distance(df[,c(9:12)]%>%as.matrix(.))%>%as.dist(.)

我收到以下错误

> d1=as.dist(distm(df1[,c(1:2)])/10^5)
Error: cannot allocate vector of size 670.6 Gb
In addition: Warning messages:
1: In matrix(0, ncol = n, nrow = n) :
Reached total allocation of 16070Mb: see help(memory.size)
2: In matrix(0, ncol = n, nrow = n) :
Reached total allocation of 16070Mb: see help(memory.size)
3: In matrix(0, ncol = n, nrow = n) :
Reached total allocation of 16070Mb: see help(memory.size)
4: In matrix(0, ncol = n, nrow = n) :
Reached total allocation of 16070Mb: see help(memory.size)
> d2=dist(df1[,c(3:8)], method = "euclidean") 
Error: cannot allocate vector of size 335.3 Gb
In addition: Warning messages:
1: In dist(df1[, c(3:8)], method = "euclidean") :
 Reached total allocation of 16070Mb: see help(memory.size)
2: In dist(df1[, c(3:8)], method = "euclidean") :
Reached total allocation of 16070Mb: see help(memory.size)
3: In dist(df1[, c(3:8)], method = "euclidean") :
Reached total allocation of 16070Mb: see help(memory.size)
4: In dist(df1[, c(3:8)], method = "euclidean") :
Reached total allocation of 16070Mb: see help(memory.size)
> d3= hamming.distance(df1[,c(9:12)]%>%as.matrix(.))%>%as.dist(.)
Error: cannot allocate vector of size 670.6 Gb
In addition: Warning messages:
1: In matrix(0, nrow = nrow(x), ncol = nrow(x)) :
Reached total allocation of 16070Mb: see help(memory.size)
2: In matrix(0, nrow = nrow(x), ncol = nrow(x)) :
Reached total allocation of 16070Mb: see help(memory.size)
3: In matrix(0, nrow = nrow(x), ncol = nrow(x)) :
Reached total allocation of 16070Mb: see help(memory.size)
4: In matrix(0, nrow = nrow(x), ncol = nrow(x)) :
Reached total allocation of 16070Mb: see help(memory.size)

【问题讨论】:

  • 您不需要一起处理所有数据,这将消耗您的所有内存并出错。考虑逐批处理它们,例如每次 10000 个向量。
  • 但是在聚类中,我们需要计算一行到所有其他行的距离。那么批量计算在这里有什么帮助呢?
  • 是的,但您可以进行最终缩减以选择最小/最大值。这有意义吗?高效计算距离可以参考here
  • 通过选择最小/最大减少??对不起,我不明白。更详细的见解可能会有所帮助。
  • 更新一个答案,因为我需要多写几个字,你清楚吗?谢谢。

标签: r matrix distance hierarchical-clustering


【解决方案1】:

为简单起见,假设您有 1 行 (A) 以最小距离与 3^8 矩阵 (B) 进行聚类。

原来的做法是:

1. load A and B
2. distance compute A with each row of B
3. select smallest one from results (reduction)

但是因为B真的很大,所以不能加载到内存或者执行过程中报错。

批处理方法将如下所示:

1. load A (suppose it is small)
2. load B.partial with 1 to 1^5 rows of B
3. compute distance of A with each row of B.partial
4. select min one in partial results and save it as res[i]
5. go back 2.) load next 1^5 rows of B 
6. final your got a 3000 partial results and saved in res[1:3000]
7. reduction : select min one from res[1:3000]
   note: if you need all distances as `dist` function, you don't need reduction and just keep this array.

代码会比原来的要复杂一些。但是当我们处理大数据问题时,这是非常常见的技巧。对于计算部分,您可以参考我之前在here 中的答案之一。

如果您可以在此处粘贴带有批处理模式的最终代码,我将非常合适。以便其他人也可以学习。


另一个有趣的事情 dist 是R 包中支持openMP 的少数几个。查看here 中的源代码以及here 中如何使用openMP 进行编译。

所以,如果您可以尝试根据您的机器将OMP_NUM_THREADS 设置为 4 或 8,然后再次运行,您可以看到性能提升很多!

 void R_distance(double *x, int *nr, int *nc, double *d, int *diag,
    int *method, double *p)
{
     int dc, i, j;
     size_t  ij;  /* can exceed 2^31 - 1 */
     double (*distfun)(double*, int, int, int, int) = NULL;
     #ifdef _OPENMP
        int nthreads;
     #endif
     .....
 }

另外,如果你想通过GPU加速dist,可以参考ParallelR中的talk部分。

【讨论】:

    猜你喜欢
    • 2015-04-21
    • 2012-09-05
    • 1970-01-01
    • 2013-04-21
    • 2014-07-28
    • 2019-02-05
    • 2011-04-13
    • 2014-10-24
    • 2016-08-21
    相关资源
    最近更新 更多