Numpy 如何为scipy.optimize.curve_fit添加约束
在数据分析和科学计算中,使用非线性回归分析来拟合数据是很常见的。在Python中,scipy.optimize.curve_fit是一个重要的库,用于优化拟合非线性函数的参数。然而,有时候我们需要添加一些约束条件,例如限制拟合参数的范围,或者是在模型中添加一些物理约束条件。在本文中,我们将学习如何使用Numpy为scipy.optimize.curve_fit添加约束。
阅读更多:Numpy 教程
添加参数范围约束
首先,让我们看一个例子。假设我们有以下这组数据:
import numpy as np
import matplotlib.pyplot as plt
x_data = np.linspace(-5, 5, num=50)
y_data = 3 * np.exp(-0.5 * (x_data - 1.5) ** 2) + 0.5 + np.random.normal(size=50)
这组数据可以很好地拟合高斯函数,我们可以使用curve_fit函数来拟合。假设我们希望限制拟合的参数a在[0, infinity),b在[-0.5, 0.5]之间。我们可以通过自定义函数和使用bound来添加这些范围限制。
def gaus(x, a, b, c):
return a * np.exp(-0.5 * (x - b) ** 2) + c
from scipy.optimize import curve_fit
popt, pcov = curve_fit(gaus, x_data, y_data, bounds=((0, -0.5, -np.inf), (np.inf, 0.5, np.inf)))
print(popt)
plt.plot(x_data, y_data, 'bo', label='data')
plt.plot(x_data, gaus(x_data, *popt), 'r-', label='fit')
plt.legend()
plt.show()
这里我们传递了bounds参数,并指定了a在[0, infinity)之间,b在[-0.5, 0.5]之间,c任意。
添加物理约束条件
在某些情况下,我们可能需要在模型中添加一些物理约束条件。例如,假设我们有以下数据:
x_data = np.linspace(0, 1, num=50)
y_data = np.log(1 + 10 * x_data) + np.random.normal(size=50) / 10
这组数据很适合使用最小二乘法拟合,但是我们知道y必须大于等于x。我们可以通过定义一个带有物理约束条件的函数来拟合这些数据。请注意,这个函数中的第一个参数是待拟合参数,需要设置为变量x,而我们的参数是存储在第二个元组中的,我们需要将它展开到函数的参数列表中以进行拟合。
def log_model(x, *params):
a, b = params
if b < x:
return np.nan + x
return a * np.log(b * x + 1)
popt, pcov = curve_fit(log_model, x_data, y_data, p0=(1, 1))
print(popt)
plt.plot(x_data, y_data, 'bo', label='data')
plt.plot(x_data, log_model(x_data, *popt), 'r-', label='fit')
plt.legend()
plt.show()
这里我们根据要求限制了参数b必须大于等于x,如果b小于x,函数返回np.nan,这样就不会对拟合产生影响。
现在我们已经学会了如何使用Numpy为scipy.optimize.curve_fit添加约束。这将使我们更容易控制和管理我们的模型,使得我们的拟合工作更加精确和可靠。
总结
- 可以使用bound参数来为拟合参数添加范围限制。
- 可以定义带有物理约束条件的函数来拟合数据。
- 这些约束条件可以帮助提高模型的可靠性和精确性。