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

Scipy curve_fit拟合双自然对数函数出现异常结果的技术求助

质谱数据双对数拟合异常问题

我正在开发质谱数据处理软件,尝试将原始数据集合y, t(y为质谱中某气体物种的强度,t为对应强度测量的时间戳)拟合成双自然对数函数。

使用的拟合函数

import numpy as np
from scipy.optimize import curve_fit

def double_ln_func(t, a, b, p, c, q, d):
    return a + b * np.log(p * t) + c * np.log(q * t)

def double_ln_fit(t, y):
    popt, pcov = curve_fit(double_ln_func, t, y)

    fitted_t = np.linspace(min(t), max(t), 100)
    fitted_y = double_ln_func(fitted_t, *popt)

    return fitted_t, fitted_y, popt

函数中一个自然对数项为正,对应记忆效应导致的强度增长;另一个为负,对应电离过程的消耗。多数情况下拟合结果合理,示例正常数据如下:

正常拟合数据

He 3798 Q1520_  2024-06-25T09:49:42 
time_sec    2.22    3.25    4.24    40.27
2.691   1.918947E-9 1.353086E-9 1.083636E-9 2.424798E-11
8.393   1.924420E-9 1.352441E-9 1.081825E-9 2.451031E-11
13.995  1.924468E-9 1.350765E-9 1.082597E-9 2.493171E-11
19.595  1.925282E-9 1.349962E-9 1.081301E-9 2.494261E-11
25.195  1.927887E-9 1.349370E-9 1.080510E-9 2.491214E-11
30.895  1.930570E-9 1.348243E-9 1.079783E-9 2.517592E-11
36.495  1.932480E-9 1.347466E-9 1.079611E-9 2.510602E-11
42.095  1.931847E-9 1.348131E-9 1.079237E-9 2.513002E-11
47.795  1.934760E-9 1.346782E-9 1.078437E-9 2.512803E-11
53.395  1.929853E-9 1.345735E-9 1.078367E-9 2.498039E-11
58.996  1.934834E-9 1.345541E-9 1.077280E-9 2.520110E-11
64.596  1.932654E-9 1.344552E-9 1.077504E-9 2.550219E-11

但在部分高散点数据(如4amu、40amu)中,拟合曲线会变成锯齿状且无合理参数意义,示例异常数据如下:

异常拟合数据

He 3800 CB1 2024-06-25T10:19:42 
time_sec    2.22    3.25    4.24    40.27
1.616   1.890576E-9 1.359579E-9 7.204719E-13 1.014118E-11
7.218   1.894592E-9 1.357168E-9 7.196407E-13 1.130713E-11
12.819  1.894756E-9 1.355699E-9 7.183293E-13 1.139818E-11
18.519  1.895724E-9 1.354677E-9 7.262793E-13 1.098621E-11
24.119  1.899128E-9 1.354235E-9 7.101848E-13 1.077834E-11
29.729  1.898467E-9 1.353402E-9 7.125748E-13 1.187576E-11
35.430  1.899100E-9 1.351661E-9 7.355859E-13 1.104034E-11
41.032  1.899836E-9 1.352259E-9 7.077889E-13 1.089571E-11
46.633  1.902685E-9 1.351637E-9 7.197934E-13 1.141361E-11
52.235  1.902119E-9 1.351389E-9 7.155005E-13 1.151000E-11
57.835  1.902982E-9 1.350957E-9 7.118936E-13 1.155836E-11
63.535  1.907762E-9 1.351266E-9 7.195685E-13 1.208988E-11

偶尔会出现OptimizeWarning: Covariance of the parameters could not be estimated警告,但警告频率不足以解释所有异常,其中4amu数据最容易出现拟合异常。

问题

  1. 为什么curve_fit会返回这类无意义的参数?
  2. 如何得到合理的拟合结果?
  3. 是否有更合适的拟合工具?

问题解答

1. 异常拟合的核心原因

(1)严重的参数冗余

你的双对数函数存在两处冗余:

  • 函数可化简为:a + b*ln(p*t) + c*ln(q*t) = (a + b*lnp + c*lnq) + (b+c)*ln(t),本质是单对数函数,b、p、c、q存在线性相关性,优化器无法确定唯一解;
  • 函数定义中的参数d完全未在返回值中使用,进一步加剧参数冗余,导致优化器陷入参数空间的平坦区域,随机返回一组满足误差的无意义参数。

(2)高噪声数据干扰

4amu这类数据噪声大,数据波动掩盖了对数趋势,优化器容易收敛到局部最小值,导致拟合曲线异常。

(3)无初始参数引导

curve_fit默认用全零初始参数,对于对数函数来说,初始值不合理会让优化器偏离正确参数空间,尤其在噪声大时更易出错。

2. 解决方法

(1)修复函数,消除参数冗余

删除无用参数d,并结合物理意义重构函数(保留增长/衰减的物理项,同时避免冗余):

# 保留物理意义的双对数形式:增长项正系数,衰减项负系数,p、q为正数
def double_ln_func(t, base, growth_coeff, decay_coeff, p, q):
    return base + growth_coeff * np.log(p * t) - decay_coeff * np.log(q * t)

(2)添加参数约束与初始值

通过bounds设置参数的物理范围,用p0提供初始值引导优化:

def constrained_double_ln_fit(t, y):
    # 根据正常数据拟合结果设置初始参数
    p0 = [1.9e-9, 1e-12, 1e-12, 1, 1]
    # 参数边界:base为基准强度,增长系数正,衰减系数正,p、q为正数
    bounds = (
        [1e-10, 0, 0, 1e-6, 1e-6],
        [2e-9, 1e-10, 1e-10, np.inf, np.inf]
    )
    popt, pcov = curve_fit(double_ln_func, t, y, p0=p0, bounds=bounds)
    
    fitted_t = np.linspace(min(t), max(t), 100)
    fitted_y = double_ln_func(fitted_t, *popt)
    
    return fitted_t, fitted_y, popt

(3)预处理高噪声数据

对噪声大的数据进行滑动平均平滑,降低噪声干扰:

def smooth_data(y, window_size=3):
    return np.convolve(y, np.ones(window_size)/window_size, mode='same')

平滑后再执行拟合,能显著提升稳定性。

3. 替代拟合工具

  • scipy.optimize.least_squares:比curve_fit更灵活,支持自定义损失函数和严格参数约束,适合复杂模型与噪声数据;
  • lmfit库:封装scipy优化工具,提供直观的参数管理、约束设置和结果分析,专为物理模型拟合设计;
  • statsmodels库:提供统计建模相关拟合工具,适合需要统计显著性分析的场景。

内容的提问来源于stack exchange,提问作者ohshitgorillas

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.21 16:30:55