迭代外加法 Numpy
Iterative outer addition Numpy
我想应用多个 vectors/matrices 的外部加法。让我们说四次:
import numpy as np
x = np.arange(100)
B = np.add.outer(x,x)
B = np.add.outer(B,x)
B = np.add.outer(B,x)
我希望加法次数可以是一个变量,例如 a=4
--> 加法的 4 倍。这可能吗?
我认为没有内置参数可以多次重复此过程,但您可以很容易地为其定义自定义函数
def recursive_outer_add(arr, num):
if num == 1:
return arr
x = np.add.outer(arr, arr)
for i in range(num - 1):
x = np.add.outer(x, arr)
return x
作为警告:数组变得非常大非常快
方法 #1
这是一个带有数组初始化的 -
n = 4 # number of iterations to add outer versions
l = len(x)
out = np.zeros([l]*n,dtype=x.dtype)
for i in range(n):
out += x.reshape(np.insert([1]*(n-1),i,l))
为什么使用这种方法而不是迭代添加来在每次迭代时创建新数组?
在每次迭代中迭代地创建新数组将需要更多的内存,因此需要更多的内存开销。通过数组初始化,我们将元素 off x
添加到已经初始化的数组中。因此,它试图通过它来提高内存效率。
选择#1
我们可以通过 x
初始化来删除一次迭代。因此,更改将是 -
out = np.broadcast_to(x,[l]*n).copy()
for i in range(n-1):
方法 # 2:使用 np.add.reduce
-
另一种方法是使用 np.add.reduce
,它同样不会创建任何中间数组,但作为一种缩减方法在这里可能更好,因为它是为 -
实现的
l = len(x); n = 4
np.add.reduce([x.reshape(np.insert([1]*(n-1),i,l)) for i in range(n)])
计时 -
In [17]: x = np.arange(100)
In [18]: %%timeit
...: n = 4 # number of iterations to add outer versions
...: l = len(x)
...: out = np.zeros([l]*n,dtype=x.dtype)
...: for i in range(n):
...: out += x.reshape(np.insert([1]*(n-1),i,l))
829 ms ± 28.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [19]: l = len(x); n = 4
In [20]: %timeit np.add.reduce([x.reshape(np.insert([1]*(n-1),i,l)) for i in range(n)])
183 ms ± 2.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
短且相当快:
n = 4
l = 10
x = np.arange(l)
sum(np.ix_(*n*(x,)))
timeit(lambda:sum(np.ix_(*n*(x,))),number=1000)
# 0.049082988989539444
我们可以回到前面来加快速度:
timeit(lambda:sum(reversed(np.ix_(*n*(x,)))),number=1000)
# 0.03847671199764591
我们也可以构建自己的反转np.ix_
:
from operator import getitem
from itertools import accumulate,chain,repeat
sum(accumulate(chain((x,),repeat((slice(None),None),n-1)),getitem))
timeit(lambda:sum(accumulate(chain((x,),repeat((slice(None),None),n-1)),getitem)),number=1000)
# 0.02427654700295534
我想应用多个 vectors/matrices 的外部加法。让我们说四次:
import numpy as np
x = np.arange(100)
B = np.add.outer(x,x)
B = np.add.outer(B,x)
B = np.add.outer(B,x)
我希望加法次数可以是一个变量,例如 a=4
--> 加法的 4 倍。这可能吗?
我认为没有内置参数可以多次重复此过程,但您可以很容易地为其定义自定义函数
def recursive_outer_add(arr, num):
if num == 1:
return arr
x = np.add.outer(arr, arr)
for i in range(num - 1):
x = np.add.outer(x, arr)
return x
作为警告:数组变得非常大非常快
方法 #1
这是一个带有数组初始化的 -
n = 4 # number of iterations to add outer versions
l = len(x)
out = np.zeros([l]*n,dtype=x.dtype)
for i in range(n):
out += x.reshape(np.insert([1]*(n-1),i,l))
为什么使用这种方法而不是迭代添加来在每次迭代时创建新数组?
在每次迭代中迭代地创建新数组将需要更多的内存,因此需要更多的内存开销。通过数组初始化,我们将元素 off x
添加到已经初始化的数组中。因此,它试图通过它来提高内存效率。
选择#1
我们可以通过 x
初始化来删除一次迭代。因此,更改将是 -
out = np.broadcast_to(x,[l]*n).copy()
for i in range(n-1):
方法 # 2:使用 np.add.reduce
-
另一种方法是使用 np.add.reduce
,它同样不会创建任何中间数组,但作为一种缩减方法在这里可能更好,因为它是为 -
l = len(x); n = 4
np.add.reduce([x.reshape(np.insert([1]*(n-1),i,l)) for i in range(n)])
计时 -
In [17]: x = np.arange(100)
In [18]: %%timeit
...: n = 4 # number of iterations to add outer versions
...: l = len(x)
...: out = np.zeros([l]*n,dtype=x.dtype)
...: for i in range(n):
...: out += x.reshape(np.insert([1]*(n-1),i,l))
829 ms ± 28.1 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In [19]: l = len(x); n = 4
In [20]: %timeit np.add.reduce([x.reshape(np.insert([1]*(n-1),i,l)) for i in range(n)])
183 ms ± 2.52 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
短且相当快:
n = 4
l = 10
x = np.arange(l)
sum(np.ix_(*n*(x,)))
timeit(lambda:sum(np.ix_(*n*(x,))),number=1000)
# 0.049082988989539444
我们可以回到前面来加快速度:
timeit(lambda:sum(reversed(np.ix_(*n*(x,)))),number=1000)
# 0.03847671199764591
我们也可以构建自己的反转np.ix_
:
from operator import getitem
from itertools import accumulate,chain,repeat
sum(accumulate(chain((x,),repeat((slice(None),None),n-1)),getitem))
timeit(lambda:sum(accumulate(chain((x,),repeat((slice(None),None),n-1)),getitem)),number=1000)
# 0.02427654700295534