2 回答

TA贡献1824条经验 获得超8个赞
我只是想从文档中指出以下内容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.0001590869999999467
7.954300000001524e-05
Differences: 0
(1000, 1000)
1.53853834
0.0843256779999999
Differences: 0
(1920, 1280, 3)
10.974010127
0.7489308680000004
Differences: 0
np.vectorize因此,在性能方面,对于较大的输入,与实际矢量化方法之间的差异是巨大的。不过,如果np.vectorize解决方案足以满足您的输入,并且您不想花太多精力重新编写代码,请坚持下去!正如我所说,我只是想表明,矢量化不仅仅如此。
希望有帮助!
----------------------------------------
System information
----------------------------------------
Platform: Windows-10-10.0.16299-SP0
Python: 3.8.1
NumPy: 1.18.1
----------------------------------------

TA贡献1878条经验 获得超4个赞
此功能适用于您的功能。试试看:
vfunc = np.vectorize(f) vfunc(a, c=0.7)
如果您仍然遇到错误 - 请使用输入数据示例发布它们
添加回答
举报