이 예에서는 multivariate_normal.cdf 함수를 두 번 사용하고 있으며 두 가지 다른 결과를 얻습니다. 결과는 비슷하지만 여전히 다릅니다. 함수를 사용할 때마다 정확히 동일한 결과를 얻기 위해 조정할 수있는 것이 있습니까?
import numpy as np
from scipy.stats import multivariate_normal
def normal_cdf_3d(d_1, d_2, d_3, correl_1_2, correl_1_3, correl_2_3):
mean = np.array([0, 0, 0])
cov = np.array(
[
[1, correl_1_2, correl_1_3],
[correl_1_2, 1, correl_2_3],
[correl_1_3, correl_2_3, 1],
]
)
x = np.array([d_1, d_2, d_3])
y = multivariate_normal(mean=mean, cov=cov).cdf(x=x)
return y
d_1_ = -0.2304886114323222
d_2_ = -0.1479019945774904
d_3_ = 0.525
correl_1_2_ = 0.5500190982169267
correl_1_3_ = 0.9219544457292886
correl_2_3_ = 0.5916079783099616
a = normal_cdf_3d(
d_1=d_1_,
d_2=d_2_,
d_3=d_3_,
correl_1_2=correl_1_2_,
correl_1_3=correl_1_3_,
correl_2_3=correl_2_3_,
)
b = normal_cdf_3d(
d_1=d_1_,
d_2=d_2_,
d_3=d_3_,
correl_1_2=correl_1_2_,
correl_1_3=correl_1_3_,
correl_2_3=correl_2_3_,
)
print(a)
print(b)
if a == b:
print(True)
else:
print(False)
# Results
# 0.2698170436763295 (a)
# 0.2698184075101584 (b)
# False
CDF는 다차원 공간에서 수치 적분에 의해 계산되어야하므로 multivariate_normal
개체의 수렴에 대한 상대적 및 절대 공차가 상대적으로 낮습니다. 또한 통합을 위해 고려할 포인트 수는 기본적으로 1000000 * ndim
입니다 3000000
. 이 경우에는입니다 .
import numpy as np
from scipy.stats import multivariate_normal
d_1 = -0.2304886114323222
d_2 = -0.1479019945774904
d_3 = 0.525
correl_1_2 = 0.5500190982169267
correl_1_3 = 0.9219544457292886
correl_2_3 = 0.5916079783099616
mean = np.array([0, 0, 0])
cov = np.array(
[
[1, correl_1_2, correl_1_3],
[correl_1_2, 1, correl_2_3],
[correl_1_3, correl_2_3, 1],
]
)
x = np.array([d_1, d_2, d_3])
mvn = multivariate_normal(mean=mean, cov=cov)
print(mvn.abseps, mvn.releps, mvn.maxpts)
# prints
1e-05 1e-05 3000000
포인트 수를 늘리고 허용 오차를 줄이면 성능을 저하시키면서 정밀도가 향상됩니다. Python의 기본 정밀도는 float의 경우 1e-17입니다.
mvn.cdf(x) - mvn.cdf(x)
# returns:
-9.741263303830738e-06 # Wall time: 1.27 ms
mvn.abseps = mvn.releps = 1e-8
mvn.maxpts = 5_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
-3.6016106763625544e-10 # Wall time: 409 ms
mvn.abseps = mvn.releps = 1e-10
mvn.maxpts = 8_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
-2.0803747613484802e-11 # Wall time: 2.22 s
mvn.abseps = mvn.releps = 1e-12
mvn.maxpts = 10_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
-4.4660386500083861e-12 # Wall time: 3.39 s
이것은 큰 시간 확장이 없습니다. 가능한 한 동일한 출력을 얻을 때까지 몇 번 더 시도하여 포인트 수를 늘립니다.
mvn.abseps = mvn.releps = 1e-17
mvn.maxpts = 35_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
-1.755373624234835e-12 # Wall time: 11.1 s
mvn.abseps = mvn.releps = 1e-19
mvn.maxpts = 70_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
2.7454705175955496e-12 # Wall time: 30 s
mvn.abseps = mvn.releps = 1e-25
mvn.maxpts = 100_000_000
mvn.cdf(x) - mvn.cdf(x)
# returns:
-2.1491142199181468e-12 # Wall time: 39.3 s
마지막 3 회 실행을 기반으로 계산의 사용 가능한 정밀도에 제한이 있습니다. 파이썬의 정밀도보다 낮더라도 엡실론이 같은 숫자 인 것으로 받아 들여질 수 있습니다.
def approx_equal(x, y, tol=1e-5):
return abs(x-y) < tol
이 기사는 인터넷에서 수집됩니다. 재 인쇄 할 때 출처를 알려주십시오.
침해가 발생한 경우 연락 주시기 바랍니다[email protected] 삭제
몇 마디 만하겠습니다