RuntimeWarning으로 numpy 나누기 : double_scalars에서 잘못된 값이 발견되었습니다.
다음 스크립트를 작성했습니다.
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()
입력 요소가 너무 작아서 파이썬이 0으로 바꾸는 것처럼 보이지만 실제로는 그 결과가 있습니다.
이런 종류의 문제를 해결하는 방법은 무엇입니까?
당신은 그것을 해결할 수 없습니다. 간단히 answer1.sum()==0
, 0으로 나누기를 수행 할 수 없습니다.
이것은 answer1
2 개의 매우 큰 음수의 지수 이기 때문에 결과가 0으로 반올림되기 때문입니다.
nan
이 경우 0으로 나누기 때문에 반환됩니다.
이제 문제를 해결하기 위해 다음을 수행 할 수 있습니다.
- 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* 1089
와 y=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 알파 ( link ) 의 솔루션과 얼마나 가까운 지 살펴 보겠습니다 .
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를 사용하는 것이 안전합니다.
사용할 수 있습니다 np.logaddexp
(@ gg349의 답변에 아이디어를 구현 함).
In [33]: d = np.array([[1089, 1093]])
In [34]: e = np.array([[1000, 4443]])
In [35]: log_res = np.logaddexp(-3*d[0,0], -3*d[0,1]) - np.logaddexp(-3*e[0,0], -3*e[0,1])
In [36]: log_res
Out[36]: -266.99999385580668
In [37]: res = exp(log_res)
In [38]: res
Out[38]: 1.1050349147204485e-116
또는 다음을 사용할 수 있습니다 scipy.special.logsumexp
.
In [52]: from scipy.special import logsumexp
In [53]: res = np.exp(logsumexp(-3*d) - logsumexp(-3*e))
In [54]: res
Out[54]: 1.1050349147204485e-116
'UFO ET IT' 카테고리의 다른 글
F # 대 OCaml : 스택 오버플로 (0) | 2020.12.01 |
---|---|
Java에서 일반 클래스에 대한 일반 생성자를 만드는 방법은 무엇입니까? (0) | 2020.12.01 |
선언적 Jenkins 파이프 라인의 단계간에 변수를 어떻게 전달합니까? (0) | 2020.12.01 |
불변 문자열 대 std :: string (0) | 2020.12.01 |
명령에서 결과 데이터가 필요할 때 명령 쿼리 분리 (CQS)를 어떻게 적용합니까? (0) | 2020.12.01 |