2017-07-19 95 views
1

我想將下面附帶的數據與-a*sin(b*x + c)(或可能也可以使用-a*sin(2*x))與a b c作爲要確定的值的函數擬合。我使用了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

您的數據看起來不像一個正弦曲線。也許兩個高斯的疊加會更好。或者,如果你知道你的數據應該是正弦曲線 - 那麼你的實驗是不好的。 –

+0

你能修好你的縮進嗎? – jacoblaw

回答

4

其實,我看出,這是一個糟糕的配合......爲正弦波。您是否期待雙峯功能?如果是這樣,您需要通過提供與您的適應感相匹配的錯誤函數來「解釋」fit函數。是的,用2.5個正弦波週期可以更好地擬合這些數據的中心部分,但波浪的左右兩端會再次向上,而數據趨勢明顯下降。這種不匹配是給你半週期波的原因。

您可能會嘗試使用錯誤函數,例如sqrt(error)而不是錯誤^ 2。雙模態高斯分佈可以更好地適應這種情況。如果你確實需要正弦波,考慮一個傅里葉變換,這將給你一個正弦波的組合(總和) - 和許多較小振幅的波來解釋噪聲。