简体   繁体   English

使用边界时如何优化我的鼻窦拟合?

[英]How can i optimize my sinus fitting when using bounds?

i'm trying to do a sinus-fit on a given part of a curve.我正在尝试对曲线的给定部分进行正弦拟合。 There a two restrictions.有两个限制。 First the offset of my fitted sinus-curve should be 0, second the amplitude of my fitted sinus-curve should be identically to the minimum value of my original data.首先我拟合的正弦曲线的偏移量应该是 0,其次我拟合的正弦曲线的幅度应该与我的原始数据的最小值相同。

When i'm using my code below, the fitting looks like in the picture i added ( 1 ).当我使用下面的代码时,配件看起来像我添加的图片 ( 1 )。 In my opinion the period of the sinus-function should be higher.在我看来,窦函数的周期应该更高。 The fitted curve only matches at the minimum with my original data, the fitting-curve isn't wide enough.拟合曲线仅与我的原始数据最低匹配,拟合曲线不够宽。 When i don't use the bounds for c and A my fitting looks good ( 2 ).当我不使用 c 和 A 的边界时,我的拟合看起来不错( 2 )。 What am i doing wrong?我究竟做错了什么? Is there a way to modify the fitting so that the sinus-curves fits better when using the bounds for A and c?有没有办法修改拟合,以便在使用 A 和 c 的边界时正弦曲线更适合?

Fitting without bounds拟合无界限

Fitting with bounds有界拟合

Edit: Something thing I mentioned is, that the fitting extremely depends on the start value of the amplitude (ff_guess).编辑:我提到的事情是,拟合非常依赖于振幅的起始值(ff_guess)。 When I manually change it to X (eg. 10 or 30), than the fitted sinus curve always shows an amplitude near to X (10.3 or 32.5).当我手动将其更改为 X(例如 10 或 30)时,拟合的正弦曲线始终显示接近 X(10.3 或 32.5)的幅度。 Is there any setting I haven't considered yet, that prevents the optimizer from varying the amplitude value?有没有我还没有考虑过的设置,可以防止优化器改变幅度值?

import matplotlib.pyplot as plt
from matplotlib.ticker import FormatStrFormatter
from matplotlib.pyplot import figure, rcParams
import numpy as np
from scipy.optimize import curve_fit


#Time
t = [313.544, 313.545, 313.546, 313.547, 313.548, 313.549, 313.55,  313.551, 313.552, 313.553, 313.554, 313.555, 313.556, 313.557, 313.558, 313.559, 313.56,  313.561, 313.562, 313.563, 313.564, 313.565, 313.566, 313.567,]

#y-Values
s = [0.911188, -0.43135, -1.80997, -3.27816, -4.85784, -6.59428, -8.2214, -9.53617, -10.6892, -11.6003, -12.0844, -12.0524, -11.9749, -11.4891, -10.6131, -9.49873, -8.1154, -6.41442, -5.09357, -3.99165, -2.72991, -1.71446, -0.56306, 0.440741]
   
    
#fourier frequency
ff = np.fft.fftfreq(len(t), (t[1]-t[0]))                               
#fourier amplitude
fa = abs(np.fft.fft(s, len(t)))                                            
#Position of maximum Amplitude 
pos_amax = np.argmax(fa[1:])+1                                        
#Frequency at maximum Amplitude (w/2pi)
ff_max = abs(ff[pos_amax])                                             
ff_guess = ff_max   
T_guess = 1000/ff_max 
#A_guess = np.std(s) *2. **0.5                                          
A_guess = min(s)
#c_guess = np.mean(s)
c_guess = 0
#First Guess for all paramters                           
f_guess = np.array([A_guess, 2*np.pi*ff_guess, 0., c_guess])  
#Sinus_Curve
def sin_func(t, A, w, phi, c):
   return A * np.sin(w*t + phi) + c    
#Defining Bounds for A and c
c_bound = 0.1
A_bound = min(s)
#Bounds Array for curve_fit
param_bounds=([1.01*A_bound, -np.inf, -np.inf, -1*c_bound],[0.99*A_bound, np.inf, np.inf, c_bound])
popt, pcov = curve_fit(sin_func, t, s, p0=f_guess, bounds=param_bounds, maxfev=10000000)
#popt, pcov = curve_fit(sin_func, t, s, p0=f_guess, maxfev=10000000)
#
A, w, phi, c = popt 
f = w/(2.*np.pi)
T = 1000/f

t = np.array(t)  
s = np.array(s)

plt.figure(1)
#Generate Sinus Function
s_fit = A * np.sin(w*t + phi) + c
#Plotting
rcParams['figure.figsize'] =10, 5
fig, ax = plt.subplots()  
plt.plot(t, s, "b", label="Original")     
plt.plot(t, s_fit, 'k--', label="Fitting")  
ytitle='ytitle'
xtitle='xtitle'
ax.set(xlabel=xtitle, ylabel=ytitle)
ax.xaxis.set_major_formatter(FormatStrFormatter('%.2f'))               
ax.yaxis.set_major_formatter(FormatStrFormatter('%.2f'))  
ax.grid()
#Sidetext
ausgabe = ("Sinus-Fit \nAmplitude = {:.2f} m/s^2 \nPeriode = {:.2f} ms \nOffset = {:.2f} m/s^2".format(A, abs(T), c))
plt.text(0.795, 0.7, ausgabe, family="sans-serif", fontsize=10, ha='left', va='top', transform=fig.transFigure)  
box = ax.get_position()
ax.set_position([box.x0, box.y0, box.width * 0.85, box.height]) 
plt.show()

If the amplitude is fixed and offset is supposedly zero, why fitting them in the first place.如果振幅是固定的并且偏移量应该为零,那么为什么首先要拟合它们。 Moreover, there is no need for fft to estimate parameters, as there is a simple linear method.此外,fft 不需要估计参数,因为有一个简单的线性方法。

Looks like this:看起来像这样:


import matplotlib.pyplot as plt
import numpy as np
from scipy.optimize import curve_fit
from scipy.integrate import cumtrapz


#Time
t = np.array([
    313.544, 313.545, 313.546, 313.547, 313.548, 313.549, 313.55,
    313.551, 313.552, 313.553, 313.554, 313.555, 313.556, 313.557,
    313.558, 313.559, 313.56,  313.561, 313.562, 313.563, 313.564,
    313.565, 313.566, 313.567
])
# ~t -= 313.544

#y-Values
s = np.array([
    0.911188, -0.43135, -1.80997, -3.27816, -4.85784, -6.59428,
    -8.2214, -9.53617, -10.6892, -11.6003, -12.0844, -12.0524,
    -11.9749, -11.4891, -10.6131, -9.49873, -8.1154, -6.41442,
    -5.09357, -3.99165, -2.72991, -1.71446, -0.56306, 0.440741
])

amp = np.max( np.abs( s ) )

def sine(t, w, f ):
    return amp * np.sin( w * t + f )

Sy = cumtrapz( s, x=t, initial = 0 )
SSy = cumtrapz( Sy, x=t, initial = 0 )
VMXT = np.array( [ s, t, np.ones( len( t ) ) ] )
VMX = np.transpose( VMXT )
A = np.dot( VMXT, VMX )
SV = np.dot( VMXT, SSy )
AI = np.linalg.inv( A )
alpha = np.dot( AI , SV )
wstart = np.sqrt( -1 / alpha[0] )


VMXT = np.array( [ np.sin( wstart * t ), np.cos( wstart * t ) ] )
VMX = np.transpose( VMXT )
A = np.dot( VMXT, VMX )
SV = np.dot( VMXT, s )
AI = np.linalg.inv( A )
alpha = np.dot( AI , SV )
phistart = np.arctan2( alpha[1], alpha[0] )


op, cv = curve_fit( sine, t, s, p0=( wstart, phistart ) )
print( op )
yth = sine( t, *op )
fig = plt.figure()
ax = fig.add_subplot( 1, 1, 1 )
ax.plot( t, s )
ax.plot( t, yth )
plt.show()

Works just fine.工作得很好。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 Scipy:使用optimize.leastsq时拟合参数的界限 - Scipy: bounds for fitting parameter(s) when using optimize.leastsq 当将正弦拟合为周期数据时,如何改善scipy.optimize.curve_fit参数的初始猜测,否则如何改善拟合? - How can I improve initial guess of parameters for scipy.optimize.curve_fit when fitting sines to periodic data, or improve the fitting otherwise? 如何使用 dict 优化我的代码? - How can I do to optimize my code using dict? 如何优化我的代码? (建议) - How can i optimize my codes ? (Suggestions) 如何使用scipy.optimize.least-squares创建提供残差以拟合阻抗数据的函数? - How should I create the function that provides the residuals for fitting of impedance data using scipy.optimize.least-squares? 我怎样才能很好地预测一个看起来像正弦波的图案幅度的增加趋势,上面有一些噪音 - How can I predict in a good way an increasing trend of the amplitude of a pattern looking like sinus wave with some noise on it 如何为我的西班牙语翻译程序优化我的代码? - How can I optimize my code for my Spanish Translation Program? 使用RegularGridInterpolator时如何仅在边界外使用最近邻插值 - How can I use nearest neighbor interpolation only outside of bounds when using RegularGridInterpolator 如何在python中定义“optimize.minimize”的边界? - how can define bounds for " optimize.minimize" in python? 如何检查输入是否超出字典列表的范围? - How can I check if an input is outside the bounds of my dictionary list?
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM