apply_along_axis с 2 аргументами, различающимися для каждого 1d среза - PullRequest
0 голосов
/ 27 февраля 2020

Я пытаюсь оптимизировать код, который в настоящее время использует вложенные для циклов и вызова функций Сципи.

По сути, у меня есть первая функция, которая вызывает методы Сиппи find_peaks (), а затем я хочу интерполировать эти данные точки (пик), чтобы найти функцию, которая описывает их. Например, я сначала нахожу пик. В основном это двумерный массив измерения 25 * 30 (ось 0) с 1000 элементами в каждом (ось 1).

arr = np.random.rand(25,30,1000)
arr = arr.reshape((arr.shape[0]*arr.shape[1], arr.shape[2]))
# we have a 25*30 set of 1000 pts each. find peaks for that
peaks = np.apply_along_axis(find_peaks, 1, arr, height=0,)

Функция Find peaks возвращает что-то в форме:

peak_indices = peaks[:,0]
peak_values = peaks[:,1]["peak_heights"]

Все идет нормально. По сути, это координаты (x, y) точек, которые я хочу интерполировать.

Теперь я хочу интерполировать эти пары значений indices-heights, чтобы получить некоторую функцию, используя scipy.interpolate.interpolate.interp1d ( ...). Подпись Interp1d имеет вид:

interp1d(x, y, kind='linear', axis=-1, copy=True, bounds_error=None, fill_value=nan, assume_sorted=False)

Где x будет моим peak_indices, а y мои peak_values.

Вопрос:

Как мне перейти к этой функции 2 аргумента, которые варьируются в зависимости от каждого среза? Например, другими словами, мое первое использование apply_along_axis использовало только один зависимый от среза аргумент (1000 точек для каждого из моих 25 * 30 элементов оси 0). Однако здесь мне нужно передать функции ДВА аргумента - peak_indices & the_pak_values. Может ли какой-нибудь питонист придумать умный способ распаковать эти аргументы ПОСЛЕ того, как я передам их apply_along_axis как кортежи или что-то в этом роде? Вид:

arr=*[peak_indices, peak_values] 

Я не могу действительно редактировать саму функцию interp1D, которая была бы моим решением, если бы я собирался вызвать свою собственную функцию ...

РЕДАКТИРОВАТЬ: часть преимуществ использование apply вдоль оси заключается в том, что я должен получить улучшения производительности по сравнению с вложенными ifs, поскольку numpy должен иметь возможность массово обрабатывать эти вычисления. В идеале любое решение должно использовать нотацию, которая по-прежнему допускает такую ​​оптимизацию.

1 Ответ

0 голосов
/ 27 февраля 2020

Откуда вы взяли, что apply_along_axis - это инструмент для повышения производительности? Действительно ли он работает быстрее в этом случае?

arr = np.random.rand(25,30,1000)
arr = arr.reshape((arr.shape[0]*arr.shape[1], arr.shape[2]))
# we have a 25*30 set of 1000 pts each. find peaks for that
peaks = np.apply_along_axis(find_peaks, 1, arr, height=0,)

по сравнению с:

peaks = np.array([find_peaks(x, height=0) for x in arr])

Это простая итерация для 25 * 30 набора 1d массивов.

apply выполняет тестовый расчет для определения формы возврата и типа d. Он конструирует массив result, затем выполняет итерацию по всем осям, кроме 1, и вызывает функцию с этим массивом 1d. Там нет компиляции или «массовой обработки» (что бы это ни было). Он просто скрывает все oop в вызове функции.

Он делает итерацию по 2 осям трехмерного массива красивее, но не быстрее:

Вы могли бы использовать его в оригинале arr, чтобы получить (25,30,2) результат:

peaks = np.apply_along_axis(find_peaks, 2, arr_3d, height=0,)

Я предполагаю, find_peaks вернет кортеж из 2 элементов значений, и peaks будет тогда массивом типа dtype.

Поскольку apply_along_axis не имеет никаких преимуществ в производительности, я не вижу смысла пытаться использовать его с более сложным массивом. Это удобно, когда у вас есть 3d-массив и функция, которая принимает 1d-вход, но помимо этого ....?

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...