Model fitting by python

python을 활용한 model fitting 하기

pythonscipy 라이브러리를 이용해 model fitting을 해보겠습니다. scipy.optimize.curve_fit 기능을 사용할때는 두가지가 필요합니다.

  1. 실제의 데이터
  2. model로 사용할 방정식

말로 설명하는 것 보다는 예를 들어가면서 살펴보도록 하죠.

  • 먼저 다양한 수학적 도구와 자료구조를 위해 numpy
  • Model fitting을 위해 scipy.optimize에서 curve_fit을 불러옵니다.
  • 마지막으로 시각화를 위해 matplotlib을 사용했습니다.
In [2]:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt

# notebook 안에 plot을 표시하는 매직명령어
%matplotlib inline

선형 회귀

간단한 선형회귀의 예를 들어보겠습니다.

선형 회귀(linear regression)는 종속 변수 y와 한 개 이상의 독립 변수 (또는 설명 변수) X와의 선형 상관 관계를 모델링하는 회귀분석 기법이다. 한 개의 설명 변수에 기반한 경우에는 단순 선형 회귀, 둘 이상의 설명 변수에 기반한 경우에는 다중 선형 회귀라고 한다. -- wikipedia

먼저 모델로 사용할 방정식을 python function으로 구현합니다.

In [3]:
## 일차방정식
def func(x, a, b):
    return a * x + b

이제 model fitting을 할 데이터가 필요한데요. 여기서는 numpy를 이용해 가상의 데이터를 만들어 보겠습니다.

In [4]:
# 0부터 10까지 100개의 구간으로 나눔
x = np.linspace(0, 10, 100)
print(x)
[  0.           0.1010101    0.2020202    0.3030303    0.4040404
   0.50505051   0.60606061   0.70707071   0.80808081   0.90909091
   1.01010101   1.11111111   1.21212121   1.31313131   1.41414141
   1.51515152   1.61616162   1.71717172   1.81818182   1.91919192
   2.02020202   2.12121212   2.22222222   2.32323232   2.42424242
   2.52525253   2.62626263   2.72727273   2.82828283   2.92929293
   3.03030303   3.13131313   3.23232323   3.33333333   3.43434343
   3.53535354   3.63636364   3.73737374   3.83838384   3.93939394
   4.04040404   4.14141414   4.24242424   4.34343434   4.44444444
   4.54545455   4.64646465   4.74747475   4.84848485   4.94949495
   5.05050505   5.15151515   5.25252525   5.35353535   5.45454545
   5.55555556   5.65656566   5.75757576   5.85858586   5.95959596
   6.06060606   6.16161616   6.26262626   6.36363636   6.46464646
   6.56565657   6.66666667   6.76767677   6.86868687   6.96969697
   7.07070707   7.17171717   7.27272727   7.37373737   7.47474747
   7.57575758   7.67676768   7.77777778   7.87878788   7.97979798
   8.08080808   8.18181818   8.28282828   8.38383838   8.48484848
   8.58585859   8.68686869   8.78787879   8.88888889   8.98989899
   9.09090909   9.19191919   9.29292929   9.39393939   9.49494949
   9.5959596    9.6969697    9.7979798    9.8989899   10.        ]
In [5]:
y = func(x, 1, 2)
# np.random.normal을 통해 0.9×N(0,1)의 난수를 특정 개수만큼 발생시켜서 y값에 더해주겠습니다.
np.random.seed(1)
yn = y + 0.9 * np.random.normal(size=len(x))

다음으로 curve_fit 기능을 사용해 model fitting을 합니다.

In [6]:
popt, pcov = curve_fit(func, x, yn)
# popt는 주어진 func 모델에서 가장 최고의 fit values를 보여줍니다.
# pcov의 대각성분들은 각 parameter들의 variances 입니다.
In [7]:
plt.scatter(x, yn, marker=".")
plt.plot(x, y, linewidth=2)
plt.plot(x, func(x, *popt), color="red", linewidth=2)
plt.legend(["not fit", "fitting"], loc=2)
plt.show()
No description has been provided for this image

빨간색으로 표현된것이 curve_fit을 통한 선형 회귀입니다.

Gaussian model을 fitting하는 것을 알아봅시다.

다른 예시로 가우시안 모델을 살펴 보겠습니다.

가우시안 모델(Gaussian model)은 자연적인 현상을 표현하기에 좋은 모델이기 때문에, 많은 분야에서 가우시안 모델이 사용될 수 있다. --wikipedia

전과 동일하게

  1. Model을 생성하고
  2. 실험데이터를 만든뒤
  3. curve_fit 기능을 사용합니다.
In [8]:
# Gaussian model을 생성합니다.
def func(x, a, b, c):
    return a * np.exp(-((x - b) ** 2) / (2 * c**2))


# 마찬가지로 0~10까지 100개 구간으로 나눈 x를 가지고
x = np.linspace(0, 10, 100)
y = func(x, 1, 5, 2)  # 답인 y들과
yn = y + 0.2 * np.random.normal(size=len(x))  # noise가 낀 y값들을 만듭니다.
## 그런 후에 curve_fit을 하고 best fit model의 결과를 출력합니다.
popt, pcov = curve_fit(func, x, yn)
In [9]:
plt.scatter(x, yn, marker=".")
plt.plot(x, y, linewidth=2, color="blue")
plt.plot(x, func(x, *popt), color="red", linewidth=2)
plt.legend(["Original", "Best Fit"], loc=2)
plt.show()
No description has been provided for this image

6~8 사이에서는 조금 차이가 나는 것을 확인할 수 있죠.

마지막으로 2개의 독립적인 Gaussian함수로 fitting하는 예제입니다.

방법은 동일합니다. 모델만 다를뿐이죠.

In [10]:
def func(x, a0, b0, c0, a1, b1, c1):
    return a0 * np.exp(-((x - b0) ** 2) / (2 * c0**2)) + a1 * np.exp(
        -((x - b1) ** 2) / (2 * c1**2)
    )


x = np.linspace(0, 20, 200)
y = func(x, 1, 3, 1, -2, 15, 0.5)
yn = y + 0.2 * np.random.normal(size=len(x))

# p0=Initial guess는 초기에 이 값들을 기준으로 optimal value를 찾으라는 설정값입니다.
initial_guess = [1, 3, 1, 1, 15, 1]
popt, pcov = curve_fit(func, x, yn, p0=initial_guess)

plt.scatter(x, yn, marker=".")
plt.plot(x, y, linewidth=2)
plt.plot(x, func(x, *popt), color="red", linewidth=2)
plt.legend(["Original", "Best Fit"], loc=2)
plt.show()
No description has been provided for this image

마치며

scipy로 model fitting하는 방법을 간단히 알아보았습니다. 먼저 Model을 생성하고 실험데이터에 curve_fit 기능을 사용한다는 것을 꼭 기억해주세요.