处理 python 中无穷大的操作

Handling operations with infinities in python

我有一段代码可以进行简单的计算。

import numpy as np

#Constants
R = 8.314462
T = 298.15
e = -678.692
e_overkbT = e*1000/(R*T)

#Independent variable
mu = np.linspace(-2000,2000,1000)  
mu_overkbT = mu*1000/(R*T)


#Calculation
aa = (np.exp(mu_overkbT- e_overkbT))
theta = aa/(1+aa)

对于'mu'的负值,'aa'非常小,因此变量“theta”非常接近于0。对于'mu'的正值,'aa' 很大。因此,对于大数 'theta' 接近 1。(大数超过大数 + 1)。

对于较大的 'aa' python 值,将 'theta' 舍入为 1,这很好。然而,最终对于足够大的数字 python 会说 'aa' 是 'inf'。因此,在计算 'theta' 的最后一步中,我遇到了除法 'inf'/'inf'.

的运行时错误

我需要某种方式来处理此错误,以便它为我提供“1”作为 'theta' 的结果。我无法缩小变量 'mu' 的范围并在错误之前停止,因为这个计算是在一个改变 'e' 值的大函数内部,因此这个错误并不总是发生在同一个地方。

谢谢。

这种溢出在大项使用指数函数时经常发生。除了注意到 exp(x)/(1+exp(x)) = 1/(1+exp(-x)) 的非常好的评论之外,如果您找不到简单的转换,另一种通用方法是使用对数使中间数字更易于管理,然后最后反转此操作。对于许多大项(或非常小的)项的乘积尤其如此,通过应用对数就变成了一个简单的和。

如果您不介意对 SciPy 的依赖,您可以替换

aa = (np.exp(mu_overkbT- e_overkbT))
theta = aa/(1+aa)

from scipy.special import expit

theta = expit(mu_overkbT- e_overkbT)

expit 是 logistic sigmoid 函数的一个实现。它可以正确处理非常大的正数和负数。请注意,1/(1 + np.exp(-x)) 会为较大的负值生成警告(但它仍然正确 returns 0):

In [148]: x = -1500

In [149]: 1/(1 + np.exp(-x))
<ipython-input-149-0afe09c93af3>:1: RuntimeWarning: overflow encountered in exp
  1/(1 + np.exp(-x))
Out[149]: 0.0