scipy.optimize.curve_fit为何无法将列表作为单个参数传入p0?
解决scipy.optimize.curve_fit参数不匹配报错问题
问题根源
curve_fit的工作逻辑是将p0中的每个元素作为独立参数传递给拟合函数。你传入嵌套列表p0=[[1, 0.1, 1, 640, 1, 0.2, 651, 2]]时,它会把内层的8个元素拆成8个独立参数,加上输入x后,一共9个参数传给你的gauss函数,但你的函数只接受2个参数(x和peaks列表),因此触发TypeError。
两种解决方案
方案1:修改自定义函数,接受可变数量的独立参数
直接调整gauss函数的参数定义,用*params接收所有独立参数,再在函数内部将参数重组为你需要的峰结构:
import numpy as np from scipy.optimize import curve_fit def gauss(x, *params): # 将扁平化的参数重组为峰列表(假设每个峰对应4个参数:振幅、宽度、偏移、中心) peaks = np.array(params).reshape(-1, 4) y = np.zeros_like(x) for amp, width, offset, center in peaks: y += amp * np.exp(-(x - center)**2 / (2 * width**2)) + offset return y # 生成测试数据 x = np.linspace(600, 700, 100) y_true = 1*np.exp(-(x-640)**2/(2*0.1**2)) + 1 + 1*np.exp(-(x-651)**2/(2*0.2**2)) + 2 y_noise = y_true + 0.05*np.random.normal(size=x.size) # 初始参数直接传扁平化列表,无需嵌套 p0 = [1, 0.1, 1, 640, 1, 0.2, 651, 2] popt, pcov = curve_fit(gauss, x, y_noise, p0=p0) print("拟合后的峰参数:", popt.reshape(-1, 4))
方案2:用lambda包装函数,保留原函数参数结构
如果不想修改原gauss函数的参数定义,可以用lambda表达式将curve_fit传递的多个独立参数打包成列表,再传给原函数:
import numpy as np from scipy.optimize import curve_fit # 原自定义高斯函数,保持接收x和单个peaks参数 def gauss(x, peaks): y = np.zeros_like(x) peaks = np.array(peaks).reshape(-1, 4) for amp, width, offset, center in peaks: y += amp * np.exp(-(x - center)**2 / (2 * width**2)) + offset return y # 生成测试数据 x = np.linspace(600, 700, 100) y_true = 1*np.exp(-(x-640)**2/(2*0.1**2)) + 1 + 1*np.exp(-(x-651)**2/(2*0.2**2)) + 2 y_noise = y_true + 0.05*np.random.normal(size=x.size) # 用lambda打包参数,p0传扁平化列表 p0 = [1, 0.1, 1, 640, 1, 0.2, 651, 2] popt, pcov = curve_fit(lambda x, *p: gauss(x, p), x, y_noise, p0=p0) print("拟合后的峰参数:", np.array(popt).reshape(-1, 4))
内容的提问来源于stack exchange,提问作者mrecksie
相关产品推荐
相关产品推荐

