2つの異なる方程式を関数に当てはめる(curve_fit)

Nov 23 2020

問題があります。2つの異なる方程式があります。1つは線形方程式で、もう1つは指数方程式です。ただし、両方の方程式が同時に有効である必要はありません。つまり、2つの異なるレジームがあります。

Equation 1 (x < a): E*x
Equation 2 (x >=a): a+b*x+c*(1-np.exp(-d*np.array(x)))

つまり、データの最初の部分は一次方程式に適合し、残りは前述の方程式2に適合している必要があります。

私が適合させようとしているデータは次のようになります(人々が行きたい場合は、いくつかのサンプルデータも追加しました):

ヘヴィサイド関数で1つの近似関数を定義するだけで、すでにいくつかのことを試しました。

def fit_fun(x,a,b,c,d,E):
    
    funktion1=E*np.array(x)
    
    funktion2=a+b*x+c*(1-np.exp(-d*np.array(x)))
           
    return np.heaviside(x+a,0)*funktion2+(1-np.heaviside(x+a,0))*funktion1

区分的関数の定義:

def fit_fun(x,a,b,c,d,E):
    return np.piecewise(x, [x <= a, x > a], [lambda x: E*np.array(x), lambda x: a+b*x+c*(1-np.exp(-d*np.array(x)))])

最後に(残念ながら、フォーム関数エラーが発生しますか?):

def plast_fun(x,a,b,c,d,E):
   
    out = E*x
    out [np.where(x >= a)] = a+b*x+c*(1-np.exp(-d+x))
    
    return out

誤解しないでください。私は「いくつかの」適合を取得しますが、どちらか一方の方程式を取り、実際には両方を使用していないようです。また、いくつかの境界と最初の推測を使用してみましたが、変更されることはありません。

どんな入力でも大歓迎です!

データ:

0.000000     -1.570670 
0.000434     83.292677 
0.000867     108.909402 
0.001301     124.121676 
0.001734     138.187659 
0.002168     151.278839 
0.002601     163.160478 
0.003035     174.255626 
0.003468     185.035092 
0.003902     195.629820 
0.004336     205.887161 
0.004769     215.611995 
0.005203     224.752083 
0.005636     233.436680 
0.006070     241.897851 
0.006503     250.352697 
0.006937     258.915168 
0.007370     267.569337 
0.007804     276.199005 
0.008237     284.646778 
0.008671     292.772349 
0.009105     300.489611 
0.009538     307.776858 
0.009972     314.666291 
0.010405     321.224211 
0.010839     327.531594 
0.011272     333.669261 
0.011706     339.706420 
0.012139     345.689265 
0.012573     351.628362 
0.013007     357.488150 
0.013440     363.185771 
0.013874     368.606298 
0.014307     373.635696 
0.014741     378.203192 
0.015174     382.315634 
0.015608     386.064126 
0.016041     389.592120 
0.016475     393.033854 
0.016908     396.454226 
0.017342     399.831519 
0.017776     403.107084 
0.018209     406.277016 
0.018643     409.441119 
0.019076     412.710982 
0.019510     415.987331 
0.019943     418.873140 
0.020377     421.178098 
0.020810     423.756827 

これまでのところ、これら2つの質問を見つけましたが、理解できませんでした。適合パラメーターとしてボーダーを使用した2つの異なる関数の適合 2つの異なるレジームで構成されるデータの曲線を適合させます。

回答

2 FlavioMoraes Nov 23 2020 at 23:35

2番目の方程式で間違いを犯しているのではないかと思いますa+b*x+c*(1-np.exp(-d+x))。ここで、ax1つの曲線から別の曲線に変更する場所の値です。y代わりにの値を使用する必要があると思いますa*E。また、フィットに初期パラメータを定義することも非常に重要です。.txtファイルのデータを使用して次のコードを実行しました。以下に示すように、適合はかなり良好に見えます。

import numpy as np
import pandas as pd
import matplotlib.pyplot as plt
from scipy import optimize, stats

def fit_fun(x,a,b,c,d,E):
    return np.piecewise(x, [x <= a, x > a], [lambda x: E*x, lambda x: a*E+b*x+c*(1-np.exp(-d*x))])

df = pd.read_csv('teste.txt', delimiter='\s+', header=None)
df.columns = ['x','y']

xdata = df['x']
ydata = df['y']

p0 = [0.001,1,1,1,100000]
popt, pcov = optimize.curve_fit(fit_fun, xdata.values, ydata.values, p0=p0, maxfev=10000, absolute_sigma=True, method='trf')
print(popt)

plt.plot(xdata, ydata,'*')
plt.plot(xdata, fit_fun(xdata.values, *popt), 'r')
plt.show()