Как заставить функцию вещать без вызова `np.vectorize` - PullRequest
3 голосов
/ 16 мая 2019

Я хочу найти способ заставить функцию вещать.

Существуют сценарии, в которых функция / метод в более позднем случае может быть перезаписана на постоянную функцию.В таком случае, если

arr = np.arange(0, 1, 0.0001)
f = lambda x: 5
f(arr) # this gives just integer 5, i want [5, 5,..., 5]

, я знаю о таких методах, как np.vectorize, которые заставляют функцию транслироваться, но проблема в том, что это неэффективно, так как это по существу для цикла под колпаком.(см. документацию )

Мы также можем использовать фабричные методы, такие как np.frompyfunc, что позволяет нам преобразовывать функцию python в универсальную функцию numpy ufunc См., например, здесь ,Это превзошло np.vectorize, но все же оно намного менее эффективно, чем встроенные ufunc методы.

Мне было интересно, есть ли эффективный способ обработки этого, а именно, принудительно заставить функцию транслироваться?

Ответы [ 2 ]

1 голос
/ 16 мая 2019

Если бы был лучший способ передавать произвольные функции Python, numpy.vectorize использовал бы его. Вы действительно должны написать функцию с учетом трансляции, если хотите, чтобы она транслировалась эффективно.

В частном случае постоянной функции вы можете написать функцию постоянной вещания, используя numpy.full:

def f(x):
    return numpy.full(numpy.shape(x), 5)

numba.vectorize также может векторизовать функции более эффективно, чем numpy.vectorize, но вам нужна Numba, и вам нужно написать свою функцию так, чтобы Numba могла эффективно компилировать.

0 голосов
/ 16 мая 2019

Для тех, кто может жить без общего ответа, лучший ответ будет np.full_like(arr, val), который улучшится примерно на 20%, чем np.full(arr.shape, val)

И после поднятия этой проблемы автору,Я нашел лучшую золотую середину, которая достигает и общности, и в то же время довольно неплохо работает:

np.broadcast_arrays(x, f(x))[1]

и вот некоторый анализ времени:

arr = np.arange(1, 2, 0.0001).reshape(10, -1)

def master_f(x): return np.broadcast_arrays(x, f(x))[-1].copy('K')
def master_f_nocopy(x): return np.broadcast_arrays(x, f(x))[-1]
def vector_f(x): return np.vectorize(f)(x)

%timeit arr+1 # this takes about 10microsec
%timeit master_f(arr) # this takes about 40 mircrosec
%timeit master_f_nocopy(arr) # this takes about 20 microsec

Обратите внимание, что это позволяетприменять к проекционным функциям, таким как f(x,y):=y, что не поддается помощи np.full_like.

Более того, когда речь идет о более сложных функциях, таких как np.sin и np.cos, вы заметите, что разница между f(arr) и master_f_nocopy(arr) практически ничтожна.

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