小能豆

numpy 函数的默认值是什么,其中 where=False?

py

ufunc 文档指出:

在哪里

1.7 版新增。接受与操作数一起广播的布尔数组。True 值表示计算该位置的 ufunc,False 值表示将该值保留在输出中。

out当没有给出时,默认行为是什么?

我观察到了一些行为,但对我来说这没有什么意义:

import numpy as np
a,b = np.ones((2,2))
np.add(a,b,where = False) #returns 0
np.exp(a, where = False)  #returns 1
np.sin(a, where = False)  #returns 1
np.sign(a, where = False) #returns 0
np.reciprocal(a, where = False) #returns 0

有人知道根本原因/行为吗?尤其是np.reciprocal没有实际意义,因为倒数值永远不会为 0

编辑:行为更加复杂:

a,b = np.ones(2)
np.add(a,b,where = False) #returns 6.0775647498958414e-316
a,b = 1,1
np.add(a,b, where = False) #returns 12301129, 
#running this line several times doesn't give the same result every time...

我正在使用 Numpy 版本 1.11.1


阅读 6

收藏
2024-10-29

共1个答案

小能豆

在你使用的 NumPy 1.11.1 版本中,where=False 时的行为可能会导致一些未定义的输出,这与未指定 out 参数时的处理方式有关。这里的关键点是:当 out 没有被指定且 where=False 时,NumPy 会创建一个未初始化的输出数组来存储结果,因此任何 where=False 的位置将保持为未初始化状态。这会导致你观察到的随机值或无意义的输出。

行为解释

  1. 未初始化的输出值:当 where=False 时,NumPy 在这些位置不计算结果,导致这些位置的数据保持为内存中的残留值。这些位置的值会因系统状态而异,因此看起来是随机的或无意义的。

  2. 不同的 ufunc 行为:在某些 ufunc 中(例如 np.expnp.sin 等),这些未初始化的值可能会因为底层优化或数据类型处理导致输出不一致的情况。例如,np.add 在不同运行中的返回值不同,原因正是由于这种未初始化的数据未定义的行为。

解决方案

为避免此问题,尤其是在处理早期 NumPy 版本时,可以使用以下方法:

  • 指定一个 out 数组:通过提前初始化输出数组,可以确保 where=False 的位置保持设定的初始值,而不是随机未初始化的值。

    python a, b = np.ones((2, 2)) result = np.empty_like(a) # 创建定义好的输出数组 result[:] = a # 可以设定初始值 np.add(a, b, where=False, out=result) print(result) # 输出将会保留 `result` 中 `where=False` 的初始值。

  • 使用更新版本的 NumPy:NumPy 从 1.15 版本开始对 where 处理进行了改进。1.17+ 版本中对 where=False 的情况处理更加稳定,通常将未初始化的部分填充为零或采用标准化的默认行为。

总结

where=False 且未指定 out 时,未初始化的输出值会导致不可预测的结果。指定 out 参数即可避免此问题,并获得稳定的输出。

2024-10-29