Запуск вашего кода в сеансе 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]
. Для трехмерных массивов [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,)
rework my_func
Чтобы сделать это без циклов, нам нужно использовать функции целого массива в my_func
. Не существует numpy
apply
, который компилирует код Python - для этого нужно посмотреть numba
или cython
.
xi=np.matmul(b,c)
. b
- (5,1000,2), c
- (2,80). matmul
счастлив делать dot
, объединяя последнюю ось b
со 2-ой по последнюю из 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
работает с целыммассивы.
In [103]: my_func(a,b)
Out[103]: 46883.49325596101