繁体   English   中英

如何修复 Scipy.optimize curve_fit 的“OptimizeWarning:无法估计参数的协方差”?

[英]How to fix the "OptimizeWarning: Covariance of the parameters could not be estimated" for Scipy.optimize curve_fit?

我试图使用curve_fit function将曲线拟合到我的设计点。 但是,我收到了警告消息,而不是来自 curve_fit function 的数据 output。 请在下面找到随附的屏幕截图。

import matplotlib.pyplot as plt
from scipy.optimize import curve_fit
import numpy as np
 
#Fitting function
def func(x, a, b):
    print("x: "+str(x))
    print("b: "+str(b))
    #return a*np.exp(b*x)
    #return a*x+b
    return a*x/(b+x)
 
#Experimental x and y data points    
xData = np.array([  31875.324,31876.35,31877.651,31878.859,31879.771,31880.657,31881.617,31882.343, \
                    31883.099,31883.758,31884.489,31885.311,31886.084,31886.736,31887.582,31888.262, \
                    31888.908,31889.627,31890.312,31890.989,31891.534,31892.142,31892.759,31893.323, \
                    31893.812,31894.397,31894.928,31895.555,31896.211,31896.797,31898.16,31898.761, \
                    31899.462,31900.099,31900.609,31901.197,31901.815,31902.32,31902.755,31903.235, \
                    31903.698,31904.232,31904.776,31905.291,31905.806,31906.182,31906.533,31906.843, \
                    31907.083,31907.175,31822.221,31833.14,31846.066,31860.254,31875.324], dtype=np.longdouble)

yData = np.array([  7999.026,7999.483,8000.048,8000.559,8000.937,8001.298,8001.683,8001.969,8002.263, \
                    8002.516,8002.793,8003.101,8003.387,8003.625,8003.931,8004.174,8004.403,8004.655, \
                    8004.892,8005.125,8005.311,8005.517,8005.725,8005.913,8006.076,8006.269,8006.443, \
                    8006.648,8006.861,8007.05,8007.486,8007.677,8007.899,8008.1,8008.259,8008.443, \
                    8008.636,8008.793,8008.929,8009.077,8009.221,8009.386,8009.554,8009.713,8009.871, \
                    8009.987,8010.095,8010.19,8010.264,8010.293,7956.451,7969.307,7981.115,7991.074,7999.026], dtype=np.longdouble)

#Plot experimental data points
plt.plot(xData, yData, 'bo', label='experimental-data')
 
# Initial guess for the parameters
initialGuess = [31880.0,8000.0]
 
#Perform the curve-fit
popt, pcov = curve_fit(func, xData, yData, initialGuess)
print("popt"+str(popt))
 
#x values for the fitted function
xFit = np.arange(0.0, 50.0, 0.001, dtype=np.longdouble)
print("xFit"+str(xFit))
 
#Plot the fitted function
plt.plot(xFit, func(xFit, *popt), 'r', label='fit params: a=%5.3f, b=%5.3f' % tuple(popt))
 
plt.xlabel('x')
plt.ylabel('y')
plt.legend()
plt.show()

警告消息的截图。 结果为 plot。

试试这个合身,很管用。 原来的 function 并不能真正拟合数据。 对于大x它收敛到a 没关系。 一个下降到更小的x但前提是b是正数。 此外,缺少一个缩放掉率的参数。 因此,在a<0b<0的情况下,一个会得到正确的形状,但会收敛到一个负数。 即缺少偏移量。 因此使用y = a + b / ( x + c )


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

#Fitting function
def func( x, a, b, c ):
    return a + b / ( x + c )

#Experimental x and y data points
xData = np.array([
    31875.324, 31876.35, 31877.651, 31878.859, 31879.771, 31880.657,
    31881.617, 31882.343, 31883.099, 31883.758, 31884.489, 31885.311,
    31886.084, 31886.736, 31887.582, 31888.262, 31888.908, 31889.627,
    31890.312, 31890.989, 31891.534, 31892.142, 31892.759, 31893.323,
    31893.812, 31894.397, 31894.928, 31895.555, 31896.211, 31896.797,
    31898.16, 31898.761, 31899.462, 31900.099, 31900.609, 31901.197,
    31901.815, 31902.32, 31902.755, 31903.235, 31903.698, 31904.232,
    31904.776, 31905.291, 31905.806, 31906.182, 31906.533, 31906.843,
    31907.083, 31907.175, 31822.221, 31833.14, 31846.066, 31860.254,
    31875.324
], dtype=float )

yData = np.array([
    7999.026, 7999.483, 8000.048, 8000.559, 8000.937, 8001.298,
    8001.683, 8001.969, 8002.263, 8002.516, 8002.793, 8003.101,
    8003.387, 8003.625, 8003.931, 8004.174, 8004.403, 8004.655,
    8004.892, 8005.125, 8005.311, 8005.517, 8005.725, 8005.913,
    8006.076, 8006.269, 8006.443, 8006.648, 8006.861, 8007.05,
    8007.486, 8007.677, 8007.899, 8008.1, 8008.259, 8008.443,
    8008.636, 8008.793, 8008.929, 8009.077, 8009.221, 8009.386,
    8009.554, 8009.713, 8009.871, 8009.987, 8010.095, 8010.19,
    8010.264, 8010.293, 7956.451, 7969.307, 7981.115, 7991.074,
    7999.026
], dtype=float )

#x values for the fitted function
xFit = np.linspace( 31820, 31950, 150 )

### sorting and shifting t get reasonable values
### scaling also would be a good idea, but I skip this part here
mx=np.mean( xData )
my=np.mean( yData )


data = np.column_stack( ( xData - mx , yData - my ) )
data = np.sort( data, axis=0 )

### getting good starting values using the fact that
### int x y = ( b + a c) x + a/2 x^2 - c * ( int y ) + const
### With two simple and fast numerical integrals, hence, we get a good
### guess for a, b, c from a simple linear fit.

Sy = cumtrapz( data[:, 1], data[:, 0], initial = 0 )
Sxy = cumtrapz( data[:, 0] * data[:, 1], data[:, 0], initial = 0 )
ST = np.array([
    data[:, 0], data[:, 0]**2, Sy, np.ones( len( data ) )
])
S = np.transpose( ST )
A = np.dot( ST, S )
eta = np.dot( ST, Sxy )
sol = np.linalg.solve( A, eta )
a = 2 * sol[1]
c = -sol[2]
b = sol[0] - a * c

print( "a = {}".format( a ) )
print( "b = {}".format( b ) )
print( "c = {}".format( c ) )

sol, cov = curve_fit( func, xData, yData, p0 = (a + my, b, c - mx) )
print( "linear fit vs non-linear fit:" )
print( a + my, b, c - mx )
print( sol )
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( xData, yData, ls='', marker ='+', label="data")
ax.plot( xFit, func( xFit, a + my, b, c - mx), ls=':', label="linear guess")
ax.plot( xFit, func( xFit, *sol ), label="non-linear fit" )
ax.legend( loc=0 )
plt.show()

提供

[  8054  -6613  -31754]

替代功能

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM