반응형

 

Uncertainties 패키지로 불확도(오차?) 전파 계산하기
(Error Propagation)

 

들어가기: 고통스러운 불확도/오차 계산

 

대학원에서 학위과정 중 갖가지 실험과 시뮬레이션 계산을 하다보면, 측정값이나 계산값에 불확도 값이 따라오곤 했습니다. 흔히 '오차'라고 부르고 있고, 저 역시 학부시절 실험교재에서 오차라고 기재되어 있었습니다만, '불확도'가 좀 더 정확한 표현이라고 합니다. 아직도 불확도라는 단어는 입에 붙지 않았고, 저는 그냥 에러(Error)라고 부릅니다.

 

학부시절 실험 수업에서는 그리 신경쓰지 않고 대충 적었었는데, 석사시절 조교가 되고 학부생들에게 설명하는데 불확도를 가진 값들이 계산에 이용될 때, 이 값(흔히 '오차'라고 부르는)들이 어떻게 전파되는지 가르칠 때면 저도 다시금 책을 보며 상기시키는게 가장 귀찮았었습니다.

 

$$
u_c(y) = \sqrt{ u(a)^2 + u(b)^2 + u(c)^2 + ...}
$$

$$
\frac{u_c(y)}{y} = \sqrt{ (\frac{u(a)}{a})^2 + (\frac{u(c)}{c})^2 + (\frac{u(c)}{c})^2 + ...}
$$

 

간단한 더하기와 빼기, 곱하기와 나누기는 그나마 위의 수식처럼 단순하지만, 이것도 값이 몇개 되지 않을 때 이야기입니다.(실은 종종 위의 수식을 보면서 머릿속에 수많은 물음표가 생기곤 합니다.) 값들이 많아지고 사칙연산이 많아지면 골치아프게 됩니다. 더군다나, 불확도(오차?)를 갖는 어느 a값이 있을때, 이 값이 수식에 더해졌다가 나눠졌다가 다시 곱해지는 등 여러번 수식에 나타나게 되면 더욱 힘든 일이 벌어집니다.

 

아주 간단한 예를 들어 A와 B를 측정한 값이 각각 a = 1 ± 0.5, b = 1 ± 0.5 라고 했을 때, 똑같이 1 ± 0.5 값을 가진다고 하더라도, a÷a 값과 a÷b 값은 다릅니다. 이걸 하나하나 신경을 써가면서 불확도 전파(Error propagation) 계산을 하는 것은 정말 끔찍합니다.

 

대학원 시절, 불확도를 제대로 계산하지 않고 연구실 미팅때 발표하던 선배는 교수님들께 정말 영혼이 가출하도록 혼났던 기억이 있습니다. 분명 여러 측정값들이 있었고, 그 측정값들로 하여금 계산해서 나온 값이 불확도가 컸으면 더 커야하는데 더 작아지는 신기한 값을 보였다가 딱 걸렸던 것이죠.

 

uncertainties : 이 패키지를 만든 사람에게 축복을...

그래도 해결책은 있는 법이죠. 제가 파이썬을 접하고 가장 만족했던 순간을 뽑으라면, 단연 uncertainties 패키지의 존재를 알았을 때가 아닐까 싶습니다. 그 골치아픈 불확도 계산을 해줍니다. 대학원 시절 파이썬을 설치하게 되면, 가장 먼저 설치했던 패키지입니다.

 

 

홈페이지 설명을 일부 가져왔습니다. 불확도 계산의 복잡함과 고통을 제거하고 불확도 전파는 더이상 공포가 아니라는 마지막 줄이 인상깊습니다.

 

설치는 간단합니다. cmd든 터미널이든 다음과 같이 설치합니다.

pip install uncertainties

 

불확도 전파 계산을 하는게 이제 엄청 쉬워집니다. 단순히 ufloat으로 불확도를 가지는 실수를 정의하고 연산을 하시면 됩니다.

>>> from uncertainties import ufloat

>>> a = ufloat(100,5)
100.0+/-5.0

>>> b = ufloat(50,1)
50.0+/-1.0  

>>> c = ufloat(100,5)
100.0+/-5.0

uncertainties 패키지로부터 ufloat를 가져와서 a = 100 ± 5, b = 50 ± 1, c = 100 ± 5 로 정의했습니다. a와 c는 동일한 숫자를 넣었습니다.

 

>>> a/a
1.0+/-0

>>> a/c
1.0+/-0.07071067811865477 

>>> a/b
2.0+/-0.1077032961426901

>>> a**2
10000.0+/-1000.0

>>> b**3
125000.0+/-7500.0 

a와 c는 똑같이 100 ± 5임에도 a/a와 a/c가 다른 것을 알 수 있습니다. 생각보다 똑똑합니다. 거듭제곱하는 것까지는 그냥 단순히 일반 사칙연산하듯 하시면 됩니다.

 

이제 문제는 exp, sin, cos 등의 수학함수인데, 이것도 uncertainties 패키지에서 지원합니다.

>>> from uncertainties.umath import *

>>> exp(a)
2.6881171418161356e+43+/-1.3440585709080678e+44

>>> sqrt(a)
10.0+/-0.25  

 

a = 100 ± 5에서 nominal value(공칭값) 100, uncertainty(불확도) 5 숫자를 직접 가져오는 방법은 다음과 같습니다.

>>> a 
100.0+/-5.0

>>> a.nominal_value
100.0

>>> a.n
100.0

>>> a.std_dev
5.0

>>> a.s
5.0

 

여기까지만 되어도 실험데이터나 계산데이터의 불확도 전파를 계산하는데 있어서, 정말 편안함을 느끼실 겁니다. 이밖에도 1차원 배열의 경우 numpy를 이용하실 수 있습니다. 좀 더 복잡해지면 unumpy 모듈을 uncertainties에서 import해서 써야하는데, 제 경우에는 여기까지 쓰는 경우는 거의 없었습니다. (이미지센서로 실험할 때 썼던 것 같은데..)

 

이 패키지가 좀 의심스러우신 분들은 직접 불확도 전파를 계산해보시고, 패키지와 비교해보시는 것도 좋은(???) 경험이 될 수 있습니다. 아주 기억에 남을 겁니다. 저는 제 지도교수님께서 어디 인터넷에 돌아다니는 패키지를 누가 믿냐면서 직접 계산하라 하셔서, 엑셀과 씨름한 기억이 아직도 생생합니다. 그땐 정말 이가 갈렸는데, 덕분에 그후 유사한 계산을 수행하는 동안에는 엑셀과 파이썬 2개로 데이터를 검증할 수 있었습니다.

반응형

+ Recent posts