非线性曲线拟合报错求助:如何用Levenberg–Marquardt算法求解alpha?
解决非线性拟合报错与alpha求解方案
一、先搞定Igor Pro的报错问题
你遇到的The fitting function returned INF for at least one X variable报错,核心原因是拟合过程中参数alpha的取值触发了函数的定义域非法情况:
- 你的拟合函数里有
sqrt(alpha/x)项,当alpha≤0时,根号内为负数,实数域下无意义,直接返回INF/NaN; - 另外,Igor Pro默认是矩阵运算,如果你的函数没做逐元素处理,数组运算时也可能出问题。
修复步骤:
- 给alpha设置取值约束:
在Igor的拟合参数设置界面,给alpha设置下限为0.001(避免等于0),上限可以设为比最大x值(72.01)大的数,比如100,确保拟合过程中alpha始终为正。 - 修正自定义函数的运算方式:
Igor里数组逐元素运算需要加波浪号~,否则会按矩阵运算处理,修改后的函数应该是:Function fitFunc(x, alpha) Variable beta = 1.135e-4 Return -1 + 2*sqrt(alpha~ / x~) * exp(-beta*(x~ - alpha)^2) - 设置合理的初始值:
看你的实验数据,x越小sin(theta)越接近1,代入函数估算:当x=23.47时,2*sqrt(alpha/23.47)*exp(...)≈1.997,近似等于2,说明此时exp项接近1(即alpha≈23.47);但x=30.16时sin(theta)为0.45,估算alpha≈16。所以初始值可以设为20,让拟合收敛更顺利。
二、更便捷的非线性拟合工具/程序
如果觉得Igor Pro设置繁琐,这些工具能更快帮你得到alpha:
1. Python(最推荐,免费且灵活)
用scipy.optimize.curve_fit,内置Levenberg–Marquardt算法,直接写几行代码就能运行:
import numpy as np from scipy.optimize import curve_fit # 定义拟合函数 def fit_func(x, alpha): beta = 1.135e-4 return -1 + 2 * np.sqrt(alpha / x) * np.exp(-beta * (x - alpha)**2) # 你的实验数据 sin_theta = np.array([-0.81704, -0.67649, -0.83137, -0.73468, -0.66744, -0.43602, 0.45368, 0.75802, 0.96705, 0.99717]) x = np.array([72.01, 59.99, 51.13, 45.53, 36.15, 31.66, 30.16, 29.01, 25.62, 23.47]) # 设置初始值和参数范围(alpha必须>0) initial_alpha = 20 bounds = (0.001, np.inf) # 执行拟合 popt, pcov = curve_fit(fit_func, x, sin_theta, p0=initial_alpha, bounds=bounds) print(f"拟合得到的alpha值:{popt[0]:.4f}") print(f"alpha的标准误差:{np.sqrt(pcov[0,0]):.4f}")
运行后直接输出alpha的拟合值和误差,非常省心。
2. OriginPro(可视化友好,适合科研人员)
- 导入你的x和sin(theta)数据;
- 选择
分析→拟合→非线性曲线拟合; - 自定义拟合函数,设置beta为常量(1.135e-4),alpha为待拟合参数,设置alpha的范围为>0;
- 点击拟合即可得到结果,还能直接生成拟合曲线。
3. MATLAB
用lsqcurvefit函数实现,代码示例:
beta = 1.135e-4; fit_func = @(alpha, x) -1 + 2*sqrt(alpha./x).*exp(-beta*(x-alpha).^2); sin_theta = [-0.81704 -0.67649 -0.83137 -0.73468 -0.66744 ... -0.43602 0.45368 0.75802 0.96705 0.99717]; x = [72.01 59.99 51.13 45.53 36.15 31.66 30.16 29.01 25.62 23.47]; initial_alpha = 20; lb = 0.001; % 参数下限 ub = Inf; % 参数上限 alpha_fit = lsqcurvefit(fit_func, initial_alpha, x, sin_theta, lb, ub); disp(['拟合得到的alpha值:', num2str(alpha_fit, '%.4f')]);
内容的提问来源于stack exchange,提问作者Martin
相关产品推荐
相关产品推荐

