尝试使用scipy将trig函数拟合到数据 [英] Trying to fit a trig function to data with scipy
问题描述
我正在尝试使用 scipy.optimize.curve_fit
拟合一些数据.我已经
其中蓝色是数据,橙色是合适的.显然我在做错事.有指针吗?
如果未提供用于初始猜测参数 p0
的值,则假定值为 1
为他们每个人.从文档中:
p0:类似array_,可选
参数的初始猜测(长度N).如果为None,则初始值将全部为1(如果可以使用自省功能确定函数的参数数量,否则将引发ValueError).
由于您的数据具有非常大的x值和非常小的y值,因此 1
的初始猜测值与实际解决方案相距甚远,因此优化程序不会收敛.您可以通过提供合适的初始参数值(可以从数据中猜测/近似)来帮助优化器:
- 幅度:
A =(y.max()-y.min())/2
- 偏移量:
C =(y.max()+ y.min())/2
频率:在这里,我们可以通过乘以连续的y值来估算过零的次数,并检查哪些乘积小于零.该数字除以总的x范围即可得出频率,为了获得频率,以 - 相移:可以设置为零,
dphi = 0
pi
为单位,我们可以将该数字乘以 pi
: y_shifted = y- 抵消;oemga = np.pi * np.sum(y_shifted [:-1] * y_shifted [1:]< 0)/(t.max()-t.min())
因此,总而言之,可以使用以下初始参数猜测:
offset =(y.max()+ y.min())/2y_shifted = y-偏移量p0 =((y.max()-y.min())/2,np.pi * np.sum(y_shifted [:-1] * y_shifted [1:]< 0)/(t.max()-t.min()),0,抵消)popt,pcov = curve_fit(func_cos,t,y,p0 = p0)
哪一个给我以下拟合函数:
I am trying to fit some data using scipy.optimize.curve_fit
. I have read the documentation and also this StackOverflow post, but neither seem to answer my question.
I have some data which is simple, 2D data which looks approximately like a trig function. I want to fit it with a general trig function
using scipy
.
My approach is as follows:
from __future__ import division
import numpy as np
from scipy.optimize import curve_fit
#Load the data
data = np.loadtxt('example_data.txt')
t = data[:,0]
y = data[:,1]
#define the function to fit
def func_cos(t,A,omega,dphi,C):
# A is the amplitude, omega the frequency, dphi and C the horizontal/vertical shifts
return A*np.cos(omega*t + dphi) + C
#do a scipy fit
popt, pcov = curve_fit(func_cos, t,y)
#Plot fit data and original data
fig = plt.figure(figsize=(14,10))
ax1 = plt.subplot2grid((1,1), (0,0))
ax1.plot(t,y)
ax1.plot(t,func_cos(t,*popt))
This outputs:
where blue is the data orange is the fit. Clearly I am doing something wrong. Any pointers?
If no values are provided for initial guess of the parameters p0
then a value of 1
is assumed for each of them. From the docs:
p0 : array_like, optional
Initial guess for the parameters (length N). If None, then the initial values will all be 1 (if the number of parameters for the function can be determined using introspection, otherwise a ValueError is raised).
Since your data has very large x-values and very small y-values an initial guess of 1
is far from the actual solution and hence the optimizer does not converge. You can help the optimizer by providing suitable initial parameter values that can be guessed / approximated from the data:
- Amplitude:
A = (y.max() - y.min()) / 2
- Offset:
C = (y.max() + y.min()) / 2
- Frequency: Here we can estimate the number of zero crossing by multiplying consecutive y-values and check which products are smaller than zero. This number divided by the total x-range gives the frequency and in order to get it in units of
pi
we can multiply that number bypi
:y_shifted = y - offset; oemga = np.pi * np.sum(y_shifted[:-1] * y_shifted[1:] < 0) / (t.max() - t.min())
- Phase shift: can be set to zero,
dphi = 0
So in summary, the following initial parameter guess can be used:
offset = (y.max() + y.min()) / 2
y_shifted = y - offset
p0 = (
(y.max() - y.min()) / 2,
np.pi * np.sum(y_shifted[:-1] * y_shifted[1:] < 0) / (t.max() - t.min()),
0,
offset
)
popt, pcov = curve_fit(func_cos, t, y, p0=p0)
Which gives me the following fit function:
这篇关于尝试使用scipy将trig函数拟合到数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!