我需要一些有关NbClust函数大量使用内存的帮助。
在我的数据上,内存膨胀到56GB,此时R发生致命错误,崩溃了。使用debug()
,我能够将错误跟踪到以下几行:
if (any(indice == 23) || (indice == 32)) {
res[nc - min_nc + 1, 23] <- Index.sPlussMoins(cl1 = cl1,
md = md)$gamma
对Index.sPlussMoins的调试显示,崩溃发生在for循环期间。它崩溃的迭代次数各不相同,并且在循环期间内存使用量在41到57Gb之间(我总共有64Gb):
for (k in 1:nwithin1) {
s.plus <- s.plus + (colSums(outer(between.dist1,
within.dist1[k], ">")))
s.moins <- s.moins + (colSums(outer(between.dist1,
within.dist1[k], "<")))
print(s.moins)
}
我猜测内存使用量来自outer()
函数。
我可以修改NbClust使其具有更高的内存效率吗(也许使用bigmemory包)?
至少,最好让R以“无法分配大小向量...”退出函数而不是崩溃。这样一来,我就会知道处理导致崩溃的矩阵需要多少内存。
编辑:我创建了一个最小的示例,该示例的矩阵近似于我正在使用的矩阵的大小,尽管当调用hclust函数时,它崩溃于另一个点:
set.seed(123)
cluster_means = sample(1:25, 10)
mlist = list()
for(cm in cluster_means){
name = as.character(cm)
m = data.frame(matrix(rnorm(60000*60,mean=cm,sd=runif(1, 0.5, 3.5)), 60000, 60))
mlist[[name]] = m
}
test_data = do.call(cbind, cbind(mlist))
library(NbClust)
debug(fun = "NbClust")
nbc = NbClust(data = test_data, diss = NULL, distance = "euclidean", min.nc = 2, max.nc = 30,
method = "ward.D2", index = "alllong", alphaBeale = 0.1)
debug: hc <- hclust(md, method = "ward.D2")
它似乎在用尽可用内存之前就崩溃了(根据我的系统监视器,当崩溃总数达到64时,正在使用34Gb。
那么,在没有对可管理大小的矩阵进行二次采样的情况下,有什么方法可以做到这一点?如果这样做了,我如何知道给定大小的矩阵需要多少内存?我本以为我的64Gb足够了。
编辑: 我尝试将NbClust更改为使用fastcluster而不是统计信息版本。它没有崩溃,但是退出并出现内存错误:
Browse[2]>
exiting from: fastcluster::hclust(md, method = "ward.D2")
Error: cannot allocate vector of size 9.3 Gb
答案 0 :(得分:1)
如果查看Nbclust的源代码,您会发现它几乎已针对速度或内存效率进行了优化。
您要报告的崩溃甚至不在集群期间-而是在评估之后,尤其是在“ Gamma,Gplus和Tau”索引代码中。 禁用这些索引,您可能会走得更远,但很可能在另一个索引中再次遇到相同的问题。也许您只能选择要运行的几个索引,特别是这样的索引,以至于 不需要很多内存?
答案 1 :(得分:0)
我分叉了NbClust并进行了一些更改,这些更改似乎使它运行了更长的时间,而不会因使用更大的矩阵而崩溃。我更改了一些功能以使用Rfast
,propagate
和fastcluster
。但是仍然存在问题。
我还没有运行我的所有数据,仅使用gap
对虚拟数据进行了一些测试,因此仍然有时间使它失败。但是任何建议/批评都将受到欢迎。
我的NbCluster(正在进行中)分叉:
https://github.com/jbhanks/NbClust