非线性曲线拟合参数标准差异常偏小问题咨询
正弦信号非线性拟合的参数标准差异常问题
我正在对示波器采集的随时间变化的正弦电压信号执行非线性曲线拟合,目标是评估实验系统(sl)信号相对于函数发生器(sa)信号的相位。
拟合模型为:V0 + Asin(phi + phase),优化参数为[V0, A, phase](分别对应电压偏移量、振幅、相位),其中phi = 2×π×频率×t = ω×t。我的方案是分别拟合两个信号,得到它们相对于初始时间t=0的相位,再通过相减计算相对相位差。
目前使用SciPy的curve_fit()函数已得到合理的优化参数值,但发现参数的标准差量级仅为1E-4至1E-5——即便真实振幅与拟合振幅存在明显可见差异,误差值依然极小,这显然不合理。说明:我通过对协方差矩阵pcov的对角线元素取平方根得到标准差。不清楚问题出在哪里,希望得到指导。
示例代码
# import standard libraries import numpy as np import matplotlib.pyplot as plt import pandas as pd from scipy.optimize import curve_fit, leastsq from scipy.signal import savgol_filter # --- Load CSV --- # Tektronix CSVs have a header of 1 lines idx = 0 path = f"f_mod_{idx}.csv" data = np.loadtxt(path, delimiter=",", skiprows=1) t = data[:,0] # seconds s_afg = np.array(data[:,2]) # signal from AFG (volts) s_mi = np.array(data[:,1]) # signal from interferometer (volts) # Smooth the signal using Savitzky-Golay filter sl = savgol_filter(s_mi, window_length=101, polyorder=3) sa = savgol_filter(s_afg, window_length=101, polyorder=3) # Frequency deviations (in MHz) f_dev_vals = [150, 166, 180, 200, 207.5] # Modulation frequencies (in kHz) f_mod_vals = [50, 100, 200, 300, 400, 500, 600, 700, 800, 900, 1000] # Select parameters and convert to SI units (Hz) idx_dev = 0 idx_mod = idx f_dev = f_dev_vals[idx_dev] * 1e6 f_mod = f_mod_vals[idx_mod] * 1e3 # Calculate phase phi = 2 * np.pi * f_mod * t # Test initial guess for MI A0 = ( max(sl) - min(sl)) /2 v0 = 2.453 fac = -0.85 g = v0 + (A0 * np.sin(2 * np.pi *f_mod * t + fac*np.pi)) # Plot the results plt.figure(figsize=(10, 6)) plt.plot(t, sl, 'b-', label='MI') plt.plot(t, g, 'r-', label='Guess') plt.legend() plt.xlabel('time ($\mu s$)') plt.ylabel('Voltage (V)') plt.title('Phase Modulation Fitting with Least Square') plt.show() # Define the function to model the modulated signal def signal_model(phi,V0, A, phase): """This function produces a sinusoidal signal of the form Asin(ωt+ϕ) where : - A : amplitude - ω = 2πf : angular frequency - ϕ = phase Inputs: - params : guess parameters - V0 : initial photodiode voltage - A : guess amplitude - phase : guess phase - s : voltage signal (in V) - phi : phase difference (in rad) Returns: - waveform """ # ------------------- # "bright": constructive, phase = 0 # "dark": destructive, phase = pi # "slope": half-fringe, phase = pi/2 # ------------------- # Model of interference intensity model = V0 + (A * np.sin(phi + phase)) return model # ------------------- # Initial guesses # for AFG v0a = 0.0 A0a = ( max(sa) - min(sa)) /2 phase0a = 0.15*np.pi p0a = [v0a, A0a, phase0a] # [offset, amplitude, phase] # for MI signal v0l = v0 A0l = A0 phase0l = fac*np.pi p0l = [v0l, A0l, phase0l] # [offset, amplitude, phase] # ------------------- # Perform the least square fit on both signals resulta, successa = curve_fit(signal_model, phi, sa, p0=p0a) resultl, successl = curve_fit(signal_model, phi, sl, p0=p0l) # Extract the optimized parameters V0_opta, A_opta, phase_opta = resulta V0_optl, A_optl, phase_optl = resultl # Extract standard deviations perr_a = np.sqrt(np.diag(successa)) perr_l = np.sqrt(np.diag(successl)) V_opta_err, A_opta_err, phase_opta_err = perr_a V_optl_err, A_optl_err, phase_optl_err = perr_l # Create fitted and guess functions for the signals fit_a = V0_opta + (A_opta * np.sin(phi + phase_opta)) fit_l = V0_optl + (A_optl * np.sin(phi + phase_optl)) guess = v0l + (A0l * np.sin(phi + phase0l)) # calculate relative phases (in units of π) using the guess and fit parameters phase_rel_f = (phase_optl - phase_opta) / np.pi phase_rel_g = (phase0l - phase0a) / np.pi # Plot the results plt.figure(figsize=(10, 6)) plt.plot(t*1e6, sl, 'grey', label='MI') plt.plot(t*1e6, fit_l, 'r--', label='Fit MI') plt.plot(t*1e6, sa, 'purple', label='AFG') plt.plot(t*1e6, fit_a, 'b--', label='Fit AFG') plt.plot(t*1e6, guess, 'g-', label='Guess') plt.xlabel('time ($\mu s$)') plt.ylabel('Voltage (V)') plt.title(f'Frequency Modulation Fitting with Least Square | f_{"dev"} ={f_dev*1e-6} MHz, f_mod = {f_mod*1e-3} kHz') plt.legend() plt.show() # Print the results print(f"Guess parameters for MI signal: Amplitude = {A0l:.4f} V, Phase = {phase0l:.1f}") print(f"Optimized parameters for MI signal: Amplitude = {A_optl:.4f} ± {A_optl_err:.4f}V, Phase = {phase_optl :.4f} ± {phase_optl_err :.4f}") print(f"Optimized parameters for AFG signal: Amplitude = {A_opta:.4f} ± {A_opta_err:.4f} V, Phase = {phase_opta :.4f} ± {phase_opta_err :.4f} ") print(f"The relative phase ΔΦ (using guess): {(phase_rel_g):.4f} π") print(f"The relative phase ΔΦ (using fit): {(phase_rel_f):.4f} π")
拟合数据说明
示波器采集的原始信号与拟合曲线对比可见,部分信号与拟合结果存在明显偏差,但参数标准差仍维持在极小量级。
内容的提问来源于stack exchange,提问作者Yolan Ankaine
相关产品推荐
相关产品推荐

