如何向量化这个简单的 NumPy 函数?

给定功能:


def f(x, c=0.7):

    if x >= 0:

        if x <= c:

            return 0.0

        if x <= 2*c:

            return x-c

        else:

            return c

    else:

        return -f(-x, c=c)

我想将它应用于 NumPy 数组。我曾经这样做过np.vectorize,但我失败了。这里有什么想法?


鸿蒙传说
浏览 100回答 2
2回答

有只小跳蛙

我只是想从文档中指出以下内容np.vectorize:提供该vectorize功能主要是为了方便,而不是为了性能。该实现本质上是一个 for 循环。所以,实际上,你并没有在这里使用 NumPy 的矢量化能力。使用 NumPy 的布尔数组索引和np.where,您可以重写您的函数,这样您就有了“真正的”矢量化。这是我这边的一个想法。我不得不承认,实际的代码看起来很丑陋,但是通过预先计算布尔数组,我们可以最大限度地减少处理时间和内存使用量。def f_vec(x, c=0.7):&nbsp; &nbsp; # Initialize output array of same size and type as input array&nbsp; &nbsp; out = np.zeros_like(x)&nbsp; &nbsp; # Pre-calculate boolean arrays to prevent multiple calculation in following steps&nbsp; &nbsp; x_gtq_0 = (x >= 0)&nbsp; &nbsp; x_lt_0 = (x < 0)&nbsp; &nbsp; x_gt_c = (x > c)&nbsp; &nbsp; x_ltq_2c = (x <= 2 * c)&nbsp; &nbsp; x_gt_2c = (x > 2 * c)&nbsp; &nbsp; abs_x = np.abs(x)&nbsp; &nbsp; abs_x_gt_c = abs_x > c&nbsp; &nbsp; abs_x_ltq_2c = abs_x <= 2 * c&nbsp; &nbsp; abs_x_gt_2c = (abs_x > 2 * c)&nbsp; &nbsp; # Re-writing if-else blocks as operations on before calculated boolean arrays&nbsp; &nbsp; out[np.where(x_gtq_0 & x_gt_c & x_ltq_2c)] = x[np.where(x_gtq_0 & x_gt_c & x_ltq_2c)] - c&nbsp; &nbsp; out[np.where(x_gtq_0 & x_gt_2c)] = c&nbsp; &nbsp; out[np.where(x_lt_0 & abs_x_gt_c & abs_x_ltq_2c)] = c - abs_x[np.where(x_lt_0 & abs_x_gt_c & abs_x_ltq_2c)]&nbsp; &nbsp; out[np.where(x_lt_0 & abs_x_gt_2c)] = -c&nbsp; &nbsp; return out我添加了以下小型测试功能来进行一些比较:def test(x):&nbsp; &nbsp; print(x.shape)&nbsp; &nbsp; vfunc = np.vectorize(f)&nbsp; &nbsp; tic = time.perf_counter()&nbsp; &nbsp; res_func = vfunc(x, c=0.7)&nbsp; &nbsp; print(time.perf_counter() - tic)&nbsp; &nbsp; tic = time.perf_counter()&nbsp; &nbsp; res_vec = f_vec(x, c=0.7)&nbsp; &nbsp; print(time.perf_counter() - tic)&nbsp; &nbsp; print('Differences: ', np.count_nonzero(np.abs(res_func - res_vec) > 10e-9), '\n')test((np.random.rand(10) - 0.5) * 4)test((np.random.rand(1000, 1000) - 0.5) * 4)test((np.random.rand(1920, 1280, 3) - 0.5) * 4)这些是结果:(10,)0.00015908699999994677.954300000001524e-05Differences:&nbsp; 0&nbsp;(1000, 1000)1.538538340.0843256779999999Differences:&nbsp; 0&nbsp;(1920, 1280, 3)10.9740101270.7489308680000004Differences:&nbsp; 0&nbsp;np.vectorize因此,在性能方面,对于较大的输入,与实际矢量化方法之间的差异是巨大的。不过,如果np.vectorize解决方案足以满足您的输入,并且您不想花太多精力重新编写代码,请坚持下去!正如我所说,我只是想表明,矢量化不仅仅如此。希望有帮助!----------------------------------------System information----------------------------------------Platform:&nbsp; &nbsp; Windows-10-10.0.16299-SP0Python:&nbsp; &nbsp; &nbsp; 3.8.1NumPy:&nbsp; &nbsp; &nbsp; &nbsp;1.18.1----------------------------------------

UYOU

此功能适用于您的功能。试试看:vfunc&nbsp;=&nbsp;np.vectorize(f) vfunc(a,&nbsp;c=0.7)如果您仍然遇到错误 - 请使用输入数据示例发布它们
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Python