np.power还做了哪些额外的工作?

Jür*_*aak 23 python numpy

我意识到这np.power(a, b)比以前慢np.exp(b * np.log(a)):

import numpy as np
a, b = np.random.random((2, 100000))
%timeit np.power(a, b) # best of 3: 4.16 ms per loop
%timeit np.exp(b * np.log(a)) # best of 3: 1.74 ms per loop
Run Code Online (Sandbox Code Playgroud)

结果是相同的(具有1e-16阶的几个数值误差).

还做了哪些额外的工作np.power?此外,我如何自己找到这些问题的答案?

Jon*_*ler 33

引擎盖下两个表达式调用相应的C函数powexplog上运行的那些C++中的分析,而没有任何代码numpy的,给出:

pow      : 286 ms
exp(log) :  93 ms
Run Code Online (Sandbox Code Playgroud)

这与numpy时间一致.因此,似乎主要区别在于C函数pow慢于exp(log).

为什么?似乎共振的一部分是表达式对于所有输入都不相等.例如,使用负数a和整数b,失败时power起作用exp(log):

>>> np.power(-2, 2)
4
>>> np.exp(2 * np.log(-2))
nan
Run Code Online (Sandbox Code Playgroud)

另一个例子是0 ** 0:

>>> np.power(0, 0)
1
>>> np.exp(0 * np.log(0))
nan
Run Code Online (Sandbox Code Playgroud)

因此,该exp(log)技巧仅适用于输入的子集,同时power适用于所有(有效)输入.

除此之外,power保证根据IEEE 754标准给出完全精度,同时exp(log)可能遭受舍入误差.

  • 而且,`pow()`总能为你提供双精度浮点数的完全精确度,即使在`exp()`和`log()`的组合丢失几个数字的情况下也是如此. (3认同)
  • 至于OP自己寻找答案的问题 - 我检查调试器的类型:`np.power`,`np.log`,`np.exp` - 它是`ufunc`,在numpy的文档中我发现这些在`generate_umath.py`中定义为:`pow`,`log`和`npy_ObjectPower`.最后一个实际上是[此文件]中的C函数(https://raw.githubusercontent.com/numpy/numpy/d46df62746995481439b650790589e60a8070172/numpy/core/src/umath/funcs.inc.src)并返回`PyNumber_Power`和这实际上是Python的`pow` [根据文档](https://docs.python.org/3/c-api/number.html) (2认同)