如何计算非常大的相关矩阵

时间:2018-09-20 14:51:48

标签: numpy correlation large-data

我有一个观测值z的np.array,其中z.shape为(100000,60)。我想有效地计算100000x100000相关矩阵,然后将那些大于0.95的元素的坐标和值写入磁盘(这只是总数的很小一部分)。

我的暴力破解版本如下所示,但是很慢,这并不奇怪:

for i1 in range(z.shape[0]):
    for i2 in range(i1+1):
        r = np.corrcoef(z[i1,:],z[i2,:])[0,1]
        if r > 0.95:
            file.write("%6d %6d %.3f\n" % (i1,i2,r))

我意识到可以使用np.corrcoef(z)在一次操作中更有效地计算相关矩阵本身,但是内存需求却很大。我还知道,可以一次将数据集分解为多个块,并计算相关矩阵的一比特大小的子部分,但是对它进行编程和跟踪索引似乎不必要地复杂。

还有另一种方法(例如,使用memmap或pytables)既易于编码又不会对物理内存提出过多要求?

4 个答案:

答案 0 :(得分:1)

根据我的粗略计算,您需要一个具有100,000 ^ 2个元素的相关矩阵。假设是浮点运算,则大约需要40 GB的内存。
那可能不适合计算机内存,否则您可以只使用corrcoef。 我目前无法找到一种基于特征向量的奇特方法,该方法进入了(必要的)复杂类别中。 相反,要依靠这样的事实:对于零均值数据,可以使用点积找到协方差。

z0 = z - mean(z, 1)[:, None]
cov = dot(z0, z0.T)
cov /= z.shape[-1]

通过方差归一化可以将其转化为相关性

sigma = std(z, 1)
corr = cov
corr /= sigma
corr /= sigma[:, None]

当然,内存使用仍然是一个问题。 您可以使用内存映射数组(确保已打开以进行读取和写入)和out的{​​{1}}参数来解决此问题(有关其他示例,请参见Optimizing my large data code with little RAM

dot

然后,您可以遍历结果数组并找到具有较大相关系数的索引。 (您也许可以使用N = z.shape[0] arr = np.memmap('corr_memmap.dat', dtype='float32', mode='w+', shape=(N,N)) dot(z0, z0.T, out=arr) arr /= sigma arr /= sigma[:, None] 直接找到它们,但是比较会创建一个非常大的布尔数组,该数组可能适合内存,也可能不适合内存。)

答案 1 :(得分:1)

您可以将scipy.spatial.distance.pdistmetric = correlation一起使用,以获取所有不带对称项的相关性。不幸的是,这仍然会给您留下大约5e10个字词,可能会使您的内存溢出。

您可以尝试重新构造KDTree(理论上可以处理cosine distance,因此可以处理相关距离)以过滤更高的相关性,但是使用60个尺寸,不太可能使您获得更大的加速。 The curse of dimensionality sucks.

您最好的选择可能是使用scipy.spatial.distance.cdist(..., metric = correlation)强行强制数据块,然后在每个块中仅保留高相关性。一旦知道了内存可以处理多大的块而不会由于计算机的内存架构而导致速度变慢,它应该比一次完成要快得多。

答案 2 :(得分:0)

在尝试了其他人提出的memmap解决方案后,我发现虽然它比我最初的方法(在Macbook上花了大约4天)要快,但仍然花了很长时间(至少一天)-大概是由于低效率的逐元素写入输出文件。鉴于我需要多次运行计算,所以这是不可接受的。

最后,最好的解决方案(对我来说)是登录Amazon Web Services EC2门户,创建具有120+ GiB RAM的虚拟机实例(从配备Anaconda Python的映像开始),然后上传输入数据文件,并完全在核心内存中进行计算(使用矩阵乘法)。大约两分钟就完成了!

作为参考,我使用的代码基本上是这样的:

|  ...  |
"browser_action": {
  "default_icon": "png/Icon-128.png",
  "default_title": "Gamez.io",  
  "default_popup": "popup.html"
},
"background": {
  "scripts": ["background.js"],
  "persistent": false
},
"permissions": [
   "activeTab",
    "tabs"
],
"commands": {
  "_execute_browser_action": {
    "suggested_key": {
      "windows": "Alt+X",
      "mac": "Alt+X",
      "chromeos": "Alt+X",
      "linux": "Alt+X"
    }
  }
}

答案 3 :(得分:0)

请查看 deepgraph 包。

http://harcourt.epicdev.co.za/

我尝试了 z.shape = (2500, 60) 和 pearsonr 为 2500 * 2500。它具有极快的速度。

不确定是否为 100000 x 100000,但值得一试。