为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

鸿蒙传说 2022-07-19 20:56:07
给定功能: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,但我失败了。这里有什么想法?
查看完整描述

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

----------------------------------------


查看完整回答
反对 回复 2022-07-19
?
UYOU

TA贡献1878条经验 获得超4个赞

此功能适用于您的功能。试试看:

vfunc = np.vectorize(f)
vfunc(a, c=0.7)

如果您仍然遇到错误 - 请使用输入数据示例发布它们


查看完整回答
反对 回复 2022-07-19
  • 2 回答
  • 0 关注
  • 99 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
微信客服

购课补贴
联系客服咨询优惠详情

帮助反馈 APP下载

慕课网APP
您的移动学习伙伴

公众号

扫描二维码
关注慕课网微信公众号