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

如何使用scipy curve_fit拟合多自变量函数求解未知参数

问题解答

结论

完全可以用curve_fit实现多自变量函数拟合,但你当前写的函数定义方式不符合curve_fit的传参规则,直接调用会报错。

正确使用curve_fit的修改方法

curve_fit要求目标函数的第一个入参必须承载全部自变量,不能把不同自变量拆成多个独立位置参数传入。你需要把x1、x2、x3打包成一个多维数组传入目标函数,再在函数内部拆分出各个自变量即可。
以你写的三自变量func2为例,修改后的可运行代码如下:

import numpy as np
from scipy.optimize import curve_fit

# 原始数据转numpy数组,方便矩阵运算
x1 = np.array([3,2,1])
x2 = np.array([3,4,2])
x3 = np.array([1,2,4])
y1 = np.array([5,7,9])

# 把所有自变量打包成形状为(自变量个数, 样本数)的数组
x = np.vstack([x1, x2, x3])

def func2(x, a1, b1, c1, a2, b2, c2, a3, b3, c3, d):
    # 从打包的x数组中拆分出各个自变量
    x1, x2, x3 = x
    return (a1*x1**3 + b1*x1**2 + c1*x1) + (a2*x2**3 + b2*x2**2 + c2*x2) + (a3*x3**3 + b3*x3**2 + c3*x3) + d

# 调用拟合,p0为参数初始值,不传默认全1,维度和待拟合参数数量一致即可
popt, pcov = curve_fit(func2, x, y1, p0=np.ones(10))
print("拟合参数顺序为a1,b1,c1,a2,b2,c2,a3,b3,c3,d:", popt)

拟合注意事项

  • 实际场景中上百组样本完全满足10个待拟合参数的自由度要求,不会出现欠定问题
  • 如果拟合出现不收敛的情况,可以根据对参数的先验认知给p0传入更贴近真实值的初始值,能大幅提升收敛速度和拟合准确性
  • 如果数据存在异常值,可以给curve_fit传入sigma参数为不同样本设置权重,降低异常值对拟合结果的干扰

更适配的参数求解方法

你定义的目标函数本质是关于待拟合参数的线性模型:所有待求参数a1、b1、c1...d都是以一次线性系数的形式存在,不存在参数的非线性变换(比如参数相乘、参数位于指数/三角函数位这类情况)。这种场景不需要用非线性最小二乘优化的curve_fit,直接用线性最小二乘求解析解效率更高,也完全不会存在局部最优、不收敛的问题。
线性最小二乘实现非常简单,只需要先构造特征矩阵:每一行对应一个样本,每一列对应一个基函数(比如第一列是x1³、第二列是x1²、第三列是x1、第四列是x2³……最后一列全是1对应截距d),然后直接调用np.linalg.lstsq就能一步算出所有参数,代码示例:

# 构造特征矩阵,每一列对应一个参数相乘的基项
X = np.column_stack([
    x1**3, x1**2, x1,
    x2**3, x2**2, x2,
    x3**3, x3**2, x3,
    np.ones(len(x1)) # 对应截距d
])
# 求解线性最小二乘
popt_linear, residuals, rank, s = np.linalg.lstsq(X, y1, rcond=None)
print("线性最小二乘得到的参数:", popt_linear)

这种方法计算速度比curve_fit快几个量级,结果和非线性优化收敛到全局最优的结果完全一致,更适配你的场景。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.29 02:12:31