美文网首页
全部最小二乘BiSquare优化。

全部最小二乘BiSquare优化。

作者: 寽虎非虫003 | 来源:发表于2023-07-17 10:24 被阅读0次

    基本介绍

    全部最小二乘解决形如如下的最小二乘问题
    E_{TLS}=\sum_i (\boldsymbol{a}_i\boldsymbol{x})^2=||\mathbf{A}\boldsymbol{x}||^2
    求解非零项转换为如下的特征值问题
    \boldsymbol{x} = \text{arg} \min_\boldsymbol{x} \boldsymbol{x}^T(\mathbf{A}^T\mathbf{A}), \qquad \text{且} ||\boldsymbol{x}||^2=1.
    可以最小化这个约数问题的\boldsymbol{x}就是\mathbf{A}^T\mathbf{A}最小的特征值对应的特征向量。它和\mathbf{A}的最末一个右特征向量是相同的。这是因为
    \mathbf{A=U \Sigma V}^T \\ \mathbf{A}^T\mathbf{A=U \Sigma V}^T \\ \mathbf{A}^T\mathbf{A} \boldsymbol{v}_k = \sigma_k^2- \boldsymbol{v}_k
    通过选择最小的\sigma_k值,我们就可以达到约束这个问题的目的。
    求解直线拟合问题ax+by+c=0的时候,为了所有的输入变量具有相同的噪声模型,需要先对变量进行处理,减去各自均值
    \hat{x}_i=x_i- \overline x\\ \hat{y}_i=y_i- \overline y\\
    然后通过最小化
    E_{LTS-2Dm} = \sum_i(a\hat{x}+b\hat{y})^2
    来拟合2D直线方程a(x-\overline x)+b(y-\overline y)=0

    最后在ax+by+c=0c = -a\overline{x} -b\overline{y}

    BiSquare

    给每个点施加一个权重,离群点的权重会变为零。
    按matlab的文档中的写法
    u_i = \frac{r_{i}}{Ks};\\ \displaystyle w_i = \begin{cases} (1-( u_i)^2)^2,\quad |u_i|<1\\ \qquad 0,\qquad \qquad |u_i|\geqslant 1\\ \end{cases}
    其中 K=4.685 为调谐常数,s 为稳健标准偏差,由残差的中位绝对偏差 (MAD) 除以 0.6745 得出。
    第一次迭代的时候所有的权重都默认为1.
    则在任意一次迭代中,直线的加权的最小全部最小二乘的形式变为
    E_{LTS-2Dm} = \sum_i w_i(a\hat{x}+b\hat{y})^2
    解的过程变为了
    \mathbf{WA=U \Sigma V}^T \\ \mathbf{(WA)}^T\mathbf{WA=U \Sigma V}^T \\ \mathbf{(WA)}^T\mathbf{WA} \boldsymbol{v}_k = \sigma_k^2- \boldsymbol{v}_k
    其中W为对角矩阵,使得W_{ii}=w_i
    结果同样是取最小的\sigma_k值对应的\boldsymbol{v}_k来达到约束这个问题的目的。

    实现步骤

    • 1.通过加权最小二乘法拟合模型。对于第一次迭代,除非你指定权重,否则算法使用的权重等于 1。
      要先使用权重更新均值,然后是构造的求解矩阵:
      均值改为加权均值
      \overline{x} = \frac{\sum w_i x_i}{\sum w_i}\\ \overline{y} = \frac{\sum w_i y_i}{\sum w_i}\\
      构造2D直线方程a(x-\overline x)+b(y-\overline y)=0的加权最小完全平方公式E_{LTS-2Dm} = \sum_i w_i(a\hat{x}+b\hat{y})^2的矩阵形式\mathbf{WA=0}
    • 2.计算调整后的残差并将其标准化。计算新的权重
      u_i = \frac{r_{i}}{Ks};\\ \displaystyle w_i = \begin{cases} (1-( u_i)^2)^2,\quad |u_i|<1\\ \qquad 0,\qquad \qquad |u_i|\geqslant1\\ \end{cases}
      参考下图
      BiSquare

    在实际操作过程中计算s的过程为
    r^* = \frac{\sum w_i r_i}{\sum w_i}\\ s=\frac{ \text{median}\{|r_i-r^*| \}}{0.6745}

    • 3.如果拟合收敛,则退出迭代过程。否则,更新权重返回步骤1,执行下一次二平方权重拟合方法迭代。
      与使用稳健最小二乘拟合将异常值的影响降至最低相比,您可以将数据点标记为从拟合中剔除。

    实现代码

    int BiSquareLineFitting(
        const Pointf *vPts, const int n,
        double &xMean, double &yMean,
        float &a, float &b, float &c)
    {
        double xsum{0.f}, ysum{0.f};
    
        // 初始化权重
        cv::Mat_<double> mWeight(n, 1);
        for (size_t i = 0; i < n; i++)
        {
            mWeight(i, 0) = 1.f;
        }
    
        cv::Mat_<double> mA(n, 2);
    
        // 迭代计算
        int maxIter = n * (n - 1) / 2;
        maxIter = min(maxIter, 50);
    
        cv::Mat_<double> mWA(n, 2);      ///< 实际计算时候,权重与A的乘积矩阵
        cv::Mat_<double> mR(n, 1);       ///< 偏差
        cv::Mat_<double> mRsort(n, 1);   ///< 偏差进行排序
        cv::Mat_<double> mMadsort(n, 1); ///< 偏差进行排序
        cv::Mat_<double> mWR(n, 1);      ///< 加权后的偏差
        cv::Mat w, u, vt;
        cv::Mat_<double> vk;
        double K = 4.685;
        double s{};
        double sumWR{}; // 加权后的偏差值
        for (size_t iter = 0; iter < maxIter; iter++)
        {
            // 这儿是不是可以根据权重先重新更新一下均值
            xsum = 0.0f;
            ysum = 0.0f;
            double w_iSum{0.f};
            for (size_t i = 0; i < n; i++)
            {
                xsum += vPts[i].x * mWeight(i, 0);
                ysum += vPts[i].y * mWeight(i, 0);
                w_iSum +=mWeight(i, 0);
            }
            // xMean = xsum / n;
            // yMean = ysum / n;
    
            xMean = xsum / w_iSum;
            yMean = ysum / w_iSum;
    
            for (size_t i = 0; i < n; i++)
            {
                mA(i, 0) = vPts[i].x - xMean;
                mA(i, 1) = vPts[i].y - yMean;
                // mA(i, 2) = 1.f;
            }
    
            // 更新计算权重后的矩阵
            for (size_t j = 0; j < n; j++)
            {
                mWA(j, 0) = mA(j, 0) * mWeight(j, 0);
                mWA(j, 1) = mA(j, 1) * mWeight(j, 0);
            }
    
            // 更新权重之后计算
            cv::SVD::compute(mWA, w, u, vt);
            vk = vt.t().col(1);
    #ifdef _DEBUG
            std::cout << vk << std::endl;
    #endif
            a = vk(0, 0);
            b = vk(1, 0);
    
            // 偏差矩阵
            for (size_t i = 0; i < n; i++)
            {
                // mR(i, 0) = mWeight(i, 0)*(a * mA(i, 0) + b * mA(i, 1));
                mR(i, 0) = (a * mA(i, 0) + b * mA(i, 1));
            }
            // 偏差中位数
            double median{};
            double wr_iSum{};
            w_iSum = 0.f;
            for (size_t i = 0; i < n; i++)
            {
                wr_iSum += mWeight(i, 0) * mR(i, 0);
                w_iSum += mWeight(i, 0);
            }
            median = wr_iSum / w_iSum;
    
            // mRsort = cv::abs(mRsort - median);
            mRsort = cv::abs(mR - median);
            cv::sort(mRsort, mMadsort, cv::SORT_EVERY_COLUMN + cv::SORT_ASCENDING);
            double mad = n % 2 == 0 ? (mMadsort(n / 2, 0) + mMadsort(n / 2 - 1, 0)) / 2 : mMadsort(n / 2, 0);
            s = mad / 0.6745;
            // 根据新计算出来的参数用bisquare更新权重
            for (size_t i = 0; i < n; i++)
            {
                double u_i = mR(i, 0) / (K * s);
                if (abs(u_i) < 1)
                {
                    mWeight(i, 0) = pow(1 - pow(u_i, 2), 2);
                }
                else
                {
                    mWeight(i, 0) = 0.f;
                }
                mWR(i, 0) = mWeight(i, 0) * pow(mR(i, 0), 2);
            }
    
            //
            sumWR = cv::sum(mWR)[0];
    #ifdef _DEBUG
            // std::cout << "mWeight = " << mWeight << std::endl;
            std::cout << "sumWR = " << sumWR << std::endl;
    #endif
        }
    
        a = vk(0, 0);
        b = vk(1, 0);
        c = -a * xMean - b * yMean;
    
        return 0;
    }
    

    参考

    全部最小二乘
    最小二乘法介绍(matlab文档翻译)

    相关文章

      网友评论

          本文标题:全部最小二乘BiSquare优化。

          本文链接:https://www.haomeiwen.com/subject/iiqgudtx.html