最小二乘法,加权最小二乘法,迭代重加权最小二乘法 (含代码)【最小二乘线性求解】



原文链接:地址

个人笔记:
最小二乘法,加权最小二乘法,迭代重加权最小二乘法。结合自己需要实现功能的目的,下面主要给出推导结果、代码实现和实际一些应用。推导过程最后会放一些个人参考的一些文章和资料。

这里推荐一个视频推导过程:利用矩阵求偏导得出 x x x= ( A T A ) − 1 A T B (A^TA)^{-1}A^TB (ATA)1ATB矩阵乘法求导视频

一:最小二乘法(OLS)

1:概述

最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。
这里说个例子,比如已经确定了目标函数 y = a 0 + a 1 x + a 2 x 2 y=a_0+a_1x+a_2x^2 y=a0+a1x+a2x2 x 和 y x和y xy是确定的实际数值, x x x是自变量, y y y是因变量,需要求 a 0 , a 1 , a 2 a_0,a_1,a_2 a0,a1,a2三个未知参数,这时候一般需要三个方程来组成一个方程组来求解得出这三个未知参数确定唯一的解。而实际中我们求三个未知参数一般都是在一个超定方程组(方程个数大于未知参数)中,这时候就需要用到最小二乘法来解决这个问题了,来求最优的解。下面给出代数式和矩阵式的解法。这里推荐使用矩阵式求解(非常方便)。

2:代数式

最小二乘法其思想主要是通过将理论值与预测值的距离的平方和达到最小。
在这里插入图片描述
举例:曲线拟合中最基本和最常用的是直线拟合。设 x x x y y y之间的函数关系为:一元一次函数 y = f ( a 0 , a 1 ) = a 0 + a 1 x y=f(a_0,a_1)=a_0+a_1x yf(a0,a1)a0+a1x 代数推导:
在这里插入图片描述

分别对 a 0 和 a 1 a_0和a_1 a0a1求偏导,这里 a 0 和 a 1 a_0和a_1 a0a1就是未知参数
在这里插入图片描述

整理为方程组
在这里插入图片描述

然后化简得:
在这里插入图片描述

3:矩阵式(推荐)

举例:曲线拟合中最基本和最常用的是直线拟合。设 x x x y y y之间的函数关系为:一元一次函数 y = f ( a 0 , a 1 ) = a 0 + a 1 x y=f(a_0,a_1)=a_0+a_1x yf(a0,a1)a0+a1x 使用矩阵表达: A x = B Ax = B Ax=B, 求 x x x向量参数
在这里插入图片描述

推导过程我会在最后放上链接。那么:

在这里插入图片描述

如果是一元多项式函数:
在这里插入图片描述
其中m代表多项式的阶数,离散点与该多项式的平方和 为 F ( a 0 , a 1 , . . . , a m ) F(a_0,a_1,..., a_m ) F(a0,a1,...,am)。其中 n n n代表采样点数:

在这里插入图片描述

一元多项式矩阵表达和一元一次项矩阵表达是一样的: A x = B Ax = B Ax=B

在这里插入图片描述
在这里插入图片描述

3.1:实现代码

/* 普通最小二乘 Ax = B
 * (A^T * A) * x = A^T * B
 * x = (A^T * A)^-1 * A^T * B
 */
Array<double,Dynamic,1> GlobleFunction::leastSquares(Matrix<double,Dynamic,Dynamic> A, Matrix<double,Dynamic,1> B)
{
    
    
    //获取矩阵的行数和列数
    int rows =  A.rows();
    int col = A.cols();
    //A的转置矩阵
    Matrix<double,Dynamic,Dynamic> AT;
    AT.resize(col,rows);

    //x矩阵
    Array<double,Dynamic,1> x;
    x.resize(col,1);

    //转置 AT
    AT = A.transpose();

    //x = (A^T * A)^-1 * A^T * B
    x = ((AT * A).inverse()) * (AT * B);
    return x;

}

Matrix是Eigen库中的一个矩阵类,这里引入Eigen库方便代数运算。

二:加权最小二乘法(WLS)

加权最小二乘法是对原模型进行加权,使之成为一个新的不存在异方差性的模型,然后采用普通最小二乘法估计其参数的一种数学优化技术。百度百科

1:增加对角矩阵 W

在最小二乘法的基础上增加一个对角矩阵 W W W,对每组数据赋予不同的权重。

在这里插入图片描述
W T ∗ W W^T * W WTW对角矩阵每个数据的平方,消除负数。

在这里插入图片描述

1.1:实现代码

/* 加权最小二乘(WLS)  W为对角线矩阵
 * W²(Ax - B) = 0
 * W²Ax = W²B
 * (A^T * W^T * W * A) * x = A^T * W^T * W * B
 * x = (A^T * W^T * W * A)^-1 * A^T * W^T * W * B
 */
Array<double,Dynamic,1> GlobleFunction::reweightedLeastSquares(Matrix<double,Dynamic,Dynamic> A, Matrix<double,Dynamic,1> B,Array<double,Dynamic,1> vectorW)
{
    
    
    //获取矩阵的行数和列数
    int rows =  A.rows();
    int col = A.cols();
    //vectorW为空,默认构建对角线矩阵1
    if(vectorW.isZero())
    {
    
    
        vectorW.resize(rows,1);
        for(int i=0;i<rows;++i)
        {
    
    
            vectorW(i,0) = 1;
        }
    }
    
    //A的转置矩阵
    Matrix<double,Dynamic,Dynamic> AT;
    AT.resize(col,rows);

    //x矩阵
    Array<double,Dynamic,1> x;
    x.resize(col,1);

    //W的转置矩阵
    Matrix<double,Dynamic,Dynamic> WT,W;
    W.resize(rows,rows);
    WT.resize(rows,rows);

    //生成对角线矩阵
    W = vectorW.matrix().asDiagonal();
    //转置
    WT = W.transpose();
    //转置 AT
    AT = A.transpose();

    // x = (A^T * W^T * W * A)^-1 * A^T * W^T * W * B
    x = ((AT * WT * W * A).inverse()) * (AT * WT * W * B);
    return x;
}

Matrix是Eigen库中的一个矩阵类,这里引入Eigen库方便代数运算。

三:迭代重加权最小二乘法(IRLS)

1:迭代重新加权最小二乘法(也叫迭代加权最小二乘法)( IRLS ) 的方法用于解决具有 p p p范数形式的目标函数的某些优化问题:维基百科。迭代加权可以对目标函数和已知的数据来进行拟合,但是这时候有的数据对总体目标函数离得特别远,参与最小二乘法的时候就会对估计参数有很大的影响,这时候就要对参数进行优化,对数据较远的赋予较小的权重(不让它显得很重要,也就影响比较小),对数据较近的赋予较大的权重(影响大)。迭代加权最小二乘,是建立加权最小二乘上进行一个迭代来估值达到最优。
在这里插入图片描述

通过迭代方法,其中每一步都涉及解决以下形式的加权最小二乘问题:
在这里插入图片描述在这里插入图片描述

2:下面引入一片论文中的一段迭代方法求解 论文地址:Burrus, C.S. (2014). Iterative Reweighted Least Squares ∗.

在这里插入图片描述在这里插入图片描述
MATLAB代码1:

% m-file IRLS0.m to find the optimal solution to Ax=b
% minimizing the L_p norm ||Ax-b||_p, using basic IRLS.
% csb 11/10/2012
function x = IRLS0(A,b,p,KK)
if nargin < 4, KK=10; end;
x = pinv(A)*b; 					% Initial L_2 solution
E = [];
for k = 1:KK 					% Iterate
	e = A*x - b; 				% Error vector
	w = abs(e).^((p-2)/2); 		% Error weights for IRLS
	W = diag(w/sum(w)); 		% Normalize weight matrix
	WA = W*A; 					% apply weights
	x = (WA'*WA)\(WA'*W)*b; 	% weighted L_2 sol.
	ee = norm(e,p); E = [E ee]; % Error at each iteration
end
plot(E)

MATLAB代码2:

% m-file IRLS1.m to find the optimal solution to Ax=b
% minimizing the L_p norm ||Ax-b||_p, using IRLS.
% Newton iterative update of solution, x, for M > N.
% For 2<p<infty, use homotopy parameter K = 1.01 to 2
% For 0<p<2, use K = approx 0.7 - 0.9
% csb 10/20/2012
function x = IRLS1(A,b,p,K,KK)
if nargin < 5, KK=10; end;
if nargin < 4, K = 1.5; end;
if nargin < 3, p = 10; end;
pk = 2; % Initial homotopy value
x = pinv(A)*b; 						% Initial L_2 solution
E = [];
for k = 1:KK 						% Iterate
	if p >= 2, pk = min([p, K*pk]);	    % Homotopy change of p
	else pk = max([p, K*pk]); end
	e = A*x - b; 						% Error vector
	w = abs(e).^((pk-2)/2); 			% Error weights for IRLS
	W = diag(w/sum(w)); 				% Normalize weight matrix
	WA = W*A; 							% apply weights
	x1 = (WA'*WA)\(WA'*W)*b;		    % weighted L_2 sol.
	q = 1/(pk-1); 						% Newton's parameter
	if p > 2, x = q*x1 + (1-q)*x; nn=p; % partial update for p>2
	else x = x1; nn=2; end 				% no partial update for p<2
	ee = norm(e,nn); E = [E ee]; 		% Error at each iteration
end
plot(E)

C++代码:


/* 迭代重加权最小二乘(IRLS)  W为权重,p为范数
 * e = Ax - B
 * W = e^(p−2)/2
 * W²(Ax - B) = 0
 * W²Ax = W²B
 * (A^T * W^T * W * A) * x = A^T * W^T * W * B
 * x = (A^T * W^T * W * A)^-1 * A^T * W^T * W * B
 * 参考论文地址:https://www.semanticscholar.org/paper/Iterative-Reweighted-Least-Squares-%E2%88%97-Burrus/9b9218e7233f4d0b491e1582c893c9a099470a73
 */
Array<double,Dynamic,1> GlobleFunction::iterativeReweightedLeastSquares(Matrix<double,Dynamic,Dynamic> A, Matrix<double,Dynamic,1> B,double p,int kk)
{
    
    
    /* x(k) = q x1(k) + (1-q)x(k-1)
     * q = 1 / (p-1)
     */
    //获取矩阵的行数和列数
    int rows =  A.rows();
    int col = A.cols();

    double pk = 2;//初始同伦值
    double K = 1.5;

    double epsilong = 10e-9; // ε
    double delta = 10e-15; // δ
    Array<double,Dynamic,1> x,_x,x1,e,w;
    x.resize(col,1);
    _x.resize(col,1);
    x1.resize(col,1);
    e.resize(rows,1);
    w.resize(rows,1);
    //初始x  对角矩阵w=1
    x = reweightedLeastSquares(A,B);

    //迭代  最大迭代次数kk
    for(int i=0;i<kk;++i)
    {
    
    
        //保留前一个x值,用作最后比较确定收敛
        _x = x;

        if(p>=2)
        {
    
    
            pk = qMin(p,K*pk);
        }
        else
        {
    
    
            pk = qMax(p,K*pk);
        }
        //偏差
        e = (A * x.matrix()) - B;
        //偏差的绝对值//  求矩阵绝对值 :e = e.cwiseAbs(); 或 e.array().abs().matrix()
        e = e.abs();
        //对每个偏差值小于delta,用delta赋值给它
        for(int i=0;i<e.rows();++i)
        {
    
    
            e(i,0) = qMax(delta,e(i,0));
        }
        //对每个偏差值进行幂操作
        w = e.pow(p/2.0-1);
        w = w / w.sum();

        x1 = reweightedLeastSquares(A,B,w);

        double q = 1 / (pk-1);
        if(p>2)
        {
    
    
            x = x1*q + x*(1-q);
        }
        else
        {
    
    
            x = x1;
        }
        //达到精度,结束
        if((x-_x).abs().sum()<epsilong)
        {
    
    
            return x;
        }
    }
    return x;
}

C++实现代码和MATLAB基本一样,不过有稍微改进,其中参考了维基百科Burrus, C.S. (2014). Iterative Reweighted Least Squares ∗.

四:应用

以下针对超定方程组来求解的。数据个数大于未知参数。

1:拟合圆(算法:迭代重新加权最小二乘)

1:使用最小二乘效果,可以看出外部的噪点干扰还是比较大的。下面使用迭代重加权最小二乘算法优化。
在这里插入图片描述2:迭代重加权最小二乘
第1次迭代
在这里插入图片描述
第2次迭代
在这里插入图片描述第3次迭代
在这里插入图片描述第4次迭代
在这里插入图片描述
第20次迭代
在这里插入图片描述

2: 直线拟合(算法:迭代重新加权最小二乘)

1: y = a 0 + a 1 x y = a_0 + a_1x y=a0+a1x
下面这张图使用的是最小二乘法,可以看出下面较远的数据噪点对整体密集数据有了很大的影响。
在这里插入图片描述1.2:使用迭代重加权最小二乘
第1次迭代
在这里插入图片描述
第100次迭代
在这里插入图片描述经过 n n n次迭代后,噪点基本上对整体没有什么影响了,这时候的得到的参数也就是理想的。

3:曲线拟合(算法:最小二乘)

1:最小二乘曲线拟合 ,寻找最佳次项函数
最小二乘法是曲线拟合的常用方法,使用该方法对匹配函数的选取非常重要。。所谓匹配函数就是函数经过的路线在图中的点达到一个最佳匹配。
不然就会出现过拟合和欠拟合的现象。
在这里插入图片描述在这里插入图片描述

在这里插入图片描述在这里插入图片描述
一次函数拟合:
在这里插入图片描述
二次函数拟合:

在这里插入图片描述
三次函数拟合:
在这里插入图片描述
四次函数拟合:
在这里插入图片描述
五次函数拟合:

在这里插入图片描述
六次函数拟合:

在这里插入图片描述
七次函数拟合:
在这里插入图片描述
八次函数拟合:

在这里插入图片描述

九次函数拟合:
在这里插入图片描述
可以发现函数在第五次函数的时候拟合程度很好了,越往后越来过拟合了。

4:N点标定(包括9点标定)(算法:最小二乘)

9点标定是求视觉 中像素坐标和世界坐标建立的关系。
在这里插入图片描述可以看到 halcon算子块 vector_to_hom_mat2d 就是用最小二乘法来计算矩阵的。图中外部算法【2】其实是本文章中的最小二乘算法实现的。内部算法【1】实现是用求偏导计算的,在这篇文章有实现N点标定

五:总结

1:工具:主要Qt + Eigen库 + QCustomPlot类
Eigen库是一个用于矩阵计算,代数计算库
QCustomPlot类是一个用于绘图和数据可视化

2:上面完整代码已上传GitHub

3:参考文献
最小二乘代数推导
最小二乘矩阵推导
最小二乘法?为神马不是差的绝对值
正则化
鲁棒学习算法
最小二乘法的原理理解

从最大似然角度理解最小二乘法
在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/weixin_43763292/article/details/127839786