Python curve_fit传参报错:需2个参数却传入15个的解决方案咨询
解决SciPy curve_fit参数化传参问题
问题背景
使用SciPy的curve_fit做拟合时,希望通过数组形式传递系数参数,实现参数化(后续调整系数数量无需修改函数代码)。但直接用数组作为函数第二个参数时触发报错,将系数拆分为单个独立参数则可正常运行,需要解决该兼容问题。
原报错代码
import pandas as pd import matplotlib.pyplot as plt import numpy as np from scipy.optimize import curve_fit import sys, re, argparse, os, json def column(matrix, i): return [row[i] for row in matrix] inputs = [[62, 15, 25, 10, 14, 7.04, 16.88, 24.48, 427219, 648745, -3.067, 3081350.0, 2], [53, 14, 32, 0, 37, 28.12, 35.94, 22.37, 403760, 516128, 0.048, 2857308.0, 2]] output = [50,60] numP = len(inputs[0]) print("nump ",numP) p = [] for i in range(0,int(numP)): p.append(column(inputs,i)) newX = np.vstack((p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12])) def testLinear3(X,coefficients): p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12] = X c = [] for i in range(0,len(coefficients)): c.append(coefficients[i]) ret = c[0]*p[0] + c[1]*p[1] + c[2]*p[2] + c[3]*p[3] + c[4]*p[4] + c[5]*p[5] + c[6]*p[6] + c[7]*p[7] + c[8]*p[8]+ c[9]*p[9] + c[10]*p[10] + c[11]*p[11] + c[12]*p[12] + c[13] return ret coefficients = [2.0]*(13+1) popt,pcov = curve_fit(testLinear3,newX,output,coefficients)
报错信息
TypeError Traceback (most recent call last) Input In [281], in <cell line: 19>() 17 #coefficients = np.array([2.0]*(13+1),dtype = float) 18 coefficients = [2.0]*(13+1) ---> 19 popt,pcov = curve_fit(testLinear3,newX,output,coefficients) 483 def func_wrapped(params): ---> 484 return func(xdata, *params) - ydata TypeError: testLinear3() takes 2 positional arguments but 15 were given
可运行的硬编码参数版本
def testLinear2(X,c0,c1,c2,c3,c4,c5,c6,c7,c8,c9,c10,c11,c12,c13): p[0],p[1],p[2],p[3],p[4],p[5],p[6],p[7],p[8],p[9],p[10],p[11],p[12] = X ret = 0 ret = c0 + c1*p[0] + c2*p[1] + c3*p[2] + c4*p[3] + c5*p[4] + c6*p[5] + c7*p[6] + c8*p[7] ret += c9*p[8]+ c10*p[9] + c11*p[10] + c12*p[11] + c13*p[12] return ret
问题原因
curve_fit的工作机制是:将传入的初始参数列表自动解包为多个独立参数,传递给自定义拟合函数。原代码中testLinear3仅接受X和coefficients两个参数,但curve_fit会把初始的14个系数拆成14个独立参数,加上X后总共传递15个参数,导致参数数量不匹配报错。
解决方案
修改自定义拟合函数,使用**可变参数*args**接收所有系数参数,再将其打包为数组进行计算。这样无论后续调整多少个系数,都无需修改函数定义。同时可以简化原代码中的数据处理逻辑(用numpy数组转置替代手动提取列)。
优化后的完整代码
import numpy as np from scipy.optimize import curve_fit # 输入数据转换为numpy数组,方便处理 inputs = np.array([[62, 15, 25, 10, 14, 7.04, 16.88, 24.48, 427219, 648745, -3.067, 3081350.0, 2], [53, 14, 32, 0, 37, 28.12, 35.94, 22.37, 403760, 516128, 0.048, 2857308.0, 2]]) output = np.array([50, 60]) # 转置后每一行对应一个特征(和原代码newX结构一致) newX = inputs.T def testLinear(X, *args): # 将可变参数转为numpy数组 coefficients = np.array(args) # X是(13,2)的数组,每一行是一个特征的所有样本值 # 计算线性组合:系数前13个对应特征,最后一个是常数项 ret = np.sum(coefficients[:-1] * X, axis=0) + coefficients[-1] return ret # 初始参数:特征数+1个常数项 num_features = inputs.shape[1] initial_coeffs = [2.0] * (num_features + 1) popt, pcov = curve_fit(testLinear, newX, output, p0=initial_coeffs) print("拟合得到的系数:", popt)
说明
- 使用
*args接收所有系数参数,完美适配curve_fit的参数解包机制,同时实现参数化需求。 - 用numpy数组的转置和广播运算简化了数据处理与线性组合计算,避免了手动循环提取列和计算的冗余代码。
initial_coeffs的长度由特征数自动推导,后续修改输入特征数量时无需手动调整。
内容的提问来源于stack exchange,提问作者Sainath reddy kotla
相关产品推荐
相关产品推荐

