尝试使用scipy将trig函数拟合到数据 [英] Trying to fit a trig function to data with scipy

查看:52
本文介绍了尝试使用scipy将trig函数拟合到数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用 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范围即可得出频率,为了获得频率,以 pi 为单位,我们可以将该数字乘以 pi : y_shifted = y- 抵消;oemga = np.pi * np.sum(y_shifted [:-1] * y_shifted [1:]< 0)/(t.max()-t.min())
  • 相移:可以设置为零, dphi = 0

因此,总而言之,可以使用以下初始参数猜测:

  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 by pi: 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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆