У меня есть функция foo
это берет массив NxM numpy в качестве аргумента и возвращает скалярное значение. У меня есть массив AxNxM numpy data
, по которому я хотел бы отобразиться foo
дать мне результант numpy массив длины A.
Curently, я делаю это:
result = numpy.array([foo(x) for x in data])
Это работает, но кажется, что я не использую в своих интересах numpy волшебство (и скорость). Существует ли лучший путь?
Я посмотрел на numpy.vectorize
, и numpy.apply_along_axis
, но никакой работы для функции 2D массивов.
Править: Я делаю повышенную регрессию на 24x24 патчи изображения, таким образом, мой AxNxM - что-то как 1000x24x24. Что я назвал foo
выше применяет подобную Хаару функцию к патчу (так, не ужасно в вычислительном отношении интенсивный).
Если NxM велико (скажем, 100), то затраты на итерации над A будут амортизированы практически в ничто.
Скажем, массив имеет размер 1000 X 100 X 100.
Итерация - O(1000), но совокупная стоимость внутренней функции - O(1000 X 100 X 100) - в 10 000 раз медленнее. (Обратите внимание, моя терминология немного корявая, но я знаю, о чем говорю)
Я не уверен, но вы можете попробовать следующее:
result = numpy.empty(data.shape[0])
for i in range(len(data)):
result[i] = foo(data[i])
Вы сэкономите большое количество памяти на построении списка... но накладные расходы цикла будут больше.
Или вы можете написать параллельную версию цикла и разделить его на несколько процессов. Это может быть намного быстрее, в зависимости от того, насколько интенсивным является foo
(поскольку придется компенсировать обработку данных).
Вы можете добиться этого, преобразовав свой 3D-массив в 2D-массив с тем же начальным размером и обернув вашу функцию foo
функцией, которая работает с 1D-массивами, изменив их форму в соответствии с требованиями foo
. Пример (с использованием trace
вместо foo
):
from numpy import *
def apply2d_along_first(func2d, arr3d):
a, n, m = arr3d.shape
def func1d(arr1d):
return func2d(arr1d.reshape((n,m)))
arr2d = arr3d.reshape((a,n*m))
return apply_along_axis(func1d, -1, arr2d)
A, N, M = 3, 4, 5
data = arange(A*N*M).reshape((A,N,M))
print data
print apply2d_along_first(trace, data)
Вывод:
[[[ 0 1 2 3 4]
[ 5 6 7 8 9]
[10 11 12 13 14]
[15 16 17 18 19]]
[[20 21 22 23 24]
[25 26 27 28 29]
[30 31 32 33 34]
[35 36 37 38 39]]
[[40 41 42 43 44]
[45 46 47 48 49]
[50 51 52 53 54]
[55 56 57 58 59]]]
[ 36 116 196]