Python SciPy

SciPy를 활용한 곡선 맞추기 (curve_fit)

PyExplorer 2025. 3. 9. 09:14
728x90

SciPy를 활용한 곡선 맞추기 (curve_fit)

1. 개요

데이터 분석과 과학적 연구에서는 관측된 데이터를 설명하는 수학적 모델을 찾는 과정이 중요합니다. 이러한 모델을 통해 데이터를 분석하고, 예측을 수행하며, 현상을 보다 잘 이해할 수 있습니다. SciPy의 curve_fit 함수는 주어진 데이터를 기반으로 특정 함수 형태에 가장 잘 맞는 최적의 매개변수를 찾는 데 사용됩니다.

이 포스팅에서는 scipy.optimize.curve_fit을 이용하여 데이터를 곡선에 맞추는 방법을 자세히 설명하고, 다양한 예제를 통해 실습해보겠습니다.


2. curve_fit 함수 개요

scipy.optimize.curve_fit 함수는 비선형 최소제곱법을 이용하여 관측 데이터에 주어진 함수 형태를 적합(fitting)하는 역할을 수행합니다. 이 함수는 다음과 같이 정의됩니다.

scipy.optimize.curve_fit(f, xdata, ydata, p0=None, sigma=None, absolute_sigma=False, check_finite=True, bounds=(-inf, inf), method=None, jac=None, **kwargs)

주요 매개변수

  • f: 적합할 함수. 첫 번째 인수로 독립 변수, 그 뒤에 매개변수를 받는 형태여야 합니다.
  • xdata: 독립 변수 데이터 (예: 관측된 x값).
  • ydata: 종속 변수 데이터 (예: 관측된 y값).
  • p0: 매개변수의 초기 추정값 (기본값은 None).
  • sigma: ydata의 표준 편차 (가중치 부여 시 사용).
  • bounds: 매개변수의 상한과 하한 범위 (기본값은 무한대).

반환값

curve_fit 함수는 다음 두 가지를 반환합니다.

  1. popt: 최적화된 매개변수의 배열.
  2. pcov: 매개변수 추정값의 공분산 행렬.

3. 간단한 예제: 선형 함수에 맞추기

가장 기본적인 예제로, 선형 함수 y = a*x + b 형태로 데이터를 생성하고 이를 curve_fit을 이용해 적합해보겠습니다.

예제 코드

import numpy as np
import matplotlib.pyplot as plt
from scipy.optimize import curve_fit

# 선형 함수 정의
def linear_func(x, a, b):
    return a * x + b

# 샘플 데이터 생성
x_data = np.linspace(0, 10, 50)
y_data = 2.5 * x_data + 1.3 + np.random.normal(0, 1, size=len(x_data))

# curve_fit 적용
popt, pcov = curve_fit(linear_func, x_data, y_data)

# 결과 출력
print("최적의 매개변수 a와 b:", popt)

# 시각화
plt.scatter(x_data, y_data, label='관측된 데이터')
plt.plot(x_data, linear_func(x_data, *popt), color='red', label='적합된 선형 함수')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

실행 결과

최적의 매개변수는 약 a ≈ 2.5b ≈ 1.3으로 추정됩니다. 이는 우리가 데이터를 생성할 때 사용한 값과 유사합니다.


4. 비선형 함수에 맞추기

이번에는 비선형 함수인 2차 다항식 형태의 함수 y = ax^2 + bx + c에 데이터를 적합해보겠습니다.

예제 코드

# 2차 다항식 함수 정의
def quadratic_func(x, a, b, c):
    return a * x**2 + b * x + c

# 샘플 데이터 생성
a_true, b_true, c_true = 1.5, -2.3, 0.8
x_data = np.linspace(0, 10, 100)
y_data = quadratic_func(x_data, a_true, b_true, c_true) + np.random.normal(0, 2, size=len(x_data))

# curve_fit 적용
popt, pcov = curve_fit(quadratic_func, x_data, y_data)

# 결과 출력
print("최적의 매개변수 a, b, c:", popt)

# 시각화
plt.scatter(x_data, y_data, label='관측된 데이터', s=10)
plt.plot(x_data, quadratic_func(x_data, *popt), color='green', label='적합된 곡선')
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

실행 결과

최적화된 매개변수는 실제 값과 매우 유사하게 추정됩니다.


5. 상한과 하한 범위 설정하기

경우에 따라 특정 매개변수의 범위를 제한해야 할 수도 있습니다. 예를 들어, 물리적 의미에서 음수가 되어서는 안 되는 매개변수 등을 제한할 수 있습니다.

예제 코드

# 지수 함수 정의
def exp_func(x, a, b):
    return a * np.exp(b * x)

# 데이터 생성
x_data = np.linspace(0, 5, 50)
y_data = exp_func(x_data, 2.0, 0.5) + np.random.normal(0, 0.2, size=len(x_data))

# 범위 설정 (a는 양수, b는 -1 ~ 1)
popt, pcov = curve_fit(exp_func, x_data, y_data, bounds=([0, -1], [10, 1]))

print("최적의 매개변수 a와 b:", popt)

이와 같이 bounds 매개변수를 사용하면 매개변수의 상한과 하한을 설정할 수 있습니다.


6. 가중치 적용

모든 데이터가 동일한 신뢰도를 갖는 것은 아닐 수 있습니다. 예를 들어, 관측 오차가 큰 데이터는 신뢰도가 낮으므로 적합 과정에서 덜 반영되도록 가중치를 설정할 수 있습니다.

예제 코드

# 가중치 적용 예제
sigma = np.ones_like(y_data)
sigma[20:30] = 5.0  # 특정 구간에 큰 오차 부여

# curve_fit 적용
popt, pcov = curve_fit(quadratic_func, x_data, y_data, sigma=sigma)

sigma 값을 설정하면 오차가 큰 데이터는 적합 과정에서 영향을 덜 미치게 됩니다.


7. 결론

scipy.optimize.curve_fit은 비선형 최소제곱법을 이용해 데이터에 적합한 곡선을 찾는 강력한 도구입니다. 선형, 비선형 함수에 모두 사용할 수 있으며, 범위 제한, 가중치 부여 등 다양한 상황에 맞춰 유연하게 활용 가능합니다.

실제 분석이나 연구 과정에서 적합한 모델을 찾는 과정은 데이터를 이해하고 예측력을 높이는 데 중요한 역할을 하므로, curve_fit을 잘 활용하면 유용한 인사이트를 얻을 수 있을 것입니다.

728x90