繁体   English   中英

scipy curve_fit 奇怪的结果 matplotlib

[英]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.

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