Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/305.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python `为Numpy中的每一行矢量化_Python_Performance_Numpy_Scipy_Vectorization - Fatal编程技术网

Python `为Numpy中的每一行矢量化

Python `为Numpy中的每一行矢量化,python,performance,numpy,scipy,vectorization,Python,Performance,Numpy,Scipy,Vectorization,假设我有一个nxm矩阵,并且想对它的每个元素调用一个函数fct。我可以这样做: A = numpy.array(...) vec_func = numpy.vectorize(fct) A_out = vec_func(A) 这将严格适用于每个矩阵元素的函数,fct将是一个函数: def fct(a_ij): # do something with matrix element a(i, j) 现在我想要相同的,但是对于矩阵的每一行: def fct(row_i): # do som

假设我有一个nxm矩阵,并且想对它的每个元素调用一个函数
fct
。我可以这样做:

A = numpy.array(...)
vec_func = numpy.vectorize(fct)
A_out = vec_func(A)
这将严格适用于每个矩阵元素的函数,fct将是一个函数:

def fct(a_ij):
  # do something with matrix element a(i, j)
现在我想要相同的,但是对于矩阵的每一行:

def fct(row_i):
  # do something with matrix row(i)

有没有一种方法可以使用
numpy.vectorize
或类似工具执行此操作?

编辑:它看起来像
np.apply\u沿轴执行您想要的操作。例如:

import numpy as np

def f(x):
    return x * x.sum()

X = np.arange(12).reshape(2, 2, 3)
np.apply_along_axis(f, -1, X)
# array([[[  0,   3,   6],
#         [ 36,  48,  60]],
#
#        [[126, 147, 168],
#         [270, 300, 330]]])
import numpy as np
from contextlib import wraps

def row_vectorize(f):
    @wraps(f)
    def wrapped_f(X):
        X = np.asarray(X)
        rows = X.reshape(-1, X.shape[-1])
        return np.reshape([f(row) for row in rows],
                          X.shape[:-1] + (-1,))
    return wrapped_f


@row_vectorize
def func(row):
    return row * row.sum()
下面我的原始回复中关于性能的注释仍然适用


原始答复:

这方面没有内置的工具,但是Python使您可以直接定义这样的上下文管理器。例如:

import numpy as np

def f(x):
    return x * x.sum()

X = np.arange(12).reshape(2, 2, 3)
np.apply_along_axis(f, -1, X)
# array([[[  0,   3,   6],
#         [ 36,  48,  60]],
#
#        [[126, 147, 168],
#         [270, 300, 330]]])
import numpy as np
from contextlib import wraps

def row_vectorize(f):
    @wraps(f)
    def wrapped_f(X):
        X = np.asarray(X)
        rows = X.reshape(-1, X.shape[-1])
        return np.reshape([f(row) for row in rows],
                          X.shape[:-1] + (-1,))
    return wrapped_f


@row_vectorize
def func(row):
    return row * row.sum()
现在,您可以在任何非零维度的数组上使用它:

>>> X_1D = np.arange(3)
>>> func(X_1D)
array([0, 3, 6])

>>> X_2D = np.arange(6).reshape(2, 3)
>>> func(X_2D)
array([[ 0,  3,  6],
       [36, 48, 60]])

>>> X_3D = np.arange(12).reshape((2, 2, 3))
>>> func(X_3D)
array([[[  0,   3,   6],
        [ 36,  48,  60]],

       [[126, 147, 168],
        [270, 300, 330]]])
就性能而言,
np.vectorize
做的事情非常相似

如果需要更快地循环跨数组应用的自定义函数,通常可以根据numpy元素操作和聚合操作构造方法;例如,此函数与上面的行矢量化函数实现相同的功能,但在较大的输入上会更快:

def func2(X):
    return X * X.sum(-1, keepdims=True)

如果您有一个更复杂的操作要跨数组的行应用,并且循环的性能是一个瓶颈,那么最好的选择可能是使用or。

我刚才读到:“提供矢量化函数主要是为了方便,而不是为了性能。实现本质上是一个for循环。”因此,该函数无论如何都不是那么有用。没有“函数不可知”的向量化方法可以显著提高性能(正如您所看到的,
np.vectorize
只是语法上的糖分)。您可以重新编写
fct
以接受数组作为输入参数,或者切换到编译的实现(例如Cython、numba)。要添加到@ali_m的建议中,您可以尝试numba的通用ufunc。除了速度提升之外,它还能实现您想要的智能广播。