2011-11-14 31 views
3

我試圖用curve_fit來適應一個簡單的正弦波(甚至沒有任何噪音)作爲測試,然後再討論更復雜的問題。不幸的是,它並沒有給出正確的答案。下面是我的語法:curve_fit甚至無法正弦波

x = linspace(0,100,300) 
y = sin(1.759*x) 
def mysine(x, a): 
    return sin(a*x) 

popt, pcov = curve_fit(mysine, x, y) 
popt 
array([ 0.98679056]) 

然後,如果我嘗試的初始猜測(比如1.5):

popt, pcov = curve_fit(mysine, x, y, p0=1.5) 
popt 
array([ 1.49153365]) 

...這仍然是無處正確的答案附近。

我想我很驚訝,鑑於功能如何被採樣,適合不適合。

回答

5

曲線擬合並不總是那麼簡單。算法基於最小二乘曲線擬合,通常需要對輸入參數進行初始猜測。根據你想要的功能種類,你的初步猜測必須是一個好的選擇。

即使您嘗試了初步猜測,我會說您還有一個額外的問題,與您的採樣頻率和波的頻率有關。欲瞭解更多信息,你可以看看維基百科的Nyquist-Shannon sampling theorem。簡單地說,你的波的頻率是1.759 /(2 * pi)= 0.28,這與你的陣列的採樣頻率非常接近(〜0.33)。另一個可能出現的問題是有太多的擺動來適應你的功能。

爲了讓您的代碼正常工作,我會建議您增加波形的頻率(a> 4 * 0.33),或者增加採樣頻率並減少空間向量長度x

我跑了以下代碼,得到的結果如圖所示here

# -*- coding: utf-8 -*- 
import numpy as np 
import pylab as pl 
from scipy.optimize import curve_fit 

def mysine(x, a): 
    return 1. * np.sin(a * x) 

a = 1.759 # Wave frequency 
x = np.linspace(0, 10, 100) # <== This is what I changed 
y = np.sin(a * x) + 0. * np.random.normal(size=len(x)) 

# Runs curve fitting with initial guess. 
popt, pcov = curve_fit(mysine, x, y, p0=[1.5]) 

# Calculates the fitted curve 
yf = mysine(x, *popt) 

# Plots results for comparison. 
pl.ion() 
pl.close('all') 
fig = pl.figure() 
ax = fig.add_subplot(111) 
ax.plot(x, y, '-', c=[0.5, 0.5, 0.5]) 
ax.plot(x, yf, 'k-', linewidth=2.0) 
ax.text(0.97, 0.97, ur'a=%.4f, ã=%.4f' % (a, popt[0]), ha='right', va='top', 
    fontsize=14, transform=ax.transAxes) 
fig.savefig('stow_curve_fit.png') 
+0

非常感謝,regeirk - 我非常感謝!乾杯,丹。 –

5

如果你知道你正在嘗試適合正弦波的頻率,可以用線性迴歸擬合正弦波。任何正弦波都可以用正弦和餘弦函數的線性組合來表示。你可以使用線性迴歸來找到正弦和餘弦的係數。這種方法的好處在於不需要進行初始猜測,只有一個答案滿足迴歸公式(例如,您不會得到'錯誤'的答案)。

http://exnumerus.blogspot.com/2010/04/how-to-fit-sine-wave-example-in-python.html有一個帶有示例代碼的簡短教程。