使用含数值积分的函数做scipy曲线拟合时报numpy.float64解包错误
报错原因与解决方案
核心报错根源
你触发的TypeError: cannot unpack non-iterable numpy.float64 object错误,本质是对scipy.optimize.curve_fit的传参机制理解错误:curve_fit调用自定义拟合函数时,会将待拟合的N个参数逐个作为独立参数传入,不会打包成一个元组赋值给第二个参数。你在lc_fit里把第二个参数命名为args,尝试从里面拆分7个拟合参数,实际上此时args只是第一个待拟合参数(单个float值),自然无法执行拆包操作。
需同步修改的几处代码
- 修改拟合函数的参数定义
直接将7个待拟合参数作为独立参数声明,无需单独拆包:
def lc_fit(t, p, a, b, T, delta, gamma1, gamma2): # 原函数内部逻辑不变 Integral_1 = integrate.quad(integrand_1, 0.0001, 1., args=(t, p, a, b, T, delta, gamma1, gamma2))[0] Integral_2 = integrate.quad(integrand_2, 0.0001, 1., args=(gamma1, gamma2))[0] F= 1. - Integral_1/Integral_2 return F
- 修改两个被积函数的参数定义
scipy.integrate.quad的args参数传入的内容也是逐个传递给被积函数,不会打包为元组,因此修改如下:
def integrand_1(r, t, p, a, b, T, delta, gamma1, gamma2): # 原内部逻辑不变,删除原来的args1拆包代码 omega = 2*np.pi/T x = a*np.cos(omega*t+delta) z = np.sqrt(x**2 + b**2) T1 = derivative(L, r, dx=1e-6, args=(p,z)) T2 = I_function(r, gamma1, gamma2) return T1*T2 def integrand_2(r, gamma1, gamma2): # 原内部逻辑不变,删除原来的args2拆包代码 return I_function(r, gamma1, gamma2)*2*r
- 处理函数向量化与初始值问题
- 你的
lc_fit仅支持单个t值输入,而curve_fit传入的是整个t_data数组,需要将函数向量化:lc_fit_vec = np.vectorize(lc_fit),拟合时传入向量化后的函数。 - 7个待拟合参数必须给定合理初始猜测值
p0,否则默认全1的初始值极易导致拟合发散:
# 初始值可根据你的物理场景调整,这里参考你代码注释里的示例值 p0 = [0.1, 2.0, 0.7, 10.0, 0.0, 0.296, 0.34] popt, pcov = scipy.optimize.curve_fit(lc_fit_vec, t_data, lc_init_data, p0=p0)
- 修正L函数的标量兼容问题
原L函数中z = np.zeros(len(z0))在z0为标量时会触发报错,可在函数开头添加z0 = np.atleast_1d(z0)兼容标量输入。
内容的提问来源于stack exchange,提问作者Juan Esteban Agudelo Ortiz
相关产品推荐
相关产品推荐

