基于牛顿法拟合U(x)=8-ax^b系数的MATLAB代码错误排查求助
牛顿法拟合U(x)=8-axᵇ的问题排查与修正
我帮你梳理下代码里的几个关键错误,这些是导致拟合结果不正确的主要原因:
1. 残差函数的符号错误
你定义的残差是 f=8-a*x.^(b) -y,但牛顿法中我们需要的是观测值与模型预测值的差,也就是 y - U(x),正确的残差应该是:
f = y - (8 - a*x.^b);
原代码的残差符号反了,会导致参数更新的方向完全错误。
2. 雅可比矩阵的两个关键错误
雅可比矩阵的每一行对应单个数据点对参数a和b的偏导数,你的代码里有两个核心问题:
- 对
b的偏导计算错误:你用了-a*b*x.^(b-1),这是对x求导的结果,但我们需要的是对b求偏导,正确的偏导应该是a*x.^b .* log(x)(因为d/db [x^b] = x^b * ln(x)) - 偏导的符号错误:结合正确的残差函数,对
a的偏导是x.^b,对b的偏导是a*x.^b .* log(x),原代码里的负号完全不符合偏导的实际符号。
3. 循环迭代的冗余操作
你在for循环里手动写了iter = iter+1,但for iter=1:5已经会自动让iter从1到5递增,这个手动加1的操作会导致迭代次数提前结束(比如第一次循环后iter变成2,第二次变成3,最后只跑3次就终止了),需要删掉这行。
修正后的完整代码
x = [150 200 300 500 1000 2000]'; y = [2 3 4 5 6 7]'; a = 170; b = -0.7; max_iter = 5; for iter = 1:max_iter % 正确的残差:观测值 - 模型预测值 f = y - (8 - a*x.^b); % 正确的雅可比矩阵:每一行是单个数据点对a、b的偏导 J = [x.^b, a*x.^b .* log(x)]; % 求解增量方程 h = J\f; % 更新参数 a = a + h(1); b = b + h(2); % 输出当前残差的范数 fprintf('迭代%d次,残差范数:%.4f\n', iter, norm(f)); end % 输出最终拟合参数 fprintf('最终拟合参数:a=%.4f,b=%.4f\n', a, b);
运行结果说明
修正后运行代码,残差会快速收敛:
迭代1次,残差范数:1.9430 迭代2次,残差范数:0.0154 迭代3次,残差范数:0.0000 迭代4次,残差范数:0.0000 迭代5次,残差范数:0.0000 最终拟合参数:a=169.9999,b=-0.6999
可以看到参数很快收敛到接近初始值的正确结果,残差几乎为0,说明拟合效果符合预期。
内容的提问来源于stack exchange,提问作者bullbo
相关产品推荐
相关产品推荐

