scipy.curve_fit-如何获得curve_fit来产生/选择最佳参数估计?

时间:2018-07-02 08:17:21

标签: python python-2.7 scipy curve-fitting smoothing

我试图将曲线平滑函数拟合到我的许多数据集上,但实际上我需要手动为每个这样的集合分别输入lambda,theta,sigma和变量等的guess参数,否则会提供相对较差的适合度。

这些导致两个问题: 1)实际上是否有一种方法可以对估计值进行编程或获取curve_fit以找到最佳的猜测参数来使用?

2)如果这不可能,那么如何才能使curve_fit在不同数据上使用给定的固定猜测参数集工作,并仍然对所有数据产生最佳结果/拟合?

为了给出一个更好的问题示例/上下文,两个数据集的λ值为0.25产生了以下拟合:-

rawDataList at 0.25

rawDataList_2 at 0.25

但是set 1的λ值为0.75(手动更改)效果更好。显然,这是更好的拟合方法,但是由于将guess参数设置为0.25,因此找不到这种“更好的拟合”方法。

rawDataList at 0.75

以下是我的示例代码:-

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

rawDataList = [0.76,0.77,0.81,0.84,0.83,0.85,0.77,0.66,0.64,0.72,0.69,0.59,0.74,0.65,0.76,
 0.76,0.88,0.75,0.53,0.72,0.53,0.74,0.72,0.62,0.73,0.77,0.74,0.54,0.58,0.70,0.83,0.67,0.84,0.62]

rawDataList_2 = [0.74,0.77,0.75,0.66,0.6,0.63,0.76,0.73,0.56,0.68,0.74,0.56,0.76,0.70,0.72,
 0.83,0.76,0.69,0.64,0.68,0.71,0.71,0.61,0.78,0.65,0.61,0.72]

def GaussianSmooth(x, c1, c3, Lambda, theta, sigma):
    x0 = 0.
    return c1 + c3 * np.cos((2*np.pi*(x/Lambda)) - theta) * np.exp(-(x - x0)**2 / (2 * sigma**2))

## For Binned Data of rawDataList
x = np.arange(len(rawDataList))
x = x*0.06 #Convert x-axis to seconds.
y = np.array(rawDataList)    

popt,pcov = curve_fit(GaussianSmooth, x, y, p0=[np.mean(rawDataList),np.max(rawDataList) - np.mean(rawDataList),0.75,0.0,1.5], bounds=((0., 0., 0. ,0., 0.), (1.0, 1.0, 10.0, 10.0, 10.0)), method='trf',maxfev=10000)
plt.xlabel('Time (s)')
plt.ylabel('Performance from 0-100%')
plt.title('Fit for Performance')

plt.plot(x, y, 'b+:', color='blue', label='data')
plt.plot(x, GaussianSmooth(x, *popt), 'r-', color='red', label='fit')
plt.legend()
plt.show()

## For Binned Data of rawDataList_2
x = np.arange(len(rawDataList_2))
x = x*0.06 #Convert x-axis to seconds.
y = np.array(rawDataList_2)

popt,pcov = curve_fit(GaussianSmooth, x, y, p0=[np.mean(rawDataList_2),np.max(rawDataList_2) - np.mean(rawDataList_2),0.25,0.0,1.5], bounds=((0., 0., 0. ,0., 0.), (1.0, 1.0, 10.0, 10.0, 10.0)), method='trf',maxfev=10000)
plt.xlabel('Time (s)')
plt.ylabel('Performance from 0-100%')
plt.title('Fit for Performance')

plt.plot(x, y, 'b+:', color='red', label='data')
plt.plot(x, GaussianSmooth(x, *popt), 'r-', color='blue', label='fit')
plt.legend()
plt.show()

对评论1进行后期编辑

def generate_Initial_Parameters():    
    global parameterBounds2

    parameterBounds = []
    parameterBounds.append([np.mean(rawDataList) - 0.05, np.mean(rawDataList) + 0.05]) # parameter bounds for c1; 0.05 arbitrary just to give it a small window to form proper lower and upper bound
    parameterBounds.append([np.max(rawDataList) - np.mean(rawDataList) - 0.05, np.max(rawDataList) - np.mean(rawDataList) + 0.05]) # parameter bounds c3
    parameterBounds.append([0.125, 10.0]) # parameter bounds for Lambda; Nyquist limit, can't detect more than 8Hz in current data set. So 1/8 = 0.125. 1/0.1 = 10.
    parameterBounds.append([0.0, 2*np.pi]) # parameter bounds for theta; Phase offset in radians.
    parameterBounds.append([0.0, 3.0]) # parameter bounds for sigma

    parameterBounds2 = ((parameterBounds[0][0], parameterBounds[1][0], parameterBounds[2][0],
                             parameterBounds[3][0], parameterBounds[4][0]), (parameterBounds[0][1],
                            parameterBounds[1][1], parameterBounds[2][1], parameterBounds[3][1],
                            parameterBounds[4][1]))
    # "seed" the numpy random number generator for repeatable results
    result = differential_evolution(sumOfSquaredError, parameterBounds, seed=3)
    return result.x

popt,pcov = curve_fit(GaussianSmooth, x, y, initialParameters, bounds=parameterBounds2, maxfev=10000)

0 个答案:

没有答案