如何在Python中让拟合曲线经过指定点(0,0)?
解决曲线拟合强制过(0,0)点的问题
问题根源
你的拟合函数在x=0时的计算值不为0:代入x=0,exp(0)=1,此时函数返回值为1 - 8/π² ≈ 0.189,这和数据点(0,0)完全矛盾,这是曲线无法降到0的核心原因。
解决方案
1. 修正函数形式,强制满足x=0时y=0
调整函数结构,使其在x=0时返回0,同时贴合数据趋势(x增大时y趋近于1),推荐使用以下函数形式:
def func(x, D): return 1 - np.exp(-D * x * (np.pi)**2 / 64)
- 当
x=0时,exp(0)=1,函数返回1-1=0,完美匹配(0,0)点; - 当
x增大时,指数项趋近于0,函数趋近于1,和你的数据趋势一致。
如果你的物理模型必须保留8/π²的系数,可调整为:
def func(x, D): return (8/(np.pi)**2) * (1 - np.exp(-D * x * (np.pi)**2 / 64))
此时x趋近于无穷大时函数趋近于8/π²≈0.81,若和你的数据终值不符,说明模型可能需要进一步调整。
2. 保留原权重设置,重新拟合
修正函数后,原有的sigma设置(给(0,0)和最后一个点更高权重)可以保留,确保拟合时优先贴合这两个关键节点。
完整修正代码
import numpy as np from scipy.optimize import curve_fit import matplotlib.pyplot as plt def func(x, D): # 修正后的函数,满足x=0时y=0 return 1 - np.exp(-D * x * (np.pi)**2 / 64) xData = np.array([0, 3, 7, 10, 17, 21, 27, 31, 34, 42, 49, 52, 56, 64]) yData = np.array([0, 0.316045, 0.358446, 0.452339, 0.581898, 0.651380, 0.829214, 0.789857, 0.783002, 0.785944, 0.879307, 0.901747, 0.911792, 0.938174]) sigma = np.ones(len(xData)) sigma[[0, -1]] = 0.01 popt, pcov = curve_fit(func, xData, yData, p0=(1), sigma=sigma) print(popt) plt.figure() plt.scatter(xData, yData) xdata = np.arange(0.0, 65.0, 0.01) plt.plot(xdata, func(xdata, *popt)) # 更新公式注释 text = "$f(x)=1-exp\\left(-\\frac{D \\pi^2 x}{64}\\right)$ | D=%.9f" % tuple(popt) plt.annotate(text, xy=(0.05, 1.05), xycoords='axes fraction', fontsize=12) plt.xlim([-2, 65]) plt.ylim([0, 1]) plt.grid() plt.show()
额外说明
如果必须保留你最初的函数形式(即使它不满足x=0时y=0),可以通过将(0,0)点的权重设为极端值(比如sigma[0] = 1e-10)来强制拟合,但这种方法本质上是“硬拉”曲线,会破坏模型的合理性,不推荐使用。
内容的提问来源于stack exchange,提问作者whd9763
相关产品推荐
相关产品推荐

