Векторизация функции python
У меня есть старая функция с именем old_func, которая принимает в качестве входных данных два позиционных аргумента, x и y. Вход функции был записан следующим образом, используя Кортеж в качестве входа:
def old_func(position):
x, y = position
return x**2 + y**2
Теперь мне нужен быстрый и простой способ вызова функции по сетке значений:
xx = numpy.linspace(0, 1, 100)
yy = numpy.linspace(0, 1, 100)
X, Y = numpy.meshgrid(xx, yy)
array_positions = (X,Y)
old_fun(array_positions)
Цель состоит в том, что каждая операция над
x в функции выполняется на всех X и то же самое для y. Я попытался векторизировать функцию с помощью numpy.vectorize но это не работает. Я предпочитаю не изменять функцию, чтобы принимать массивы NumPy, потому что это займет слишком много времени. 2 ответов:
Приведенный ниже код делает свое дело и избавляет вас от необходимости создавать
array_positions.
Во-первых, используйте
ravelчтобы сгладитьXиYв NumPy массивы формы(10000,).X_flattened = X.ravel() Y_flattened = Y.ravel()Затем используйте
apply_along_axisчтобы реализовать пользовательскую функцию итеративно вниз по длине этих уплощенных массивов.float_array = np.apply_along_axis(old_func, 0, (X_flattened, Y_flattened))Наконец, переформуйте выходной массив в желаемую форму
(100, 100).np.reshape(float_array, (100, 100))
Ваш собственный код должен (и работает) нормально:
def old_fun(position): x, y = position z = x**2 + y**2 return z xx = numpy.linspace(0,1,100) yy = numpy.linspace(0,1,100) X,Y = numpy.meshgrid(xx, yy) array_positions = (X,Y) Z = old_fun(array_positions)
Z.shapeесть сейчас(100, 100).В общем случае массивы numpy будут работать с любым стандартным оператором, например
+и**. Обратите внимание, что хотя вашold_funпринимает Кортеж в качестве входных данных, и этот кортеж должен состоять из двух значений, тип этих двух значений может быть любым, если этот тип поддерживает математические операторы. Их поддерживают как стандартные скаляры Python, так и массивы numpy, поэтому код работает нормально.Заметка о @Juanmanuel's ответ: хотя он также отлично работает,
apply_along_axisспециально не предназначен для векторизации в том смысле, что люди обычно хотят использовать его, т. е. получать хорошую производительность от numpy.apply_along_axisприведет к медленному циклу Python, а не к быстрому циклу C, Как правильно векторизованный код. Ваш собственный код использует правильную векторизацию, поэтому используйте ее вместо этого.
Comments