2017-06-20 13 views
0

私はoptimalization.curve_fitを使用して決定したい2つの空きパラメータで記述されたデータセットを持っています。Python curve_fit境界の選択と初期条件は結果に影響します

def func(x, a, b,): 
    return a*x*np.sqrt(1-b*x) 

そしてabのためのソリューションの結果はinit_guessの私の選択に非常に強い依存

popt, pcov = opt.curve_fit(f = func, xdata = x_data, ydata= y_data, p0 
= init_guess, bounds = ([a_min, b_min], [a_max, b_max])) 

として嵌合部を次のようにモデルは、初期推定とも上すなわち、定義されています範囲の選択。 解決方法はありますか?

+1

どちらも、境界の選択は、溶液は、その驚くべきことではない影響を与えることことである:ここでは

は、ラマン分光データを当てはめるための初期パラメータ推定のためにscipyのダウンロードの遺伝的アルゴリズムを使用していますRamanSpectroscopyFitからのコード例では、ありません最初の推測がします。私はそれを扱う最善の方法はi)あなたが本当にそれらについて確実であるときだけ境界を選択することです(例えば、あなたの例では 'b'の境界は' sqrt'が定義された方法で選択されるべきです) ii)プロットしたり、残差を計算したりしてフィットの質を調べる。いくつかのデータを追加すると、人々が少しでも遊べるようになるかもしれない。:) – Cleb

答えて

2

Python scipyモジュールの作成者は、Differential Evolution遺伝アルゴリズムをscipyの最適化コードにモジュールscipy.optimize.differential_evolutionとして追加しました。このモジュールを使用すると、非線形回帰の初期パラメータ値を確率的に見つけることができます。

import numpy as np 
import pickle # for loading pickled test data 
import matplotlib 
import matplotlib.pyplot as plt 
from scipy.optimize import curve_fit 
import warnings 

from scipy.optimize import differential_evolution 


# Double Lorentzian peak function 
# bounds on parameters are set in generate_Initial_Parameters() below 
def double_Lorentz(x, a, b, A, w, x_0, A1, w1, x_01): 
    return a*x+b+(2*A/np.pi)*(w/(4*(x-x_0)**2 + w**2))+(2*A1/np.pi)*(w1/(4*(x-x_01)**2 + w1**2)) 


# function for genetic algorithm to minimize (sum of squared error) 
# bounds on parameters are set in generate_Initial_Parameters() below 
def sumOfSquaredError(parameterTuple): 
    warnings.filterwarnings("ignore") # do not print warnings by genetic algorithm 
    return np.sum((yData - double_Lorentz(xData, *parameterTuple)) ** 2) 


def generate_Initial_Parameters(): 
    # min and max used for bounds 
    maxX = max(xData) 
    minX = min(xData) 
    maxY = max(yData) 
    minY = min(yData) 

    parameterBounds = [] 
    parameterBounds.append([-1.0, 1.0]) # parameter bounds for a 
    parameterBounds.append([maxY/-2.0, maxY/2.0]) # parameter bounds for b 
    parameterBounds.append([0.0, maxY*100.0]) # parameter bounds for A 
    parameterBounds.append([0.0, maxY/2.0]) # parameter bounds for w 
    parameterBounds.append([minX, maxX]) # parameter bounds for x_0 
    parameterBounds.append([0.0, maxY*100.0]) # parameter bounds for A1 
    parameterBounds.append([0.0, maxY/2.0]) # parameter bounds for w1 
    parameterBounds.append([minX, maxX]) # parameter bounds for x_01 

    # "seed" the numpy random number generator for repeatable results 
    result = differential_evolution(sumOfSquaredError, parameterBounds, seed=3) 
    return result.x 



# load the pickled test data from original Raman spectroscopy 
data = pickle.load(open('data.pkl', 'rb')) 
xData = data[0] 
yData = data[1] 

# generate initial parameter values 
initialParameters = generate_Initial_Parameters() 

# curve fit the test data 
fittedParameters, niepewnosci = curve_fit(double_Lorentz, xData, yData, initialParameters) 

# create values for display of fitted peak function 
a, b, A, w, x_0, A1, w1, x_01 = fittedParameters 
y_fit = double_Lorentz(xData, a, b, A, w, x_0, A1, w1, x_01) 

plt.plot(xData, yData) # plot the raw data 
plt.plot(xData, y_fit) # plot the equation using the fitted parameters 
plt.show() 

print(fittedParameters) 
関連する問題