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