如何使用 pylab 和 numpy 为我的数据拟合正弦曲线? [英] How do I fit a sine curve to my data with pylab and numpy?

查看:16
本文介绍了如何使用 pylab 和 numpy 为我的数据拟合正弦曲线?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图表明经济遵循相对正弦的增长模式.我正在构建一个 python 模拟,以表明即使我们让某种程度的随机性占据上风,我们仍然可以产生一些相对正弦的东西.

I am trying to show that economies follow a relatively sinusoidal growth pattern. I am building a python simulation to show that even when we let some degree of randomness take hold, we can still produce something relatively sinusoidal.

我对我生成的数据很满意,但现在我想找到某种方法来获得与数据非常匹配的正弦图.我知道您可以进行多项式拟合,但您可以进行正弦拟合吗?

I am happy with the data I'm producing, but now I'd like to find some way to get a sine graph that pretty closely matches the data. I know you can do polynomial fit, but can you do sine fit?

推荐答案

您可以使用 最小二乘优化 函数在 scipy 中拟合任意函数到另一个函数.在拟合 sin 函数的情况下,要拟合的 3 个参数是偏移 ('a')、幅度 ('b') 和相位 ('c').

You can use the least-square optimization function in scipy to fit any arbitrary function to another. In case of fitting a sin function, the 3 parameters to fit are the offset ('a'), amplitude ('b') and the phase ('c').

只要您提供对参数的合理初步猜测,优化就应该很好地收敛.幸运的是,对于正弦函数,对其中 2 个的初步估计很容易:偏移量可以通过取数据的均值和幅度通过 RMS (3*标准偏差/sqrt(2)).

As long as you provide a reasonable first guess of the parameters, the optimization should converge well.Fortunately for a sine function, first estimates of 2 of these are easy: the offset can be estimated by taking the mean of the data and the amplitude via the RMS (3*standard deviation/sqrt(2)).

注意:作为稍后的编辑,还添加了频率拟合.这不能很好地工作(可能导致极差的拟合).因此,请自行决定使用,我的建议是不要使用频率拟合,除非频率误差小于几个百分点.

Note: as a later edit, frequency fitting has also been added. This does not work very well (can lead to extremely poor fits). Thus, use at your discretion, my advise would be to not use frequency fitting unless frequency error is smaller than a few percent.

这导致以下代码:

import numpy as np
from scipy.optimize import leastsq
import pylab as plt

N = 1000 # number of data points
t = np.linspace(0, 4*np.pi, N)
f = 1.15247 # Optional!! Advised not to use
data = 3.0*np.sin(f*t+0.001) + 0.5 + np.random.randn(N) # create artificial data with noise

guess_mean = np.mean(data)
guess_std = 3*np.std(data)/(2**0.5)/(2**0.5)
guess_phase = 0
guess_freq = 1
guess_amp = 1

# we'll use this to plot our first estimate. This might already be good enough for you
data_first_guess = guess_std*np.sin(t+guess_phase) + guess_mean

# Define the function to optimize, in this case, we want to minimize the difference
# between the actual data and our "guessed" parameters
optimize_func = lambda x: x[0]*np.sin(x[1]*t+x[2]) + x[3] - data
est_amp, est_freq, est_phase, est_mean = leastsq(optimize_func, [guess_amp, guess_freq, guess_phase, guess_mean])[0]

# recreate the fitted curve using the optimized parameters
data_fit = est_amp*np.sin(est_freq*t+est_phase) + est_mean

# recreate the fitted curve using the optimized parameters

fine_t = np.arange(0,max(t),0.1)
data_fit=est_amp*np.sin(est_freq*fine_t+est_phase)+est_mean

plt.plot(t, data, '.')
plt.plot(t, data_first_guess, label='first guess')
plt.plot(fine_t, data_fit, label='after fitting')
plt.legend()
plt.show()

我假设您知道正弦波中的周期数.如果您不这样做,则适应起来会有些棘手.您可以尝试通过手动绘图来猜测周期数,并尝试将其优化为您的第 6 个参数.

I assumed that you know the number of periods in the sine-wave. If you don't, it's somewhat trickier to fit. You can try and guess the number of periods by manual plotting and try and optimize it as your 6th parameter.

这篇关于如何使用 pylab 和 numpy 为我的数据拟合正弦曲线?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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