• 高斯-牛顿迭代


    高斯牛顿迭代用于求解最小化(r中的函数数量大于等于β中的变量数量)

    类似于牛顿迭代法寻找每一步迭代所得解得切线,高斯牛顿迭代法要找r在β处的最优线性逼近。

    雅可比矩阵体现了一个可微方程与给出点的最优线性逼近,形式如下

    也就是说

    雅克比矩阵行数与列数不相等,所以求逆方法后结果为。(这里也说明了r中的函数数量大于等于β中的变量数量的原因。如果不是则JrTJr不可逆)

    于是每一次迭代的结果为

    与牛顿迭代相同,高斯牛顿迭代的做法等同于忽略函数的二阶导。

    忽略二阶导的条件为。该条件满足有两种情况

    1.ri较小2.较小,函数接近线性。

    若二阶导不可忽略,函数不收敛

    维基举例与实现代码。

    设有n函数,m变量

    单次迭代复杂度O(m^2*n)

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <iostream>
    #define LDB long double
    using namespace std;
    
     int n;
     LDB x[233],y[233],ans[233];
    
     struct matrix{
        LDB a[601][601],tmp[601][601];
        int n,m;
          
        void clear(){
          memset(a,0,sizeof(a));
          memset(tmp,0,sizeof(tmp));
        } 
          
        void cpy(matrix&b){
          n=b.n;m=b.m;
          for (int i=1;i<=n;i++)    
            for (int j=1;j<=m;j++)
              a[i][j]=b.a[i][j];
        }
          
        void mul(matrix &b){
          for (int i=0;i<=n;i++) 
            for (int j=0;j<=b.m;j++) 
              tmp[i][j]=0;
            
          for (int i=0;i<=n;i++)
            for (int k=0;k<=m;k++)
              if (a[i][k]){
                  for (int j=0;j<=b.m;j++)
                  tmp[i][j]+=a[i][k]*b.a[k][j];
                a[i][k]=0;
              }
          
          for (int i=0;i<=n;i++)
            for (int j=0;j<=b.m;j++)
              a[i][j]=tmp[i][j];
          m=b.m;
        }
        
        void getinv(){
          for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][n+j]=0;
          for (int i=1;i<=n;i++) a[i][n+i]=1;
          for (int i=1;i<=n;i++){
            int po;LDB maxi=0;
            for (int j=i;j<=n;j++){
              if (fabs(a[j][i])>maxi){
                maxi=fabs(a[j][i]);po=j;
              }
            }
            for (int j=1;j<=2*n;j++){
              LDB t=a[i][j];a[i][j]=a[po][j];a[po][j]=t;
            }
            if (fabs(maxi)==0) continue;
                
            for (int j=i+1;j<=n;j++){
              LDB tim=a[j][i]/a[i][i];
              for (int k=i;k<=2*n;k++) a[j][k]-=a[i][k]*tim;
            }
          }
            
          for (int i=n;i>=1;i--){
            for (int j=i+1;j<=n;j++){
              for (int k=n+1;k<=2*n;k++)
                a[i][k]-=a[i][j]*a[j][k];
              a[i][j]=0;          
            }
            for (int j=n+1;j<=2*n;j++)
              a[i][j]/=a[i][i];
            a[i][i]=1;  
          }
          
          for (int i=1;i<=n;i++)
            for (int j=1;j<=n;j++)
              a[i][j]=a[i][j+n];
          for (int i=1;i<=n;i++) for (int j=1;j<=n;j++) a[i][j+n]=0;
        }
        
        void trav(){
          for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
              tmp[i][j]=a[j][i],a[j][i]=0;
          for (int i=1;i<=m;i++)
            for (int j=1;j<=n;j++)
              a[i][j]=tmp[i][j];
          swap(n,m);
        }
      }a,b,c,d;
      
      int main(){      
        scanf("%d",&n);
        for (int i=1;i<=n;i++) scanf("%Lf%Lf",&x[i],&y[i]);
        ans[1]=0.9;ans[2]=0.2;
        
        LDB tot=0;
        for (int i=1;i<=n;i++)
          tot+=(y[i]-ans[1]*x[i]/(ans[2]+x[i]))*(y[i]-ans[1]*x[i]/(ans[2]+x[i]));
        printf("0 %.6Lf %.6Lf %.6Lf
    ",ans[1],ans[2],tot);
          
        for (int T=1;T<=10;T++){
          a.clear();b.clear();c.clear();d.clear();    
              
          a.n=n;a.m=2;
          for (int i=1;i<=n;i++)
            a.a[i][1]=-x[i]/(ans[2]+x[i]),
            a.a[i][2]=ans[1]*x[i]/(ans[2]+x[i])/(ans[2]+x[i]);
          b.cpy(a);c.cpy(a);
          d.n=n;d.m=1;
          for (int i=1;i<=n;i++)
            d.a[i][1]=y[i]-ans[1]*x[i]/(ans[2]+x[i]);
          a.trav();
          a.mul(b);
          a.getinv();
          c.trav();
          a.mul(c);
          a.mul(d);
          ans[1]=ans[1]-a.a[1][1];ans[2]=ans[2]-a.a[2][1];
          
          LDB tot=0;
          for (int i=1;i<=n;i++)
            tot+=(y[i]-ans[1]*x[i]/(ans[2]+x[i]))*(y[i]-ans[1]*x[i]/(ans[2]+x[i]));
          printf("%d %.6Lf %.6Lf %.6Lf
    ",T,ans[1],ans[2],tot);
        }
      }
  • 相关阅读:
    java发送邮件
    MySQL查询表结构的SQL语句
    Jquery的toggle()方法
    jQuery为图片添加链接(创建新的元素来包裹选中的元素)
    mysql修改存储过程的权限
    php中接收参数,不论是来自GET还是POST方法
    解决php中文乱码
    MySQL的视图view,视图创建后,会随着表的改变而自动改变数据
    选项卡面向对象练习
    对数组的操作splice() 和slice() 用法和区别
  • 原文地址:https://www.cnblogs.com/zhujiangning/p/8133836.html
Copyright © 2020-2023  润新知