牛顿法实验收敛阶计算MATLAB代码异常问题求助
修正牛顿法/截断牛顿法收敛阶计算问题排查与修正
问题根源分析
你的代码计算收敛阶时出现p值异常,主要有以下几个原因:
- 笔误问题:代码第一行的
typex_min是无效变量名,应为x_min=[1;1]; - 数值稳定性问题:当迭代接近极小值点时,误差
ek会趋近于机器精度,此时log(ekp/ek)或log(ek/ekm)会出现数值震荡(比如误差过小导致的下溢、比值趋近0或无穷大),直接计算对数比值会得到异常值 - 索引与数组初始化不匹配:
- 当
k<=100时,pseq初始化长度为k,但循环仅填充length(xseq)-2个元素,剩余元素为0,拉低平均值 - 当
k>100时,xseq_new取最后101个点,循环仅生成99个收敛阶值,但pseq初始化长度为100,最后一个元素为0,同样影响结果
- 当
- 未筛选收敛阶段数据:初始迭代阶段算法还未进入局部收敛区域,此时计算的收敛阶不具备参考性,直接取所有值的平均会导致结果偏差
修正后的代码
x_min = [1;1]; % 一次性计算所有迭代点的误差 error_seq = vecnorm(xseq - x_min, 2, 1); % 找到进入收敛阶段的起始索引(误差小于1e-3,可根据需求调整阈值) conv_idx = find(error_seq < 1e-3, 1, 'first'); if isempty(conv_idx) || length(error_seq) - conv_idx < 3 error('迭代未进入收敛阶段,无法计算有效收敛阶'); end % 仅使用收敛阶段的误差数据 valid_error = error_seq(conv_idx:end); pseq = zeros(length(valid_error)-2, 1); for i = 2:length(valid_error)-1 ekm = valid_error(i-1); ek = valid_error(i); ekp = valid_error(i+1); % 避免数值异常:仅当误差在合理范围内时计算收敛阶 if ek > eps && ekm > eps && ekp/ek > eps && ek/ekm > eps pseq(i-1) = log(ekp/ek) / log(ek/ekm); else pseq(i-1) = NaN; % 标记无效值 end end % 剔除无效值后计算平均收敛阶 pseq = pseq(~isnan(pseq)); if ~isempty(pseq) p = mean(pseq); else error('无有效收敛阶数据'); end
关键改进点
- 预计算误差序列:用
vecnorm一次性计算所有迭代点的误差,更高效且避免重复计算 - 筛选收敛阶段:仅使用误差足够小之后的迭代点,确保计算的是算法的局部收敛阶
- 数值异常防护:添加误差阈值判断,避免因误差过小导致的对数计算异常,用NaN标记无效值后剔除
- 数组长度匹配:根据有效误差序列的长度初始化
pseq,避免未赋值的0元素干扰平均值计算
内容的提问来源于stack exchange,提问作者Giuliana Paradiso
相关产品推荐
相关产品推荐

