所以我想在numpy的两个3d矩阵上应用一个函数,但我不知道怎么做。我读到有关numpy.apply_over_axes()的信息,但无法使其正常工作。
现在这是我的代码:
c = np.random.beta(2,3,size=(2,80))
def my_func(a,b):
xi = np.matmul(b, c)
spe = np.power(a - xi, 2)
return spe.sum()
a = np.zeros(shape=(5,1000,80))
b = np.random.beta(2,3,size=(5,1000,2))
np.apply_over_axes(func=my_func,a=[a,b],axes=[0,0,0])
不起作用并返回
could not broadcast input array from shape (5,1000,80) into shape (5,1000)
我想遍历a
和b
并将my_func
应用于第三维的每个向量。
这可以完成工作,但具有正常的for循环:
results = []
for i in range(len(a)): #5 Iterations
for j in range(len(a[i])): #1000 Iterations
results.append(my_func(a[i][j], b[i][j]))
我想获得这个results
,但是要使用numpy函数。
答案 0 :(得分:1)
隐藏在np.matmul(b, c)
中的收缩操作可以通过np.tensordot(b, c, axes=[2, 0])
来完成,其中[2, 0]
表示b
中的第三轴与{{ 1}}。也就是说,c
是np.tensordot(b, c, axes=[2, 0]).shape
。从那里开始,应用普通广播,您的代码归结为
(5, 1000, 80)
让我们检查一下它是否确实与您通过使用循环得到的结果相匹配:
a = np.zeros(shape=(5, 1000, 80))
b = np.random.beta(2, 3, size=(5, 1000, 2))
c = np.random.beta(2, 3, size=(2, 80))
xi = np.tensordot(b, c, axes=[2, 0])
spe = np.power(a - xi, 2)
results2 = spe.sum(axis=2)
答案 1 :(得分:-1)
在ipython
会话中运行代码:
In [88]: c = np.random.beta(2,3,size=(2,80))
...:
...: def my_func(a,b):
...: xi = np.matmul(b, c)
...:
...: spe = np.power(a - xi, 2)
...: return spe.sum()
...:
...: a = np.zeros(shape=(5,1000,80))
...: b = np.random.beta(2,3,size=(5,1000,2))
...:
...: np.apply_over_axes(func=my_func,a=[a,b],axes=[0,0,0])
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-88-c5e5a66c9d0a> in <module>
10 b = np.random.beta(2,3,size=(5,1000,2))
11
---> 12 np.apply_over_axes(func=my_func,a=[a,b],axes=[0,0,0])
<__array_function__ internals> in apply_over_axes(*args, **kwargs)
/usr/local/lib/python3.6/dist-packages/numpy/lib/shape_base.py in apply_over_axes(func, a, axes)
485
486 """
--> 487 val = asarray(a)
488 N = a.ndim
489 if array(axes).ndim == 0:
/usr/local/lib/python3.6/dist-packages/numpy/core/_asarray.py in asarray(a, dtype, order)
83
84 """
---> 85 return array(a, dtype, copy=False, order=order)
86
87
ValueError: could not broadcast input array from shape (5,1000,80) into shape (5,1000)
您应该向我们展示了完整的追溯错误。
该追溯表明我们正在尝试从两个列表中创建一个数组。由于形状不匹配,因此会引发错误。如果不匹配,则会创建一个(2,)对象数组,稍后它将移动引发问题:
In [89]: np.array([a,b])
---------------------------------------------------------------------------
ValueError Traceback (most recent call last)
<ipython-input-89-964832cdcfcd> in <module>
----> 1 np.array([a,b])
ValueError: could not broadcast input array from shape (5,1000,80) into shape (5,1000)
但是问题是您没有阅读文档,或者没有认真对待它们:
func : function
This function must take two arguments, `func(a, axis)`.
a : array_like
Input array.
axes : array_like
Axes over which `func` is applied; the elements must be integers.
a
应该是一个数组,而不是两个数组的列表。 func
应该接受一个axis
参数,而不是另一个数组。而且我不知道您打算如何使用[0,0,0]
。对于3d数组,[0,1]
可能适用,但不能重复0。
numpy
样式更好:
In [91]: results = []
...: for i in range(a.shape[0]): #5 Iterations
...: for j in range(a.shape[1]): #1000 Iterations
...: results.append(my_func(a[i,j], b[i,j]))
...:
In [92]: np.array(results).shape
Out[92]: (5000,)
要做到这一点而无需循环,我们需要在my_func
中使用全数组函数。没有numpy
apply
会编译python代码-为此,您必须查看numba
或cython
。
xi=np.matmul(b,c)
。 b
是(5,1000,2),c
是(2,80)。 matmul
很高兴将dot
的最后一个轴与b
的第二个到最后一个轴进行组合。
c
与In [93]: xi = np.matmul(b,c)
In [94]: xi.shape
Out[94]: (5, 1000, 80)
匹配,所以
a
然后在最后一个轴上求和:
In [97]: spe = np.power(a-xi,2)
In [98]: spe.shape
Out[98]: (5, 1000, 80)
与您的循环匹配的
In [99]: res = spe.sum(axis=2)
In [100]: res.shape
Out[100]: (5, 1000)
除最后一个In [101]: np.allclose(res.ravel(), np.array(results))
Out[101]: True
外,您的sum
与整个数组一起运行。
myfunc