[英]scipy curve_fit strange result matplotlib
在我的代码之前:
def func (x,a,b):
return a*np.exp(b*x)
xFit= np.arange(0.0, 20, 0.01)
dev_Fluenz1= np.array([68.9, 21.81, 9.38, 3.73])
dev_Fluenz2= np.array([137.68 , 42.34, 18.75, 7.47 ])
dev_Fluenz3= np.array([80.34, 23.82 , 10.06, 3.76 ])
dev_Fluenz4= np.array([203.7, 61.67 , 10.06, 10.33 ])
dev_Fluenz5= np.array([135.74, 46.23 , 19.42 , 11.21 ])
dev_Fluenz6= np.array([382.83, 112.95, 50.02, 14.95])
dev_Fluenz7= np.array([382.45 , 117.62 , 50.01, 14.95 ])
dev_Fluenz8= np.array([147.32 , 43.67 , 17.88 , 5.01 ])
dev_Fluenz9= np.array([282.91, 85.64 , 35.63 , 13.77 ])
dev_Fluenz10= np.array([150.82, 51.37 , 20.5 , 11.21 ])
dev_x2= np.array([2,5,10,20])
plt.plot(dev_x2,dev_Fluenz1, 'bo')
popt, pcov = curve_fit(func, dev_x2, dev_Fluenz1)
plt.plot(xFit, func(xFit,*popt),color='b', linestyle='--',label=f'Reales DOE Sa <= 0,3 Fluenz 1 J/cm**2 \u03bcm F(x) = {round(popt[0])} * e^({round(popt[1])}*x)')
结果:在此处输入图像描述
将xFit= np.arange(0.0, 20, 0.01)
更改为xFit= np.arange(0.0, 200, 0.01)
和
`dev_x2= np.array([2,5,10,20])` to `dev_x2= np.array([20,50,100,200])`
结果在此处输入图像描述
为什么?
谢谢您的帮助!
说到拟合,重要的是要帮助曲线拟合算法。 做到这一点的一个好方法是适当地标准化观察。 否则,算法可能会丢失。 下面:您的代码修改为适合标准化数据:
import numpy as np
from scipy.optimize import curve_fit
import matplotlib.pyplot as plt
def func (x,a,b):
return a*np.exp(x*b)
# x grid points for fitting:
#xFit= np.arange(0.0, 20, 0.01)
xFit= np.arange(0.0, 200, 0.01)
# Observed x points:
#dev_x2= np.array([2,5,10,20])
dev_x2= np.array([20,50,100,200])
dev_Fluenz1= np.array([68.9, 21.81, 9.38, 3.73])
dev_Fluenz2= np.array([137.68 , 42.34, 18.75, 7.47 ])
dev_Fluenz3= np.array([80.34, 23.82 , 10.06, 3.76 ])
dev_Fluenz4= np.array([203.7, 61.67 , 10.06, 10.33 ])
dev_Fluenz5= np.array([135.74, 46.23 , 19.42 , 11.21 ])
dev_Fluenz6= np.array([382.83, 112.95, 50.02, 14.95])
dev_Fluenz7= np.array([382.45 , 117.62 , 50.01, 14.95 ])
dev_Fluenz8= np.array([147.32 , 43.67 , 17.88 , 5.01 ])
dev_Fluenz9= np.array([282.91, 85.64 , 35.63 , 13.77 ])
dev_Fluenz10= np.array([150.82, 51.37 , 20.5 , 11.21 ])
dev_Fluenz_all=[dev_Fluenz1, dev_Fluenz2, dev_Fluenz3, dev_Fluenz4, dev_Fluenz5,\
dev_Fluenz6, dev_Fluenz7, dev_Fluenz8, dev_Fluenz9, dev_Fluenz10]
# Normalization:
# We divide the observed sizes by the average size
# We dive the observed growth rates by the average growthrate
# This way, the new sizes and growth rates will be close to 1
# Note: each curve is independently normalized.
def normalize_observations(Size, GrowthRate):
meanSize=np.mean(Size)
meanGrowthRate=np.mean(GrowthRate)
return Size/meanSize, GrowthRate/meanGrowthRate, meanSize, meanGrowthRate
# Let's say we are interested in dev_Fluenz1:
fig = plt.figure()
for Fluenz in dev_Fluenz_all:
# Let's normalize the observed data:
x, growthRate, mean_X, mean_GrowthRate = normalize_observations(dev_x2, Fluenz)
# We fit the normalized data:
popt, pcov = curve_fit(f=func, xdata=x, ydata=growthRate)
# And we rescale the obtained parameters:
popt = popt[0]*mean_GrowthRate, popt[1]/mean_X
label='Reales DOE Sa <= 0,3 Fluenz 1 J/cm**2 \u03bcm F(x) = '+format(popt[0],'3.1f')+' * e^('+format(popt[1],'0.4f')+'*x}'
lines, =plt.plot(xFit, func(xFit,*popt), linestyle='--',label=label)
plt.scatter(dev_x2, Fluenz,color=lines.get_color())
plt.xlabel('Mikrostrukturgrösse [ym]')
plt.ylabel('Herstellungsrate: Mikrostrukturen pro Sekunde')
plt.show()
输出:
xFit= np.arange(0.0, 20, 0.01) 和 dev_x2= np.array([2,5,10,20]):
输出:
xFit= np.arange(0.0, 200, 0.01) 和 dev_x2= np.array([20,50,100,200]):
如您所见,“a”参数没有改变,但“b”参数现在缩放了 10 倍。 这正是我们所期望的。
curve_fit
将初始猜测作为拟合的起点,请参阅https://docs.scipy.org/doc/scipy/reference/generated/scipy.optimize.curve_fit.html 。
如果您不提供它,因为您没有提供,则使用默认值:
p0array_like,可选参数的初始猜测(长度 N)。 如果为 None,则初始值将全部为 1(如果函数的参数数量可以使用自省来确定,否则会引发 ValueError)。
对于你的第二个测试用例,这很重要,因为使用func
中指数b
的默认初始值,对于给定的 dev_x2` 范围,你会得到非常大的值,优化器找不到好的解决方案
所以你需要提供一个合理的起始值。 例如,请注意下面的p0 = [...位
xFit= np.arange(0.0, 200, 0.01)
dev_x2= np.array([20,50,100,200])
plt.plot(dev_x2,dev_Fluenz1, 'bo')
popt, pcov = curve_fit(func, dev_x2, dev_Fluenz1, p0 = [100, -0.01])
plt.plot(xFit, func(xFit,*popt),color='b', linestyle='--',label=f'Reales DOE Sa <= 0,3 Fluenz 1 J/cm**2 \u03bcm F(x) = {round(popt[0])} * e^({round(popt[1])}*x)')
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.