Matlab 最小二乘法拟合函数

             

预备知识 最小二乘法,Nelder-Mead 算法

   我们在 “最小二乘法” 见到的三个例子中,方差函数都是待定系数的线性组合,这种情况下我们令偏导为零后得到的是线性方程组,便于求解.然而当方差不是待定系数的线性组合时,得到的方程组往往非常复杂,这时就需要借助数值计算.相比用数值计算解 $N$ 元的非线性方程组,更简单的方法是直接用数值方法寻找方差函数的极小值(如 Nelder-Mead 算法).实践证明,大多数情况下极小值点仅有一个,那就是最小值点.

   为了验证结果的正确性,我们先来用数值方法拟合 $A \cos\left(x + \varphi_0\right) + C$,并与 “最小二乘法” 中的方法比较结果.

图
图 1:运行结果

代码 1:curveFit.m
function curveFit
close all;
% 随机生成简谐曲线
N = 20;
x0 = linspace(0, 2*pi, N);
y0 = 5*rand * sin(x0 + 2*pi * rand) + 10 * rand;
y0 = y0 + 2*rand(1,20); % 产生随机误差
scatter(x0, y0, '+'); % 画出散点
hold on;

% Nelder-Mead 求方差最小值点
f = @(x) norm( x(1)*sin(x0 + x(2)) + x(3) - y0 )^2;
c = NelderMead(f, [5, 1, 5], 1e-7);
% 画拟合结果
x = linspace(0, 2*pi, 50);
y1 = c(1) * sin(x + c(2)) + c(3);
plot(x, y1);

% 解线性方程组求方差最小值点
c = sinfit(x0, y0);
% 画拟合结果
y2 = c(1)*cos(x) + c(2)*sin(x) + c(3);
plot(x, y2, '.');
end

% 拟合简谐曲线
% y = C(1)*cos(x) + C(2)*sin(x) + C(3)
function C = sinfit(x, y)
N = numel(x);
cosx = cos(x); sinx = sin(x);
sc = sum(sinx.*cosx);
s = sum(sinx); c = sum(cosx);
% 系数矩阵
M = [sum(cosx.^2), sc          , c;
               sc, sum(sinx.^2), s;
                c,            s, N];
b = [sum(y.*cosx); sum(y.*sinx); sum(y)];
C = M\b; % 解线性方程组
end

   运行结果如图 1 所示,可见两种方法拟合出的曲线一致(红色的曲线和黄色的点线).注意第 13 行使用了 “Nelder-Mead 算法” 中的函数 NelderMead 求函数句柄 f 的最小值.

致读者: 小时百科一直以来坚持所有内容免费无广告,这导致我们处于严重的亏损状态。 长此以往很可能会最终导致我们不得不选择会员制,大量广告,内容付费等。 因此,我们请求广大读者热心打赏 ,使网站得以健康发展。 如果看到这条信息的每位读者能慷慨打赏 10 元,我们一个星期内就能脱离亏损, 并保证网站能在接下来的一整年里向所有读者继续免费提供优质内容。 但遗憾的是只有不到 1% 的读者愿意捐款, 他们的付出帮助了 99% 的读者免费获取知识, 我们在此表示感谢。

广告位

投放详情

         

© 小时科技 保留一切权利