Scipy.optimize.curve_fit 不适合
Scipy.optimize.curve_fit does not fit
假设我想使用 scipy.optimize.curve_fit
拟合正弦函数。我不知道函数的任何参数。为了获得频率,我进行傅立叶变换并猜测所有其他参数——振幅、相位和偏移。当 运行 我的程序时,我确实得到了一个适合但它没有意义。问题是什么?任何帮助将不胜感激。
import numpy as np
import matplotlib.pyplot as plt
import scipy as sp
ampl = 1
freq = 24.5
phase = np.pi/2
offset = 0.05
t = np.arange(0,10,0.001)
func = np.sin(2*np.pi*t*freq + phase) + offset
fastfft = np.fft.fft(func)
freq_array = np.fft.fftfreq(len(t),t[0]-t[1])
max_value_index = np.argmax(abs(fastfft))
frequency = abs(freq_array[max_value_index])
def fit(a, f, p, o, t):
return a * np.sin(2*np.pi*t*f + p) + o
guess = (0.9, frequency, np.pi/4, 0.1)
params, fit = sp.optimize.curve_fit(fit, t, func, p0=guess)
a, f, p, o = params
fitfunc = lambda t: a * np.sin(2*np.pi*t*f + p) + o
plt.plot(t, func, 'r-', t, fitfunc(t), 'b-')
您程序中的主要问题是对 scipy.optimize.curve_fit
的设计方式及其拟合函数的假设存在误解:
ydata = f(xdata, *params) + eps
这意味着 fit 函数必须将 x 值数组作为第一个参数,后跟函数参数(无特定顺序),并且必须 return y 值数组。这是一个例子,如何做到这一点:
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize
#t has to be the first parameter of the fit function
def fit(t, a, f, p, o):
return a * np.sin(2*np.pi*t*f + p) + o
ampl = 1
freq = 2
phase = np.pi/2
offset = 0.5
t = np.arange(0,10,0.01)
#is the same as fit(t, ampl, freq, phase, offset)
func = np.sin(2*np.pi*t*freq + phase) + offset
fastfft = np.fft.fft(func)
freq_array = np.fft.fftfreq(len(t),t[0]-t[1])
max_value_index = np.argmax(abs(fastfft))
frequency = abs(freq_array[max_value_index])
guess = (0.9, frequency, np.pi/4, 0.1)
#renamed the covariance matrix
params, pcov = scipy.optimize.curve_fit(fit, t, func, p0=guess)
a, f, p, o = params
#calculate the fit plot using the fit function
plt.plot(t, func, 'r-', t, fit(t, *params), 'b-')
plt.show()
如您所见,我还更改了绘图拟合函数的计算方式。您不需要其他功能 - 只需将 fit 函数与参数列表一起使用,fit 过程就会返回。
另一个问题是您调用了协方差数组 fit
- 覆盖了先前定义的函数 fit
。我也修好了。
P.S.: 当然现在你只能看到一条曲线,因为完美拟合覆盖了你的数据点。
假设我想使用 scipy.optimize.curve_fit
拟合正弦函数。我不知道函数的任何参数。为了获得频率,我进行傅立叶变换并猜测所有其他参数——振幅、相位和偏移。当 运行 我的程序时,我确实得到了一个适合但它没有意义。问题是什么?任何帮助将不胜感激。
import numpy as np
import matplotlib.pyplot as plt
import scipy as sp
ampl = 1
freq = 24.5
phase = np.pi/2
offset = 0.05
t = np.arange(0,10,0.001)
func = np.sin(2*np.pi*t*freq + phase) + offset
fastfft = np.fft.fft(func)
freq_array = np.fft.fftfreq(len(t),t[0]-t[1])
max_value_index = np.argmax(abs(fastfft))
frequency = abs(freq_array[max_value_index])
def fit(a, f, p, o, t):
return a * np.sin(2*np.pi*t*f + p) + o
guess = (0.9, frequency, np.pi/4, 0.1)
params, fit = sp.optimize.curve_fit(fit, t, func, p0=guess)
a, f, p, o = params
fitfunc = lambda t: a * np.sin(2*np.pi*t*f + p) + o
plt.plot(t, func, 'r-', t, fitfunc(t), 'b-')
您程序中的主要问题是对 scipy.optimize.curve_fit
的设计方式及其拟合函数的假设存在误解:
ydata = f(xdata, *params) + eps
这意味着 fit 函数必须将 x 值数组作为第一个参数,后跟函数参数(无特定顺序),并且必须 return y 值数组。这是一个例子,如何做到这一点:
import numpy as np
import matplotlib.pyplot as plt
import scipy.optimize
#t has to be the first parameter of the fit function
def fit(t, a, f, p, o):
return a * np.sin(2*np.pi*t*f + p) + o
ampl = 1
freq = 2
phase = np.pi/2
offset = 0.5
t = np.arange(0,10,0.01)
#is the same as fit(t, ampl, freq, phase, offset)
func = np.sin(2*np.pi*t*freq + phase) + offset
fastfft = np.fft.fft(func)
freq_array = np.fft.fftfreq(len(t),t[0]-t[1])
max_value_index = np.argmax(abs(fastfft))
frequency = abs(freq_array[max_value_index])
guess = (0.9, frequency, np.pi/4, 0.1)
#renamed the covariance matrix
params, pcov = scipy.optimize.curve_fit(fit, t, func, p0=guess)
a, f, p, o = params
#calculate the fit plot using the fit function
plt.plot(t, func, 'r-', t, fit(t, *params), 'b-')
plt.show()
如您所见,我还更改了绘图拟合函数的计算方式。您不需要其他功能 - 只需将 fit 函数与参数列表一起使用,fit 过程就会返回。
另一个问题是您调用了协方差数组 fit
- 覆盖了先前定义的函数 fit
。我也修好了。
P.S.: 当然现在你只能看到一条曲线,因为完美拟合覆盖了你的数据点。