【问题标题】:Numpy dot product of very large arrays非常大的数组的 Numpy 点积
【发布时间】:2018-02-08 13:17:33
【问题描述】:

我遇到了代码运行速度非常慢的问题。尝试通过转置计算非常大的二进制矩阵 (170544 X 22) 的点积。 首先我尝试了这段代码

import numpy as np
start = time.time()
import warnings
warnings.filterwarnings("ignore", message='genfromtxt',     category=UserWarning)
np.set_printoptions(threshold=np.nan)

fin = open('E:/myscripts/Abin.txt', 'rb')    # input file (170544X22     binary matrix)
fin1 = open('E:/myscripts/AbinT.txt', 'rb')    # input file (22X170544        binary matrix the transpose of Abin)
fout = open('E:/myscripts/RPartial.txt', 'w+b')  # output file

FW = np.genfromtxt(fin,delimiter=',',   dtype=int)
WF = np.genfromtxt(fin1,delimiter=',',   dtype=int)

r = np.dot(FW,WF) #r calculation
np.savetxt(fout, r,  fmt='%i' ,delimiter=',', newline='\r\n')

fin.close()
fin1.close()
fout.close() 

但出现内存错误。然后我使用行方法更改了 r 计算:

for row in FW:
    a=FW[row,:]
    r = np.dot(a,WF)
    np.savetxt(fout, r,  fmt='%i' ,delimiter=',', newline='\r\n')

代码现在可以运行了,但是速度很慢,90 分钟后只计算了 8000 行。 硬件是具有 12GB 内存的 I7,运行 Windows 64 位。 怎样才能加快代码速度?

数据是这样的

([1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,0,0,0],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,1,0,0,0,0,0,0],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,1,0,0,0,0,0],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,1,0,0,0,0],
 [1,1,1,1,1,1,1,1,1,1,1,1,1,1,0,0,0,0,1,0,0,0])

结果应该是这样的

([15,14,14,14,14],
 [14,15,14,14,14],
 [14,14,15,14,14],
 [14,14,14,15,14],
 [14,14,14,14,15]) .

【问题讨论】:

  • 使用行方法计算结果需要 460s (int) 或 129s (float32)。您真正的问题是数据 IO。为什么使用文本文件来保存和加载数据?在处理更大的数据时,应该绝对避免这种情况......(非常慢,非常大的文件)
  • 您的输出大小约为 232 GB(密集矩阵,未压缩的 int64)。之后还请添加您不想对数据做的事情...
  • 我尝试将数据保存为 npy 文件。再次返回内存错误。在这个计算之后,我将按行总结结果。

标签: python numpy


【解决方案1】:

这听起来像是一个sparse matrix 问题,scipy 提供了一个package。这些是具有许多 0 元素的矩阵(如您的示例中)。运算将考虑稀疏性,矩阵将占用更少的内存空间。记得做矩阵运算,比如FW.dot(WF)(使用这个而不是np.dot)。

【讨论】:

  • 样本中零的比例不高。
  • 是的...有些列全为零,在任何情况下大块都为零。 scipy 包可以处理这些。
  • 稀疏矩阵在稀疏度约为 10% 或更少时很有用。
  • 当然,但是向右和向下扩展该样本(我假设矩阵的左上角)......你得到了什么?无论如何,如果没有我们不知道的完整数据。
  • 数据行有 40% 到 50% 的零。
【解决方案2】:

正如我在 cmets 中所写的,输出数组的大小为 232GB(int64)。如果您不想为此任务使用 h5py 将结果存储到磁盘将是一个合适的解决方案。

关于第一个轴的求和稍微简化了问题。如果您不想要纯点积,我可以更新我的答案。但这会有点复杂和慢。

res=np.zeros(WF.shape[1])
for i in range(WF.shape[1]):
  a=np.copy(WF[:,i])
  r=np.dot(FW,a)
  res[i] = np.sum(r)

【讨论】:

  • 点积数组的每个元素
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-10-05
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-06-15
  • 1970-01-01
相关资源
最近更新 更多