Python 迭代外加法

Python 迭代外加法,python,numpy,addition,Python,Numpy,Addition,我想应用多个向量/矩阵的外部加法。让我们说四次: 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递归外部添加(arr,num): 如果num==1: 返

我想应用多个向量/矩阵的外部加法。让我们说四次:

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递归外部添加(arr,num):
如果num==1:
返回arr
x=np.添加外部(arr,arr)
对于范围内的i(num-1):
x=np.add.outer(x,arr)
返回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:With
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\uu

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

简单的循环有什么问题?通过广播,你可以做到:
x[:,None,None]+x[None,:,None]+x
,但将其推广到
a
次将是更多的工作。@hpaulj我认为可能是其他方式。