MATLAB中lsqcurvefit拟合异常:系数数量级差异导致无优化
解决lsqcurvefit拟合不优化(沿用初始值)的问题
核心原因
待拟合系数coeff(1)(量级1e10)和`coeff(2)`(量级4)数量级差异过大,导致Levenberg-Marquardt算法的梯度缩放失衡,算法误判初始点为最优解,未执行迭代优化。
具体解决办法
1. 对系数进行归一化/缩放处理
将数量级悬殊的系数缩放至同一区间(比如1~100),拟合完成后再还原真实值,消除量级差异对算法的影响。
修改后的代码示例:
V = [V1, Vp]; %voltages a = 1.1792; b = 0.5; e = 1.60217662e-19; Area = 4.7909e-7; mi = 39.948./(6.022e23.*1000); % 定义缩放因子,将系数拉到相近量级 scale_coeff1 = 1e10; % 匹配coeff(1)的初始量级 scale_coeff2 = 1; % coeff(2)量级接近1,无需额外缩放 % 缩放初始猜测值 coeff0_scaled = [7e10/scale_coeff1, 4/scale_coeff2]; % 变为[7,4] % 修改拟合方程,用缩放后的系数计算 Eqn7_scaled = @(coeff_scaled, VV) ((e^1.5)*(coeff_scaled(1)*scale_coeff1)*Area*sqrt((coeff_scaled(2)*scale_coeff2)/(2*pi*mi)))*100^3*... (a*(-VV(:,1)/(coeff_scaled(2)*scale_coeff2)).^b.*tanh(VV(:,2)/(2*(coeff_scaled(2)*scale_coeff2))) + ... (a*(-VV(:,1)/(coeff_scaled(2)*scale_coeff2)).^b - a*(-(VV(:,1)+VV(:,2))/(coeff_scaled(2)*scale_coeff2)).^b)./(exp(VV(:,2)/(coeff_scaled(2)*scale_coeff2))+1)); options = optimoptions('lsqcurvefit','Algorithm','levenberg-marquardt','OptimalityTolerance',1e-16,'FunctionTolerance',1e-16); lb = []; ub = []; % 拟合缩放后的系数 [vals_scaled, resnorm, out, flag] = lsqcurvefit(Eqn7_scaled, coeff0_scaled, V, data(:,2),lb,ub); % 还原真实系数 vals = [vals_scaled(1)*scale_coeff1, vals_scaled(2)*scale_coeff2]; % 绘图验证 plot(data(:,1),data(:,2),'x',data(:,1),Eqn7(vals,V),'b-')
2. 切换算法并启用自动缩放
改用信赖域反射算法,同时开启雅可比矩阵自动缩放,算法会自适应调整系数的量级影响:
options = optimoptions('lsqcurvefit','Algorithm','trust-region-reflective',... 'OptimalityTolerance',1e-16,'FunctionTolerance',1e-16,... 'ScaleProblem','jacobian');
注:该算法适合目标函数雅可比矩阵可高效计算的场景,若你的方程计算量不大,可直接尝试。
3. 补充系数上下界约束
若已知系数的合理范围,给lb和ub设置边界,帮助算法缩小搜索空间,避免因量级问题迷失方向:
lb = [5e10, 2]; % 根据实际情况调整下限 ub = [9e10, 6]; % 根据实际情况调整上限
验证要点
- 查看
vals是否与初始猜测值不同,确认算法执行了迭代 - 对比拟合曲线与原始数据的贴合度
- 检查
out结构体中的iterations字段,确认迭代次数大于0
内容的提问来源于stack exchange,提问作者Andrew
相关产品推荐
相关产品推荐

