2017-07-19 119 views
1

a b cの形式の関数-a*sin(b*x + c)(または多分-a*sin(2*x)でもかまいません)を以下のデータに適合させたいと思います。私はscipy.optimize.curve_fitを使用しましたが、それほどうまくいきません(このimageでわかるように)。これをどのように改善できますか?Pythonでサインデータをフィッティング

コード:

import numpy as np 
import matplotlib.pylab as plt 

data = open('pruebaData.dat', 'r') 
lines = data.readlines()[1:] 
x = []     
y = [] 

for line in lines: 
pos = line.split() 
if pos != []: 
    x.append(float(pos[0])) 
    y.append(float(pos[1])) 

z = [] 
for k in range(len(x)): 
    z.append(np.deg2rad(x[k])) 

valX = np.asarray(z) 
valY = np.asarray(y) 

from scipy.optimize import curve_fit 
def fitFunc(X,a,b,c): 
    return (- a*np.sin(b*X + c)) 

fig = plt.figure(2, figsize = (10,8)) 

init_vals = [1,1,1]  
best_vals, covar = curve_fit(fitFunc, valX, valY, p0=init_vals, maxfev = 15000) 
line1 = plt.plot(x, y, 'o', color = 'k', ms = 6) 
fig2 = plt.plot(x,fitFunc(valX,best_vals[0],best_vals[1], best_vals[2]), '- 
', color = 'k', lw = 1) 
print('PARAMETERS:',best_vals) 

plt.ylabel(r'DATA Y',fontsize=30) 
plt.xlabel(r'DATA X',fontsize=30) 
plt.xlim(min(x),max(x)) 
locs,labels = plt.xticks() 
plt.xticks(locs, fontsize = 20) 
locs,labels = plt.yticks() 
plt.yticks(locs, fontsize = 20) 
plt.savefig('prueba.png', dpi = 500) 

PruebaData.dat

+0

フィッティング周期関数は、常にトリッキーです。周波数bの初期値を予想される周波数と良く一致するように変更する。 – DyZ

+0

あなたのデータは正弦波のようには見えません。たぶん、2つのガウスの重ね合わせがうまくいくでしょう。または、データが正弦波であるとわかっている場合は、実験は悪いです。 –

+0

あなたはインデントを修正できますか? – jacoblaw

答えて

4

実は、私は、これは正弦のために悪いフィット...であることを確認しません。あなたは2つのピーク機能を期待していますか?もしそうなら、あなたのフィットネス感に合ったエラー関数を提供することによって、fit関数にそのことを「説明する」必要があります。はい、2.5サイクルの正弦波でこのデータの中央部分をはるかによくフィットさせることができますが、データの傾向がはっきりと下がっている間に、波の左右の端が再び上向きになります。このミスマッチは半サイクル波を与えます。

エラー^ 2の代わりにsqrt(エラー)などのエラー関数を試してみることもできます。バイモーダルガウス分布はこれをはるかに良く適合させるでしょう。正弦波が本当に必要な場合は、フーリエ変換を検討してください。これは、両方の正弦波の組み合わせ(合計)と、ノイズを考慮する小さな振幅の波の多くをもたらします。

関連する問題