为什么 SciPy 的 curve_fit 找不到这个高阶高斯函数的 covariance/give 有意义的参数?
Why can't SciPy's curve_fit find the covariance/give me sensical parameters for this higher order gaussian function?
下面是一些最简单的代码:
from scipy.optimize import curve_fit
xdata = [16.530468600170202, 16.86156794563677, 17.19266729110334, 17.523766636569913,
17.854865982036483, 18.18596532750305, 18.51706467296962, 18.848164018436194, 19.179263363902763,
19.510362709369332]
ydata = [394, 1121, 1173, 1196, 1140, 1196, 1158, 1160, 1046, 416]
#function i'm trying to fit the data to (higher order gaussian function)
def gauss(x, sig, n, c, x_o):
return c*np.exp(-(x-x_o)**n/(2*sig**n))
popt = curve_fit(gauss, xdata, ydata)
#attempt at printing out parameters
print(popt)
当我尝试执行代码时,收到此错误消息:
ExCurveFit:9: RuntimeWarning: invalid value encountered in power
return c*np.exp(-(x-x_o)**n/(2*sig**n))
C:\Users\dsneh\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\scipy\optimize\minpack.py:828: OptimizeWarning: Covariance of the parameters could not be estimated
warnings.warn('Covariance of the parameters could not be estimated',
(array([nan, nan, nan, nan]), array([[inf, inf, inf, inf],
[inf, inf, inf, inf],
[inf, inf, inf, inf],
[inf, inf, inf, inf]]))
我看到我应该忽略第一个,但也许这是个问题。第二个更令人担忧,我显然希望参数的值更合理。我试过添加参数作为猜测([2,3,1000,17] 供参考),但它没有帮助。
我相信你 运行 遇到了这个问题,因为 curve_fit
也在测试 n
的非整数值,在这种情况下你的函数 gauss
returns 当 x<x_o
.
时的复数值
我相信暴力破解每个整数 n
并为每个 n
找到最佳参数 sig,c,x_o
会更容易。
例如,如果你认为 n = 0,1,2,...
最多可能是 50,那么 n
的选项就很少了,暴力破解实际上是一种不错的方法。
查看您的数据,最好只将 n
视为 2 的倍数(除非您的其他数据看起来 n
可能是奇数)。
此外,您可能应该为其他参数引入一些界限,就像有 sig>0
会很好,并且您可以安全地设置 c>0
(也就是说,如果您的所有数据看起来像是您在问题中包含的最少数据)。
这是我所做的:
p0 = [1,1200,18] # initial guess for sig,c,x_o
bounds = ([0.01,100,10],[1000,2500,200]) # (lower,upper) bounds for sig,c,x_o
min_err = np.inf # error to minimize to find the best value for n
for n in range(0,41,2): # n = 0,2,4,6,...,40
def gauss(x, sig, c, x_o, n=n):
return c*np.exp(-(x-x_o)**n/(2*sig**n))
popt,pcov = curve_fit(gauss, xdata, ydata, p0=p0, bounds=bounds)
err = np.sqrt(np.diag(pcov)).sum()
if err < min_err:
min_err, best_n, best_popt, best_pcov = err, n, popt, pcov
print(min_error, best_n, best_popt, best_pcov, sep='\n')
import matplotlib.pyplot as plt
plt.plot(xdata,ydata)
plt.plot(xdata, gauss(xdata, *best_popt, n=best_n))
plt.show()
我得到 best_n = 10
和 best_popt = [1.38, 1173.52, 18.02]
。
这是结果图:(蓝线是数据,橙色线是高斯拟合)
下面是一些最简单的代码:
from scipy.optimize import curve_fit
xdata = [16.530468600170202, 16.86156794563677, 17.19266729110334, 17.523766636569913,
17.854865982036483, 18.18596532750305, 18.51706467296962, 18.848164018436194, 19.179263363902763,
19.510362709369332]
ydata = [394, 1121, 1173, 1196, 1140, 1196, 1158, 1160, 1046, 416]
#function i'm trying to fit the data to (higher order gaussian function)
def gauss(x, sig, n, c, x_o):
return c*np.exp(-(x-x_o)**n/(2*sig**n))
popt = curve_fit(gauss, xdata, ydata)
#attempt at printing out parameters
print(popt)
当我尝试执行代码时,收到此错误消息:
ExCurveFit:9: RuntimeWarning: invalid value encountered in power
return c*np.exp(-(x-x_o)**n/(2*sig**n))
C:\Users\dsneh\AppData\Local\Packages\PythonSoftwareFoundation.Python.3.8_qbz5n2kfra8p0\LocalCache\local-packages\Python38\site-packages\scipy\optimize\minpack.py:828: OptimizeWarning: Covariance of the parameters could not be estimated
warnings.warn('Covariance of the parameters could not be estimated',
(array([nan, nan, nan, nan]), array([[inf, inf, inf, inf],
[inf, inf, inf, inf],
[inf, inf, inf, inf],
[inf, inf, inf, inf]]))
我看到我应该忽略第一个,但也许这是个问题。第二个更令人担忧,我显然希望参数的值更合理。我试过添加参数作为猜测([2,3,1000,17] 供参考),但它没有帮助。
我相信你 运行 遇到了这个问题,因为 curve_fit
也在测试 n
的非整数值,在这种情况下你的函数 gauss
returns 当 x<x_o
.
我相信暴力破解每个整数 n
并为每个 n
找到最佳参数 sig,c,x_o
会更容易。
例如,如果你认为 n = 0,1,2,...
最多可能是 50,那么 n
的选项就很少了,暴力破解实际上是一种不错的方法。
查看您的数据,最好只将 n
视为 2 的倍数(除非您的其他数据看起来 n
可能是奇数)。
此外,您可能应该为其他参数引入一些界限,就像有 sig>0
会很好,并且您可以安全地设置 c>0
(也就是说,如果您的所有数据看起来像是您在问题中包含的最少数据)。
这是我所做的:
p0 = [1,1200,18] # initial guess for sig,c,x_o
bounds = ([0.01,100,10],[1000,2500,200]) # (lower,upper) bounds for sig,c,x_o
min_err = np.inf # error to minimize to find the best value for n
for n in range(0,41,2): # n = 0,2,4,6,...,40
def gauss(x, sig, c, x_o, n=n):
return c*np.exp(-(x-x_o)**n/(2*sig**n))
popt,pcov = curve_fit(gauss, xdata, ydata, p0=p0, bounds=bounds)
err = np.sqrt(np.diag(pcov)).sum()
if err < min_err:
min_err, best_n, best_popt, best_pcov = err, n, popt, pcov
print(min_error, best_n, best_popt, best_pcov, sep='\n')
import matplotlib.pyplot as plt
plt.plot(xdata,ydata)
plt.plot(xdata, gauss(xdata, *best_popt, n=best_n))
plt.show()
我得到 best_n = 10
和 best_popt = [1.38, 1173.52, 18.02]
。
这是结果图:(蓝线是数据,橙色线是高斯拟合)