• <ins id="pjuwb"></ins>
    <blockquote id="pjuwb"><pre id="pjuwb"></pre></blockquote>
    <noscript id="pjuwb"></noscript>
          <sup id="pjuwb"><pre id="pjuwb"></pre></sup>
            <dd id="pjuwb"></dd>
            <abbr id="pjuwb"></abbr>
            posts - 12,  comments - 54,  trackbacks - 0
            考慮用有M個(gè)未定參數(shù)aj(j=1,...,M)的模型來擬合N個(gè)數(shù)據(jù)點(diǎn)(xi, yi),i= 1, 2, ..., N。
            因變量與自變量的一個(gè)函數(shù)關(guān)系可以如下給出:
            y(x) = y( x; a1, a2, ..., aM)
            如果所給的N個(gè)數(shù)據(jù)點(diǎn)(xi, yi)誤差都是獨(dú)立的,并且服從具有相同常數(shù)方差的正態(tài)分布,那么最小二乘方擬合就是擬合參數(shù)aj的最大似然估計(jì)
            X2 = \sum_{i=1}^N [ yi - y(xi; a1, a2, ..., aM )]2

            如果這個(gè)模型是x的任意M個(gè)特定函數(shù)的線性組合,如
            y(x) = a0 + a1 cos(k1x+2) + a2 sin(k2x+3)
            一般形式可以寫為
            y(x) = \sum_{k=1}^N ak Xk(x)

            那么它的優(yōu)值函數(shù)為
            X2 = \sum_{i=1}^N [yi - \sum_{k=1}^M ak Xk(xi)]2

            將上式分別對(duì)M個(gè)參數(shù)ak求偏導(dǎo)數(shù),并令其等于0, 可以得到X2的最小值。
            于是得到M個(gè)方程
            \sum_{i=1}^N [yi-\sum_{j=1}^M aj Xj(xi)]Xk(xi) = 0    k= 1, 2, ..., M

            用克萊姆法則求解這個(gè)M元一次方程組,可以得到 a1, a2, ..., aM的解,即為所求的aj的最大似然估計(jì)。

            接下來估計(jì)數(shù)據(jù)與模型的契合度
            由平移伽瑪近似計(jì)算
            ssq = gammq((N-2)/2, X2/2)


            以下為c++實(shí)現(xiàn)
            regression.h
              1 template<size_t SIZE, size_t N>
              2 class Regression
              3 {
              4 public:
              5     //ctor
              6     Regression()
              7     {
              8         Y.resize ( SIZE );
              9         X.resize ( SIZE * N );
             10         Result.resize ( SIZE );
             11         SSQ = 0.0L;
             12     }
             13 
             14     //dtor
             15     ~Regression() {}
             16     //get Y[SIZE]
             17     void _y ( const std :: vector<long double>& y )
             18     {
             19         assert ( SIZE == y.size() );
             20         Y = y;
             21     }
             22 
             23     //set vector x[][]
             24     void _x ( const std :: vector<long double>& x )
             25     {
             26         assert ( SIZE * N == x.size() );
             27         X = x;
             28     }
             29 
             30     //set vector x[][] cloumn index
             31     void _x ( const std :: vector<long double>& x, const unsigned int& index )
             32     {
             33         assert ( index < N );
             34         assert ( SIZE == x.size() );
             35 
             36         for ( unsigned int i = 0; i < SIZE; ++i )
             37         {
             38             X[ i * N + index ] = x[i];
             39         }
             40     }
             41 
             42     //execute least square fit
             43     void fit()
             44     {
             45         //the model is
             46         //             alfa[N][N] * result[N] = beta[N]
             47         //
             48         long double alfa[N][N];
             49         long double beta[N];
             50 
             51         for ( unsigned int k = 0; k < N; ++k )
             52         {
             53             for ( unsigned int j = 0; j < N; ++j )
             54             {
             55                 long double tmp = 0.0L;
             56                 for ( unsigned int i = 0; i < SIZE; ++i )
             57                 {
             58                     tmp += X[i*N+k] * X[i*N+j];
             59                 }//end of i loop
             60                 alfa[k][j] = tmp;
             61             }//end of j loop
             62 
             63             long double tmp = 0.0L;
             64             for ( unsigned int i = 0; i < SIZE; ++i )
             65             {
             66                 tmp += Y[i] * X[i*N+k];
             67             }//end of i loop
             68             beta[k] = tmp;
             69         }//end of k loop
             70 
             71         std::vector<long double> a;
             72         a.clear();
             73         for ( unsigned int i = 0; i < N; ++i )
             74             for ( unsigned int j = 0; j < N; ++j )
             75             {
             76                 a.push_back ( alfa[i][j] );
             77             }
             78 
             79         std::vector<long double> b;
             80         b.clear();
             81         for ( unsigned int i = 0; i < N; ++i )
             82             b.push_back ( beta[i] );
             83 
             84         //calculate Result[N]
             85         lq<long double> ( a, b, N, Result );
             86 
             87         //calculate chi-square
             88         long double chi = 0.0L;
             89         for ( unsigned int i = 0; i < SIZE; ++i )
             90         {
             91             long double tmp = 0.0L;
             92             for ( unsigned int j = 0; j < N; ++j )
             93             {
             94                 tmp += Result[j] * X[i*j+j];
             95             }
             96             tmp -= Y[i];
             97             chi += tmp * tmp;
             98         }
             99 
            100         SSQ = gammq ( static_cast<long double> ( SIZE - 2 ) / 2.0L, chi / 2.0L );
            101 
            102 
            103     }//end of k loop
            104 
            105     std :: vector< long double> result() const
            106     {
            107         return Result;
            108     }
            109 
            110     long double ssq() const
            111     {
            112         return SSQ;
            113     }
            114 
            115 private:
            116     std :: vector<long double> Y;       // -- Y[SIZE]
            117     std :: vector<long double> X;       // -- X[N][SIZE]
            118     std :: vector<long double> Result;  // -- Result[N]
            119     long double SSQ;                      //fitness of the model
            120 };
            121 
            122 

            其中SIZE即為所要擬合的aj的數(shù)量M,而N為原始數(shù)據(jù)點(diǎn)數(shù)(xi, yi)的數(shù)量N。

            給出gamma函數(shù)計(jì)算代碼
            #include <cmath>
            #include 
            <cstdlib>

            static long double
            gammln ( 
            const long double &xx )
            {
                
            long double     x,
                tmp,
                ser;
                
            static long double cof[6= { 76.18009173-86.5053203324.01409822,
                                              
            -1.2317395160.120858003e-2-0.536382e-5
                                            };
                
            int             j;

                x 
            = xx - 1.0;
                tmp 
            = x + 5.5;
                tmp 
            -= ( x + 0.5 ) * log ( tmp );
                ser 
            = 1.0;
                
            for ( j = 0; j <= 5; j++ )
                {
                    x 
            += 1.0;
                    ser 
            += cof[j] / x;
                }
                
            return -tmp + log ( 2.50662827465 * ser );
            }

            static void
            gcf ( 
            long double *gammcf,
                  
            const long double &a, const long double &x, long double *gln )
            {
                
            const unsigned int ITMAX = 100;
                
            const long double EPS = 3.0e-7;
                unsigned 
            int    n = 0;
                
            long double     gold = 0.0,
                                       g,
                                       fac 
            = 1.0,
                                             b1 
            = 1.0;
                
            long double     b0 = 0.0,
                                     anf,
                                     ana,
                                     an,
                                     a1,
                                     a0 
            = 1.0;

                
            *gln = gammln ( a );
                a1 
            = x;
                
            for ( n = 1; n <= ITMAX; n++ )
                {
                    an 
            = ( float ) n;
                    ana 
            = an - a;
                    a0 
            = ( a1 + a0 * ana ) * fac;
                    b0 
            = ( b1 + b0 * ana ) * fac;
                    anf 
            = an * fac;
                    a1 
            = x * a0 + anf * a1;
                    b1 
            = x * b0 + anf * b1;
                    
            if ( a1 )
                    {
                        fac 
            = 1.0 / a1;
                        g 
            = b1 * fac;
                        
            if ( fabs ( ( g - gold ) / g ) < EPS )
                        {
                            
            *gammcf = exp ( -+ a * log ( x ) - ( *gln ) ) * g;
                            
            return;
                        }
                        gold 
            = g;
                    }
                }
                
            if ( "a too large, ITMAX too small in routine GCF" )
                    exit ( EXIT_FAILURE );
            }

            static void
            gser ( 
            long double *gamser,
                   
            const long double &a, const long double &x, long double *gln )
            {
                
            const unsigned int ITMAX = 100;
                
            const long double EPS = 3.0e-7;
                unsigned 
            int    n = 0;
                
            long double     sum,
                del,
                ap;

                
            *gln = gammln ( a );
                
            if ( x <= 0.0 )
                {
                    
            if ( x < 0.0 )
                        
            if ( "x less than 0 in routine GSER" )
                            exit ( EXIT_FAILURE );
                    
            *gamser = 0.0;
                    
            return;
                }
                
            else
                {
                    ap 
            = a;
                    del 
            = sum = 1.0 / a;
                    
            for ( n = 1; n <= ITMAX; n++ )
                    {
                        ap 
            += 1.0;
                        del 
            *= x / ap;
                        sum 
            += del;
                        
            if ( fabs ( del ) < fabs ( sum ) * EPS )
                        {
                            
            *gamser = sum * exp ( -+ a * log ( x ) - ( *gln ) );
                            
            return;
                        }
                    }
                    
            if ( "a too large, ITMAX too small in routine GSER" )
                        exit ( EXIT_FAILURE );

                    
            return;
                }
            }

            long double
            gammq ( 
            const long double &a, const long double &x )
            {
                
            long double     gamser,
                gammcf,
                gln;

                
            if ( x < 0.0 || a <= 0.0 )
                    
            if ( "Invalid arguments in routine gammq." )
                        exit ( EXIT_FAILURE );

                
            if ( x < ( a + 1.0 ) )
                {
                    gser ( 
            &gamser, a, x, &gln );
                    
            return 1.0 - gamser;
                }
                
            else
                {
                    gcf ( 
            &gammcf, a, x, &gln );
                    
            return gammcf;
                }
            }

            利用克萊姆法則求解線性方程組
            lq.h
             1 #include "det.h"
             2 
             3 #include <vector>
             4 #include <cassert>
             5 #include <cstdlib>
             6 
             7 //
             8 //for solution of the linear equation
             9 //                  A X = B
            10 //
            11 template<class T>
            12 void lq ( const std :: vector<T>& a,    //store A[size][size]
            13           const std :: vector<T>& b,     //store B[size]
            14           const unsigned int& order, //store size
            15           std :: vector<T>& result       //store X[size]
            16         )
            17 {
            18     unsigned int Order = order;
            19     //if order is set to default, calculate
            20     if ( 0 == Order )
            21     {
            22         Order = b.size();
            23     }
            24 
            25     assert ( Order * Order == a.size() );
            26     assert ( Order == b.size() );
            27 
            28     result.clear();
            29 
            30     const T _D = det ( a, Order );  //store D
            31 
            32     if ( 0 == _D )
            33     {
            34         if ( "Failed to solve the linear equation" )
            35             exit ( EXIT_FAILURE );
            36     }
            37 
            38     for ( unsigned int i = 0; i < Order; ++i )
            39     {
            40         std :: vector<T> A = a;
            41         for ( unsigned int j = 0; j < Order; ++j )
            42         {
            43             A[i+j*Order] = b[j];
            44         }
            45         const T D = det ( A, Order );   //store D[i]
            46 
            47         result.push_back ( D / _D );    //get X[i]
            48     }
            49 }
            50 




            在lq.h中有提到一個(gè)det函數(shù),這個(gè)是用來計(jì)算矩陣的行列式值的,因?yàn)榭巳R姆法則就是幾個(gè)行列式的值之間除來除去罷了,代碼如下
            det.h
             1 //return the determinant of a square matrix arr whose size is order by order
             2 template< class T >
             3 T det ( const std :: vector<T>& arr, const unsigned int& order = 0 )
             4 {
             5     unsigned int Order = order;
             6 
             7     //if order is set to default, calculate it
             8     if ( 0 == Order )
             9     {
            10         Order = sqrt ( arr.size() );
            11     }
            12 
            13     assert ( Order * Order == arr.size() );
            14 
            15 
            16     if ( 1 == Order )
            17         return ( arr[0] ) ;
            18 
            19     T sum = 0;
            20     std ::vector<T> arr2 ;
            21     int sign = 1;
            22 
            23     for ( unsigned int i = 0 ; i < Order ; ++i, sign *= -1 )
            24     {
            25         /* copy n-1 by n-1 array into another array */
            26         const unsigned int newsize = ( Order - 1 ) * ( Order - 1 ) ;
            27 
            28         arr2.resize ( newsize );
            29         for ( unsigned int j = 1 ; j < Order ; ++j )
            30         {
            31             for ( unsigned int k = 0, count = 0 ; k < Order ; ++k )
            32             {
            33                 if ( k == i )
            34                     continue ;//jump out of k loop
            35 
            36                 const unsigned int pos = j * Order + k ;
            37                 const unsigned int newpos = ( j - 1 ) *
            38                                             ( Order - 1 ) + count ;
            39                 arr2[newpos] = arr[pos] ;
            40                 count++ ;
            41             }//end of k loop
            42         }//end of j loop
            43 
            44         /*  find determinant value of n-1 by n-1 array and  add it to sum */
            45         sum += arr[i] * sign * det ( arr2, Order - 1 ) ;
            46     }
            47     return sum;
            48 }
            49 


            下邊給出一個(gè)示例
            要擬合的參數(shù)方程為
            a1 x1 + a2 x2 + a3 x3 + a4 x4 + a5 x5 = y
            給出5組數(shù)據(jù)進(jìn)行擬合,分別是(1 0 0 0 0 1)(0 1 0 0 0 2)(0 0 1 0 0 3)(0 0 0 1 0 4)(0 0 0 0 1 5)
             1 #include "regression.h"
             2 #include <iostream>
             3 #include <vector>
             4 
             5 using namespace std;
             6 
             7 int main()
             8 {
             9     const unsigned int N = 5;
            10 
            11     Regression<N, N> r;
            12     vector<long double> y;
            13     vector<long double> x;
            14     vector<long double> result;
            15 
            16 
            17     for ( unsigned int i = 0; i < N; ++i )
            18         y.push_back( 1.0L + i );
            19     r._y( y );
            20 
            21     for ( unsigned int i = 0; i < N; ++i )
            22     {
            23         x.clear();
            24         for ( unsigned int j = 0; j < N; ++j )
            25         {
            26             if ( i == j )
            27                 x.push_back( 1.0L );
            28             else
            29                 x.push_back( 0.0L );
            30         }
            31         r._x( x, i );
            32     }
            33 
            34     r.fit();
            35 
            36     result = r.result();
            37 
            38     for ( unsigned int i = 0; i < N; ++i )
            39         cout << result[i] << endl;
            40 
            41 
            42     return 0;
            43 }





            posted on 2008-04-15 22:38 Wang Feng 閱讀(4916) 評(píng)論(2)  編輯 收藏 引用 所屬分類: Numerical C++

            FeedBack:
            # re: 一般線性模型的最小二次方擬合方法
            2008-11-06 20:07 | cdy20
            這個(gè)blog好多算法  回復(fù)  更多評(píng)論
              
            # re: 一般線性模型的最小二次方擬合方法
            2008-11-06 20:07 | cdy20

            <2011年4月>
            272829303112
            3456789
            10111213141516
            17181920212223
            24252627282930
            1234567

            常用鏈接

            留言簿(4)

            隨筆分類

            隨筆檔案

            Link List

            搜索

            •  

            最新評(píng)論

            閱讀排行榜

            評(píng)論排行榜

            久久久久久亚洲Av无码精品专口| 久久综合成人网| 久久99国产精品久久99| 久久综合中文字幕| 久久天天躁狠狠躁夜夜av浪潮| 久久综合久久鬼色| 色8久久人人97超碰香蕉987| 97久久超碰成人精品网站| 国产精品免费看久久久香蕉| 女人高潮久久久叫人喷水| 无码伊人66久久大杳蕉网站谷歌| 99精品久久精品| 久久亚洲中文字幕精品一区四| 久久精品国产亚洲AV香蕉| 久久综合狠狠色综合伊人| 亚洲国产精品无码久久青草| 日日躁夜夜躁狠狠久久AV| 婷婷综合久久狠狠色99h| 亚洲欧洲精品成人久久曰影片| 久久香综合精品久久伊人| 国内精品久久久久久中文字幕| 影音先锋女人AV鲁色资源网久久| 久久精品国产亚洲欧美| 精品久久久久久久国产潘金莲 | 国产精品伊人久久伊人电影| 狠狠色丁香婷婷久久综合| 久久久国产精品福利免费 | 97久久香蕉国产线看观看| 日韩中文久久| 亚洲嫩草影院久久精品| 日日躁夜夜躁狠狠久久AV| 亚洲日本va午夜中文字幕久久| 亚洲午夜久久影院| 久久99精品久久久久久久不卡 | 99久久婷婷国产一区二区| 无码人妻久久一区二区三区免费| 久久精品女人天堂AV麻| 精品久久一区二区三区| 亚洲AV日韩AV永久无码久久| 亚洲&#228;v永久无码精品天堂久久 | 香蕉久久一区二区不卡无毒影院|