我有许多矩阵要添加。假设矩阵是[M1,M2 ...,M_n]。然后,一个简单的办法就是numpy矩阵加法的有效方法
X = np.zeros()
for M in matrices:
X += M
在操作上,X + = M,并Python中创建一个新的内存X每次+ =执行?如果是这样的话,那似乎是低效的。在没有为X创建新内存的情况下进行就地操作有什么方法吗?
我有许多矩阵要添加。假设矩阵是[M1,M2 ...,M_n]。然后,一个简单的办法就是numpy矩阵加法的有效方法
X = np.zeros()
for M in matrices:
X += M
在操作上,X + = M,并Python中创建一个新的内存X每次+ =执行?如果是这样的话,那似乎是低效的。在没有为X创建新内存的情况下进行就地操作有什么方法吗?
这工作,但不是我的机器上更快:
numpy.sum(matrices, axis=0)
除非你得到的MemoryError,试图第二次猜测内存使用numpy的是不值得的。将其留给知道编译代码的开发人员。
但是我们可以执行一些时间测试 - 这才是真正重要的,不是吗?
我会测试添加一个好的大小数组100次。
In [479]: M=np.ones((1000,1000))
您与+ =
In [480]: %%timeit
...: X=np.zeros_like(M)
...: for _ in range(100): X+=M
...:
1 loop, best of 3: 627 ms per loop
或者使尺寸的阵列(100,1000,1000),并应用np.sum
跨过第一轴线迭代方法。
In [481]: timeit np.sum(np.array([M for _ in range(100)]),axis=0)
1 loop, best of 3: 1.54 s per loop
并使用np.add
ufunc。通过reduce
,我们可以将它依次应用于列表中的所有值。
In [482]: timeit np.add.reduce([M for _ in range(100)])
1 loop, best of 3: 1.53 s per loop
的np.sum
情况下给我的MemoryError如果我使用range(1000)
。我没有足够的内存来存放(1000,1000,1000)数组。 add.reduce
相同,从列表中构建一个数组。
+=
什么+=
在掩护下通常是隐藏的,并且我们通常不关心。但对于下盖峰看ufunc.at
:https://docs.scipy.org/doc/numpy/reference/generated/numpy.ufunc.at.html#numpy.ufunc.at
上执行操作到位操作无缓冲“A”由“指数”指定的元素。对于另外的ufunc,这个方法等同于[indices] + = b,除了对索引多于一次的元素累计结果。
因此X+=M
会将总和写入缓冲区,然后将该缓冲区复制到X
。有一个临时缓冲区,但最终的内存使用情况不会改变。 但是,该缓冲区的创建和复制是在快速C代码中完成的。
np.add.at
被添加来处理缓冲动作产生一些问题(重复索引)的情况。
因此,它避免了临时缓冲区 - 但速度相当快。这可能是增加的索引功能会降低速度。 (可能有更公平的add.at
测试;但在这种情况下肯定无济于事。)
In [491]: %%timeit
...: X=np.zeros_like(M)
...: for _ in range(100): np.add.at(X,(slice(None),slice(None)),M)
1 loop, best of 3: 19.8 s per loop
你究竟做了什么:'[M1,M2 ...,M_n]'?它是一个数组列表吗?添加一个样本? – Divakar
@Divakar我认为这是一个矩阵列表。 – TuanDT
@Divakar,M是np.ndarray。 – DSKim