使用scipy.optimize.curve_fit拟合特定方程遇类型错误及拟合失效问题
Python曲线拟合问题排查与解决建议
1. 幂运算符报错的原因与修复
你遇到的bitwise_xor类型错误,是因为Python里^是按位异或运算符,不是幂运算。必须用**来表示幂计算,这一步你已经做对了,是正确的修复方式。
2. 部分数据拟合不匹配的问题分析与解决
你猜测的「负数开根生成虚数」是核心原因之一,结合你的代码和拟合函数,具体分析如下:
问题根源
你的拟合函数:
def law(x, i, a, bo, q, bi): return i * (1 + x / bo) ** (-a) * (1 - x / bi) ** q
当x >= bi时,1 - x/bi会变成非正数,而q是2.0-4.0之间的数(根据你的bounds),如果q是小数,非正数的小数次幂会产生虚数。curve_fit无法处理虚数输出,会导致拟合收敛失败,结果完全偏离数据。
具体解决步骤
(1)强制约束bi大于x的最大值
修改bounds中bi的下界,确保bi始终大于你的输入数据x(即SP_B [T])的最大值:
import numpy as np x_max = SP1['SP_B [T]'].max() # 把bi的下界设为x_max的1.1倍,留出安全余量 fit = curve_fit(law, SP1['SP_B [T]'], SP1['SP_Ic [A]'], bounds=[(0, 0.0, 0.2, 2.0, x_max*1.1), (2000, 1.0, 2.0, 4.0, 100)])
(2)添加初始参数猜测(p0)
curve_fit默认初始参数全为1,和实际数据差距过大时容易收敛到局部最优。根据你的数据范围手动设置初始值,比如:
# 根据你的数据大致估算初始值,比如i设为Ic的最大值,bo设为x的中位数,bi设为x_max*1.2 p0 = [SP1['SP_Ic [A]'].max(), 0.5, 1.0, 3.0, x_max*1.2] fit = curve_fit(law, SP1['SP_B [T]'], SP1['SP_Ic [A]'], p0=p0, bounds=[(0, 0.0, 0.2, 2.0, x_max*1.1), (2000, 1.0, 2.0, 4.0, 100)])
(3)在拟合函数中处理非正数情况(可选)
如果你的数据中确实存在x >= bi的情况,物理上Ic应该为0或无意义,可以在函数中添加判断,避免生成虚数:
def law(x, i, a, bo, q, bi): term1 = (1 + x / bo) ** (-a) # 当1-x/bi<=0时,term2设为0,避免虚数 term2 = np.where(1 - x/bi > 0, (1 - x/bi)**q, 0) return i * term1 * term2
(4)检查参数边界的合理性
比如你的bo下界是0.2,要确保x/bo不会过大导致数值溢出;q的范围是2-4,若为整数则非正数的整数次幂合法,但如果是小数仍会有问题,所以优先保证bi > x_max更稳妥。
内容的提问来源于stack exchange,提问作者Idoia
相关产品推荐
相关产品推荐

