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

如何自定义scipy.curve_fit拟合函数组合实现灵活峰解卷积?

实现方案

你可以通过函数工厂动态生成符合curve_fit参数要求的组合拟合函数,不需要每次手动写固定的Combined定义,具体实现步骤如下:


步骤1:建立拟合函数映射表

先把所有预定义的基线、峰函数都存入映射字典,方便通过字符串名称调用,同时可自动获取每个函数的拟合参数数量(第一个参数x不算入拟合参数):

import scipy.optimize as opt
import numpy as np

# 你已有的基线函数
def ZeroOrder(x,a):
    return a
def Linear(x,a,b):
    return a+b*x
def SecondOrder(x,a,b,c):
    return a+b*x+c*x**2

# 补充你用到的高斯峰定义(本地已有可跳过)
def Gaussian(x, a, mu, sigma):
    return a * np.exp(-(x - mu)**2 / (2 * sigma**2))

# 函数映射表,后续新增洛伦兹、Voigt等峰函数直接往这里加即可
FUNC_MAP = {
    'ZeroOrder': ZeroOrder,
    'Linear': Linear,
    'SecondOrder': SecondOrder,
    'Gaussian': Gaussian
}

步骤2:编写组合函数生成工厂

这个工厂函数会根据你传入的基线类型、峰类型列表,自动返回符合curve_fit要求的、签名为f(x, *params)的组合函数:

def generate_combined_func(baseline_type: str, peak_types: list):
    """
    生成符合curve_fit要求的组合拟合函数
    :param baseline_type: 基线函数名称,对应FUNC_MAP的key
    :param peak_types: 峰函数名称列表,有几个峰就传几个元素
    :return: 组合拟合函数、所需总拟合参数个数
    """
    # 读取基线函数和对应参数个数
    baseline_func = FUNC_MAP[baseline_type]
    baseline_param_num = baseline_func.__code__.co_argcount - 1
    # 读取所有峰函数和对应参数个数
    peak_funcs = [FUNC_MAP[p] for p in peak_types]
    peak_param_nums = [f.__code__.co_argcount - 1 for f in peak_funcs]
    total_param_num = baseline_param_num + sum(peak_param_nums)

    def combined(x, *params):
        assert len(params) == total_param_num, f"参数个数不匹配,需要{total_param_num}个,实际传入{len(params)}个"
        # 计算基线
        res = baseline_func(x, *params[:baseline_param_num])
        # 逐个累加峰信号
        ptr = baseline_param_num
        for func, param_num in zip(peak_funcs, peak_param_nums):
            res += func(x, *params[ptr:ptr+param_num])
            ptr += param_num
        return res
    return combined, total_param_num

步骤3:使用示例

你需要调整基线/峰类型时,仅需要修改工厂函数的入参即可,不需要重写组合逻辑:

# 示例1:生成 线性基线 + 3个高斯峰 的组合函数,和你原来的逻辑完全对齐
combined_func, param_count = generate_combined_func(
    baseline_type='Linear',
    peak_types=['Gaussian', 'Gaussian', 'Gaussian']
)
# 初始参数p0长度需要等于返回的param_count,这里和你原参数长度一致(2+3*3=11)
p0 = [0.1, 0.1, 115, 508.33, 7.1, 130, 508.33, 7.1, 165.84, 508.33, 7.1]
# 直接传入curve_fit即可使用
popt, pcov = opt.curve_fit(
    combined_func, 
    data[10][0], 
    data[10][1], 
    method='lm', 
    check_finite=True, 
    p0=p0
)

# 示例2:切换为 零阶基线 + 2个洛伦兹峰,仅需要修改入参(需要先把Lorentzian加入FUNC_MAP)
# combined_func, param_count = generate_combined_func(
#     baseline_type='ZeroOrder',
#     peak_types=['Lorentzian', 'Lorentzian']
# )
# 对应调整p0长度为1+2*3=7即可使用

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 16:36:03