使用scipy curve_fit拟合含sin(atan)曲线时遇RuntimeError求助
解决scipy.curve_fit拟合嵌套arctan正弦函数时的RuntimeError问题
问题根源分析
你使用的y_fit是嵌套arctan的正弦非线性函数,这类函数在拟合时存在明确限制:
- 参数高度耦合:
Bx与Ex共同作用于Bx*x - np.arctan(Bx*x)项,参数间相关性极强,无约束优化难以找到收敛路径。 - 初始猜测敏感度极高:
curve_fit默认全1的初始值与你的数据范围(y值±110左右)完全不匹配,会引发数值溢出或梯度爆炸,触发RuntimeError。 - 数值稳定性风险:当
Bx*x绝对值较大时,Bx*x - np.arctan(Bx*x)的计算可能出现精度损失,干扰优化过程。
具体解决方案
1. 提供贴合数据的初始参数猜测
根据数据的奇函数特性、y极值范围、x=0时y=0的特征,设置初始值:
Dx:对应振幅,设为110(匹配数据最大值)Cx:控制正弦周期,设为π/2(x=±1时y接近±87,对应正弦非极值点)Bx:控制arctan陡峭程度,设为5(让arctan在x=±1附近变化显著)Ex:调节arctan修正幅度,设为0.5(中等强度修正)
2. 调整优化方法与参数约束
使用trf或dogbox方法(比默认lm更适配强非线性、参数耦合场景),同时设置参数边界,避免极端值导致的计算异常。
3. 修正后的可运行代码
from scipy.optimize import curve_fit import matplotlib.pyplot as plt import numpy as np x = np.linspace(-1.0,1.0,15) y = [-86.97572322743066, -89.53074407145257, -92.87263307518653, -97.35933273748071, -103.42406004626562, -110.56817865568372, -106.1393898655548, 0.0, 106.13938986555478, 110.56817865568372,103.42406004626562, 97.35933273748071, 92.87263307518657, 89.53074407145257, 86.97572322743066] def y_fit(x,Dx,Cx,Bx,Ex): term = Bx * x inner = term - Ex * (term - np.arctan(term)) return Dx * np.sin(Cx * np.arctan(inner)) # 初始猜测值 p0 = [110, np.pi/2, 5, 0.5] # 参数边界:[最小值列表], [最大值列表] bounds = ([0, 0, 1, 0], [200, np.pi, 20, 2]) # 使用trf方法拟合 popt, pcov = curve_fit(f=y_fit, xdata=x, ydata=y, p0=p0, method='trf', bounds=bounds) print("拟合参数:", popt) plt.plot(x, y_fit(x, *popt), label='拟合曲线') plt.plot(x, y, 'o', label='原始数据') plt.legend() plt.show()
方案生效原因
- 初始猜测贴合数据特征,让优化算法从合理起点开始搜索,避免陷入数值不稳定区域。
trf方法支持边界约束,限制参数在合理范围内,防止出现函数计算异常的极端值。- 拆分函数内部计算步骤,提升了数值计算的稳定性,减少精度损失。
内容的提问来源于stack exchange,提问作者João Marcos Cavalcante
相关产品推荐
相关产品推荐

