dzh*_*lil 5 python select numpy lazy-evaluation
考虑下面的代码
>>> x = np.array([0, 0, 1, 1])
>>> np.select([x==0, True], [x+1, 1/x])
array([ 1., 1., 1., 1.])
Run Code Online (Sandbox Code Playgroud)
它有两个问题。
首先,它并不懒惰。它会急切地计算 x+1 和 1/x,即使最终结果中不需要某些计算值。
其次,numpy 每次运行代码时都会发出警告
RuntimeWarning: divide by zero encountered in true_divide
Run Code Online (Sandbox Code Playgroud)
这与上一点有些相关,因为它试图评估 1/x,即使最终答案中不需要这样做。
是否有一个 select 版本是惰性的并且不会遇到上述问题?
您可以通过显式屏蔽两种情况的输出向量来避免计算:
y = x.copy()
mask = (x == 0) # parentheses only necessary for readability
y[mask] = x[mask] + 1
y[~mask] = 1 / x[~mask]
Run Code Online (Sandbox Code Playgroud)
以上是我强烈建议您做的事情,因此您应该只继续阅读一个毫无意义的设计解决方案,该解决方案实际上解决了问题的“惰性评估”部分。我不建议在实践中使用下面的代码片段!你被警告了。
我终于可以实现实际的惰性评估,尽管它有点混乱并且造成了不必要的情况复杂化(好吧,至少在这种情况下;我可以想象在某些情况下这可能会派上用场)。本着“任何值得做的事情都值得过度去做”的精神:
xfun1 = [lambda xval=xval: xval + 1 for xval in x]
xfun2 = [lambda xval=xval: 1 / xval for xval in x]
[fun() for fun in np.select([x == 0, True], [xfun1, xfun2])]
Run Code Online (Sandbox Code Playgroud)
这个想法是通过将它们隐藏在定义后面来保护 的值1/x不被评估lambda。辅助数组xfun1和为 的每个值xfun2定义一个虚拟值;第一次回来,第二次回来。然而,直到您将元素称为 时,才会对这些进行求值。lambdaxx+11/xxfun2[2]()
因此,我们使用select调用从两个函数数组中选择元素,然后我们获得一个函数列表。为了获得数字返回值,我们需要使用列表理解来评估每个lambda。
| 归档时间: |
|
| 查看次数: |
797 次 |
| 最近记录: |