我只是拟合一个线性函数到一些数据,但遇到了curve_fit中默认初始值设置为1的问题。因此,我希望更改初始值,但代码必须非常通用,因为我希望将其应用于不同的y变量。所以我将截距值设置为前20个数据点的平均值,因为这应该非常接近最佳答案(我的x值偏移到0附近)。但是我使斜率为0,因为对于不同的变量,可能有任何符号关系,或者没有。
然而,在我的示例中,斜率为零,curve_fit不会改变此斜率-而是更改截距以最佳拟合数据,把它从它应该在的地方拉开。当值被改变为非零但仍然很小时,这种行为不会改变-在示例中,0.01和0.001具有相同的效果。当它不改变参数时,它会给出“无法估计参数的协方差”警告。
这些数据都是float 64,所以它与之前讨论的here问题没有直接关系。
我不确定这是否是最好的分享方式,但我已经上传了Dropbox here上的数据。下面的代码沿着这些数据应该重现这个问题。我的scipy是版本1.11.3。
感谢任何关于为什么会发生这种情况的想法!
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
import pickle
def fit1(x, alpha, beta_t):
yhat = alpha + beta_t*x
return yhat
with open('example_data.pkl', 'rb') as handle:
xs, ys = pickle.load(handle)
plt.plot(xs, ys, color='blue')
for guess in [0, 0.001, 0.01, 0.1, 1, 10]:
init_guess = np.zeros(2)
init_guess[0] = np.mean(ys[:20])
init_guess[1] = guess
params, _ = curve_fit(fit1, xs, ys, p0=init_guess)
plt.plot(xs, fit1(xs, *params), label=f'init_guess[1] = {init_guess[1]}')
plt.legend()
字符串
x1c 0d1x的数据
1条答案
按热度按时间ne5o7dgx1#
对评论中提到的想法进行扩展:
如果你对数据进行缩放,使大多数点都在1左右,这就消除了无法估计协方差的错误,并允许它拟合线性回归,无论初始猜测是什么。
字符串
的数据
您也可以使用StandardScaler,而不是乘以或除以常数。
或者,如果使用scipy.stats.linregress(),它可以直接找到解决方案,而无需初始猜测或缩放:
型
的
(Note:这是在我将xs和ys都按xs排序之后。)
对于这个数据集,linregress()也比curve_fit()快20倍,因为curve_fit()更灵活。