在Python中拟合可变Sinc函数

0 投票
2 回答
3335 浏览
提问于 2025-04-18 01:56

我想把一个sinc函数拟合到一些数据线上。用高斯函数拟合是可以的,但我的数据似乎不够符合高斯分布,所以我想换成sinc函数。

我刚试着写了一段可以自运行的简短代码,但意识到我可能不太明白数组在传给函数时是怎么处理的,这可能是我在运行程序时收到错误信息的原因之一。

所以我现在的代码看起来是这样的:

from numpy import exp
from scipy.optimize import curve_fit
from math import sin, pi

def gauss(x,*p):
    print(p)
    A, mu, sigma = p
    return A*exp(-1*(x[:]-mu)*(x[:]-mu)/sigma/sigma)

def sincSquare_mod(x,*p):
    A, mu, sigma = p
    return A * (sin(pi*(x[:]-mu)*sigma) / (pi*(x[:]-mu)*sigma))**2


p0 = [1., 30., 5.]
xpos = range(100)
fitdata = gauss(xpos,p0)
p1, var_matrix = curve_fit(sincSquare_mod, xpos, fitdata, p0)

我得到的结果是:

Traceback (most recent call last):
File "orthogonal_fit_test.py", line 18, in <module>
fitdata = gauss(xpos,p0)
File "orthogonal_fit_test.py", line 7, in gauss
A, mu, sigma = p
ValueError: need more than 1 value to unpack

根据我的理解,p没有被正确传递,这很奇怪,因为它确实在我的实际代码中。然后在拟合sincSquare函数时,我也收到了类似的错误信息,这可能是同样类型的错误。我对星号操作符还比较陌生,所以可能隐藏着一些问题...

有没有人有什么想法?:)

谢谢!

2 个回答

0

还要注意的是,当 x*π 接近零时,你可能会遇到舍入误差,这些误差可能会被放大。为了获得更好的结果,可以参考下面的近似方法(VB.NET,抱歉):

Private Function sinc(x As Double) As Double
    x = (x * Math.PI)
    'The Taylor Series expansion of Sin(x)/x is used to limit rounding errors for small values of x
    If x < 0.01 And x > -0.01 Then
        Return 1.0 - x ^ 2 / 6.0 + x ^ 4 / 120.0
    End If
    Return Math.Sin(x) / x
End Function

http://www.wolframalpha.com/input/?i=taylor+series+sin+%28x%29+%2F+x&dataset=&equal=Submit

1

你需要做三个修改,

def gauss(x, A, mu, sigma):
    return A*exp(-1*(x[:]-mu)*(x[:]-mu)/sigma/sigma)

def sincSquare_mod(x, A, mu, sigma):
    x=np.array(x)
    return A * (np.sin(pi*(x[:]-mu)*sigma) / (pi*(x[:]-mu)*sigma))**2

fitdata = gauss(xpos,*p0)

1. 查看一下文档

2. 把 sin 替换成 numpy 里的版本,以便支持 array 的广播功能

3. 这很简单,对吧? :P

注意,我觉得你应该使用 p1, var_matrix = curve_fit(gauss,... 这个,而不是原问题里提到的那个,因为后者似乎没有解决方案。

撰写回答