1. ホーム
  2. スクリプト・コラム
  3. パイソン

[解決済み】RuntimeWarning: invalid value encountered in double_scalars で numpy の除算ができない。

2021-12-28 01:51:27

質問

以下のpythonコードを実行しました。

import numpy

d = numpy.array([[1089, 1093]])
e = numpy.array([[1000, 4443]])
answer = numpy.exp(-3 * d)
answer1 = numpy.exp(-3 * e)
res = answer.sum()/answer1.sum()
print res

そして、エラーが出ました。

nan
C:\Users\Desktop\test.py:16: RuntimeWarning: invalid value encountered in double_scalars
  res = answer.sum()/answer1.sum()

解決方法は?

解けません。単に answer1.sum()==0 , とゼロによる除算を実行することはできません。

このようなことが起こるのは answer1 は非常に大きな負の数2つの指数であるため、結果はゼロに丸められます。

nan が返されるのは、この場合ゼロで割っているからです。

さて、問題を解決するには、次のようにします。

  • 高精度な数学のためのライブラリ、例えば mpmath . でも、それだと面白みがない。
  • 大きな武器の代わりとして、以下に詳述するように、数学的な操作を行う。
  • テーラードで行く scipy/numpy 関数は、まさにあなたが望むことを行うことができます Warren Weckesserの回答をご覧ください。

ここでは、この問題に役立つ計算操作の方法を説明します。分子にはそれがあります。

exp(-x)+exp(-y) = exp(log(exp(-x)+exp(-y)))
                = exp(log(exp(-x)*[1+exp(-y+x)]))
                = exp(log(exp(-x) + log(1+exp(-y+x)))
                = exp(-x + log(1+exp(-y+x)))

ここで x=3* 1089y=3* 1093 . さて、この指数関数の引数は

-x + log(1+exp(-y+x)) = -x + 6.1441934777474324e-06

分母についても同様ですが、次のようになります。 log(1+exp(-z+k)) はすでに丸められ 0 ということで、分母の指数関数の引数は単純に丸められます。 -z=-3000 . この場合、結果は次のようになります。

exp(-x + log(1+exp(-y+x)))/exp(-z) = exp(-x+z+log(1+exp(-y+x)) 
                                   = exp(-266.99999385580668)

というのは、先頭の2つの項(つまり最初の数字 1089 を分子に、最初の数字 1000 を分母に持つ)。

exp(3*(1089-1000))=exp(-267)

とりあえず、Wolfram alphaの解にどれだけ近いか見てみよう( リンク ):

Log[(exp[-3*1089]+exp[-3*1093])/([exp[-3*1000]+exp[-3*4443])] -> -266.999993855806522267194565420933791813296828742310997510523

この数値と上の指数との差は +1.7053025658242404e-13 ということで、分母で行った近似は問題なかったのです。

最終的な結果は

'exp(-266.99999385580668) = 1.1050349147204485e-116

wolframアルファから( リンク )

1.105034914720621496.. × 10^-116 # Wolfram alpha.

で、ここでもnumpyを使うのが無難です。