【发布时间】:2020-06-22 19:29:51
【问题描述】:
这是基于我之前的问题Replacing for loops with function call inside with broadcasting/vectorized solution,但更复杂,额外的复杂性让我不知所措。
这里有一些类似的帖子,但是,在阅读了他们的问题的解决方案后,我无法解决我的问题:
Broadcasting function calls in np arrays
Broadcasting a function call to a a 3D array in python
Broadcasting a python function onto np arrays
这里是 MWE
def OneD(x, y, z, r_1, r_2):
ret = 0.0
for i in range(x+1):
for j in range(y+1):
m = i + j
if m % 2 == 0:
ret += np.exp(i+r_1)**(j+1) / (z+1+r_2)
return ret
def ThreeD(a,b,c, d, e):
value = OneD(a[0],b[0], c, d[0], e[0])
value *= OneD(a[1],b[1], c, d[1], e[1])
value *= OneD(a[2],b[2], c, d[2], e[2])
return value
M1 = M2 = np.array(([[0,0,0],[0,0,1], [1,1,1], [1,0,2]]), dtype=int)
scales0 = scales1 = np.array([1.1, 2.2, 3.3, 4.4])
cc0 = cc1 = cc2 =1.77 # for simplicity, all constants made the same
r1 = np.array([0.0,0.0,0.0])
r2 = r1 + 1.0
results = np.zeros((4,4))
for s0, n0, in enumerate(M1):
for s1, n1, in enumerate(M2):
v = ThreeD(n0, n1, cc2, r1, r2)
v *= cc0 * cc1 * scales0[s0] * scales1[s1]
results[s0, s1] += v
类似于为start 链接的更简单问题创建的矢量化/广播版本,我试图摆脱for loops 并通过对函数OneD 执行矢量化调用来加快计算速度
v = np.prod(OneD(M1[:,None,:], M2[None,:,:], np.arange(4)[None,:,None], r1, r2), axis=2)
results = v * cc0*cc1*np.array(scales0)[:,None]*np.array(scales1)[None,:]
我遇到的问题是,现在,当使用OneD 时,没有传递标量,而是出现了数组。这告诉我我需要进一步填充数组(也许增加二维?)?我正在努力正确填充数组。我想我需要让数组有更多的维度,然后再挤压它们,但我不清楚如何做到这一点。我的无数次尝试都错了,并且总是不断将数组发送到OneD。对于此示例,我需要以 (4,4) 数组结尾。
[[ 7.07469713e-02 1.41493943e-01 2.12240914e-01 5.65975771e-01]
[ 1.41493943e-01 2.37400124e+00 3.56100187e+00 5.31397826e+00]
[ 2.12240914e-01 3.56100187e+00 3.75915002e+02 6.68688926e+01]
[ 2.37400124e+00 8.93002921e+00 1.12371774e+02 3.99028687e+03]]
【问题讨论】:
-
在我之前的回答中,您的
OneD使用了数组。只需np.exp(x)**(y+1) / (z+1)。您需要专注于以类似的方式编写这个新的OneD。 -
我认为它已经被矢量化了。我发送到
ThreeD的每个变量都是长度为 3 的向量,但 1 个变量是标量除外。所以我应该能够跳过ThreeD并使用矢量化OneD -
使用之前的
OneD,您可以将数组a等传递给OneD。这会引发错误,因为range(x+1)需要一个标量x。如果给定数组,if也会引发错误。 -
@hpaulj 我不介意您对我的解决方案的意见。我想我成功了:)
标签: python python-3.x numpy vectorization array-broadcasting