【问题标题】:Python OverflowError: math range error being raised differently in different runsPython OverflowError:数学范围错误在不同的运行中以不同的方式引发
【发布时间】:2014-09-13 07:20:13
【问题描述】:

我的程序似乎几乎是任意地崩溃了。

我的代码包括这两行:

z[i, j] = -math.exp(oneminusbeta[j, i])
weights[i,j] = math.exp(beta[j,i] + oneminusbeta[j,i])

我之前在二维数据上运行过我的整个代码,它是7341 x 648。运行该代码我完全没有问题。

但现在我使用的数据大约是原来的十倍。这是71678 x 648,我收到了这个错误:

OverflowError: math range error

而且我没有在任何特定点上得到这个。我在每一行代码之前记录了 cmets,以便我可以查看导致崩溃的原因,并且看起来崩溃在上面提到的第二行 (weights[i,j] = math.exp(beta[j,i] + oneminusbeta[j,i])) 上发生的频率更高。

问题是,它在不同的时间崩溃。 起初,它在weights[30816, 42] 崩溃。然后在weights[55399, 43]。然后在z[33715,45]。但所有 3 种情况下的数据都是相同的。

问题可能是什么?这是与 python 的内存相关问题吗?顺便说一句,我也在使用Numba

编辑

我忘了提一下,我已经设置了阈值,以便 exp() 函数中的内容不超过 709 或 -708,所以从技术上讲不应该有溢出。

【问题讨论】:

    标签: python numpy scipy overflow exponent


    【解决方案1】:

    您的计算结果无法在您的计算机上显示。这可能意味着 math.exp(...) 大于大约 10308,或者传递给 math.exp() 的参数大于大约 710。

    尝试在每次计算之前打印beta[j,i]oneminusbeta[j,i] 的值。

    实际上,您不必在每行代码之前打印 cmets。相反,请尝试使用 try 块包装计算,如下所示:

    try:
      weights[i,j] = math.exp(beta[j,i] + oneminusbeta[j,i])
    except OverflowError:
      print "Calculation failed! j=%d i=%d beta=%f oneminusbeta=%f"%(j,i,beta[j,i],oneminusbeta[j,i])
      raise
    

    【讨论】:

    • 这些值并没有那么大,当我在单独的 python 控制台上单独尝试它们时,它们不会导致崩溃。另外,我已经对我的值设置了阈值,以便它们不超过 10^308 或 708。我只是按照你的建议尝试了引发错误 - 但它说 NotImplementedError: offset=742 opcode=0x79 opname=SETUP_EXCEPT
    • 我不知道为什么异常处理不起作用。但是你可以回去记录这些值。将beta[j,i]oneminusbeta[j,i] 添加到日志记录时会发生什么?
    • 是的,我试过了,但差别不大。它在打印出它们被添加之前崩溃了,即在 [30816, 42]。然后,后来,它确实添加并打印出 [30816, 42],但在其他地方崩溃了。我正在打印 beta 和 oneminusbeta 的值,但它们实际上并没有那么大。例如。 -11 或 -6(大约 9 到 13 位小数)。
    • 现在我什至没有使用 numba,这是后续操作,它在另一行崩溃但又在不同点崩溃:stackoverflow.com/questions/26124464/…
    【解决方案2】:

    您的溢出几乎可以肯定是真正的溢出;您的其中一个值太大而无法放入 Python float(即 C double)中。


    那么,为什么每次都发生在不同的地方呢?

    因为您使用的是 Numba。

    Numba JIT 编译您的代码。如果它检测到没有争用,它可以重新排序你的代码——甚至,至少在理论上,在多个内核或 GPU 上并行运行它(尽管我认为目前你只有在显式编码时才能获得 GPU 计算) numba.cuda)。

    无论如何,这意味着通过代码的路径可能是不确定的。如果有多个地方可能发生溢出,您无法预测哪一个会失败并触发异常。


    无论如何,这并不重要。如果你的计算溢出,你必须解决这个问题。而且每次不同的溢出不应该使调试变得更加困难——尤其是考虑到它显然通常发生在一个地方,但并非总是如此。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-11-10
      • 2017-08-26
      • 2020-11-06
      • 1970-01-01
      相关资源
      最近更新 更多