You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

非线性曲线拟合参数标准差异常偏小问题咨询

正弦信号非线性拟合的参数标准差异常问题

我正在对示波器采集的随时间变化的正弦电压信号执行非线性曲线拟合,目标是评估实验系统(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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.12 03:09:52