lmfit全局参数+子集参数拟合问题及解决:DataFrame适配
用lmfit实现分数据集拟合参数的问题解决
原始可运行代码
我有一组存储在pandas DataFrame中的数据,使用lmfit进行多方程拟合,初始可运行代码如下:
# 读取数据 df1 = pd.read_excel('Data.xlsx', skiprows=0) # 定义拟合残差函数 def residual(params, Obvs_int, logfO2, Op_b, P, T, uncertainty): cS = params['a'] cH = params['b'] v0 = params['c'] v1 = params['d'] d0 = params['e'] d1 = params['f'] e0 = params['g'] e1 = params['h'] logK = cS + cH/T + Op_b + (v0*P + v1*P**2)/T a0 = d0 + d1*Op_b a1 = e0 + e1*Op_b Calc_int = (1/(1+10**(0.25*logfO2 + logK)) - a0)/a1 return (Obvs_int - Calc_int)/uncertainty # 设置拟合参数初始值 params = Parameters() params.add('a', value=-3) params.add('b', value=5000) params.add('c', value=300) params.add('d', value=-97) params.add('e', value=-0.13) params.add('f', value=-0.06) params.add('g', value=1) params.add('h', value=1) # 执行拟合 out1 = minimize(residual, params, args=(df1['Obvs_int'], df1['logfO2'], df1['Op_b'], df1['Pressure'], df1['Temperature'], df1['Total_unc']), nan_policy='omit')
需求
需要实现:
- 参数
cS、cH、d0、d1、e0、e1对全部数据进行拟合; - 参数
v0、v1用于拟合其中一个数据子集; - 参数
v2、v3用于拟合另一个数据子集。
错误尝试及问题
我在DataFrame中添加了0/1标记列p来区分子集,并用if-else编写新的残差函数:
def residual(params, Obvs_int, p, logfO2, Op_b, P, T, uncertainty): cS = params['a'] cH = params['b'] v0 = params['c'] v1 = params['d'] d0 = params['e'] d1 = params['f'] e0 = params['g'] e1 = params['h'] v2 = params['i'] v3 = params['j'] a0 = d0 + d1*Op_b a1 = e0 + e1*Op_b if p == 1: logK = cS + cH/T + Op_b + (v0*P + v1*P**2)/T Calc_int = (1/(1+10**(0.25*logfO2 + logK)) - a0)/a1 else: logK1 = cS + cH/T + Op_b + (v2*P + v3*P**2)/T Calc_int = (1/(1+10**(0.25*logfO2 + logK1)) - a0)/a1 return (Obvs_int - Calc_int)/uncertainty params = Parameters() params.add('a', value=-3) params.add('b', value=5000) params.add('c', value=300) params.add('d', value=-97) params.add('e', value=-0.13) params.add('f', value=-0.06) params.add('g', value=1) params.add('h', value=1) params.add('i', value=300) params.add('j', value=-97)
运行后报错:'The truth value of a Series is ambiguous. Use a.empty, a.bool(), a.item(), a.any() or a.all()',原因是将整列pandas Series传入if条件,无法直接判断布尔值,导致歧义。
解决方法及修正后代码
用np.where()替代if-else实现向量化判断,这样可以对整个Series的每个元素分别处理,避免歧义。修正后的残差函数及完整代码如下:
# 读取数据 df1 = pd.read_excel('Data.xlsx', skiprows=0) # 定义拟合残差函数 def residual(params, Obvs_int, p, logfO2, Op_b, P, T, uncertainty): cS = params['a'] cH = params['b'] v0 = params['c'] v1 = params['d'] d0 = params['e'] d1 = params['f'] e0 = params['g'] e1 = params['h'] v2 = params['i'] v3 = params['j'] a0 = d0 + d1*Op_b a1 = e0 + e1*Op_b # 用np.where实现分数据集计算压力项 pressure_term = np.where(p == 1, v0*P + v1*P**2, v2*P + v3*P**2) logK = cS + cH/T + Op_b + pressure_term/T Calc_int = (1/(1+10**(0.25*logfO2 + logK)) - a0)/a1 return (Obvs_int - Calc_int)/uncertainty # 设置拟合参数初始值 params = Parameters() params.add('a', value=-3) params.add('b', value=5000) params.add('c', value=300) params.add('d', value=-97) params.add('e', value=-0.13) params.add('f', value=-0.06) params.add('g', value=1) params.add('h', value=1) params.add('i', value=300) params.add('j', value=-97) # 执行拟合,注意传入新增的p列参数 out1 = minimize(residual, params, args=(df1['Obvs_int'], df1['p'], df1['logfO2'], df1['Op_b'], df1['Pressure'], df1['Temperature'], df1['Total_unc']), nan_policy='omit')
内容的提问来源于stack exchange,提问作者Anme
相关产品推荐
相关产品推荐

