回 帖 发 新 帖 刷新版面

主题:求拟合三次方程 Y=b0+b1X+b2X2+b3X3 的算法

我只知道一次方程的线性拟合,但不知道二次和三次方程的拟合 [em10]

下面是一次方程的
用最小二乘法 做線性擬合
如果壹組數據滿足線性關係式 yi = A + B xi,由相關結論可知數學公式 (其中 Σ 表示求和,N 表示資料組的總個數)
數學公式如下
[img]http://www.ied.edu.hk/apfslt/v3_issue2/lailf/image008.gif[/img]

但三次方的呢? [em18][em18]
希望得到高手帮助

回复列表 (共9个回复)

沙发

http://blog.programfan.com/article.asp?id=5187
我的这篇里虽然没讲二次、三次,但原理是一样的,你用笔算算就可以得出公式。

板凳

谢谢rickone
按您的文章,我现在只能做到
e = ∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)^2 = 0
但下面的偏导方程却不知道怎样导出,能够指教吗?

3 楼

是这样的,这个函数是一个四元函数,因为你要确定四个系数,现在要它最小(偏差最小),所以必要条件是偏导为0,四个偏导是:

e = ∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)^2

de/db0=-2∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)=0
de/db1=-2∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)xi=0
de/db2=-2∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)xi^2=0
de/db3=-2∑(yi - b0 - b1*xi - b2*xi^2 - b3*xi^3)xi^3=0

这是一个线性方程组,化简一下:
∑yi - nb0 - b1∑xi - b2∑xi^2 - b3∑xi^3=0
∑yixi - b0∑xi - b1∑xi^2 - b2∑xi^3 - b3∑xi^4=0
∑yixi^2 - b0∑xi^2 - b1∑xi^3 - b2∑xi^4 - b3∑xi^5=0
∑yixi^3 - b0∑xi^3 - b1∑xi^4 - b2∑xi^5 - b3∑xi^6=0

然后求解之,将系数矩阵和常数合在一起进行初等行变换使系数矩阵变成单位矩阵,那常数列对应的就是方程的解。

4 楼

谢谢版主的帮助
我是才学做vb的
对数学算法可以说一窍不通。
这样复杂的矩阵解法用计算机怎么解呢?

5 楼

再次谢谢rickone 已经拟合成功

6 楼

这个方程组不复杂啊,才四阶,不要被符号吓倒了

∑yi - nb0 - b1∑xi - b2∑xi^2 - b3∑xi^3=0
∑yixi - b0∑xi - b1∑xi^2 - b2∑xi^3 - b3∑xi^4=0
∑yixi^2 - b0∑xi^2 - b1∑xi^3 - b2∑xi^4 - b3∑xi^5=0
∑yixi^3 - b0∑xi^3 - b1∑xi^4 - b2∑xi^5 - b3∑xi^6=0

整理成一般形式

nb0      + b1∑xi   + b2∑xi^2 + b3∑xi^3=∑yi
b0∑xi   + b1∑xi^2 + b2∑xi^3 + b3∑xi^4=∑yixi
b0∑xi^2 + b1∑xi^3 + b2∑xi^4 + b3∑xi^5=∑yixi^2
b0∑xi^3 + b1∑xi^4 + b2∑xi^5 + b3∑xi^6=∑yixi^3

令b={b0,b1,b2,b3}'
A={
{  n   ,∑xi  ,∑xi^2,∑xi^3},
{∑xi  ,∑xi^2,∑xi^3,∑xi^4},
{∑xi^2,∑xi^3,∑xi^4,∑xi^5},
{∑xi^3,∑xi^4,∑xi^5,∑xi^6}}
c={∑yi,∑yixi,∑yixi^2,∑yixi^3}'
于是方程就是
Ab=c
如果A可逆,求出它的逆阵左乘上c就是一个解
b=A^-1c

不要看这里的求和符号多,其实并不复杂,现在你手上拿到的是n个点(xi,yi),这是已知,那求A和c的过程可以是:
double a[4][4]={0.0},c[4]={0.0};
for(int i=0;i<N;++i)
{
   double tmp=1.0;
   a[0][1]+=(tmp*=x[i]);
   a[0][2]+=(tmp*=x[i]);
   a[0][3]+=(tmp*=x[i]);
   a[1][3]+=(tmp*=x[i]);
   a[2][3]+=(tmp*=x[i]);
   a[3][3]+=(tmp*=x[i]);
   c[0]+=(tmp=y[i]);
   c[1]+=(tmp*=x[i]);
   c[2]+=(tmp*=x[i]);
   c[3]+=(tmp*=x[i]);
}
然后对A其余的元素补上:
a[0][0]=(double)N;
a[1][0]=a[0][1];
a[2][0]=a[1][1]=a[0][2];
a[3][0]=a[2][1]=a[1][2]=a[0][3];
a[3][1]=a[2][2]=a[1][3];
a[3][2]=a[2][3];
到此A和c就全部求出来了,接下来就是解线性方程组Ab=c,这里才4阶,小case,现实中需要求很大阶的方程,都不在话下,算法是P级的。你可以查查资料,关于线性方程组求解的算法。

7 楼

不客气,如果你有matlab应该更容易一些。

8 楼

我是用消元法硬解4元1次方程的,不是用矩阵解的,计算过程很复杂,程序很大。不过我觉得已经很成功了。
数学方法的确很重要,解题过程会变得简单,程序也会简单。看来以后还是要多学一些数学对于编程也很有益处。

这个帖子我已经收下了
再次谢谢你

下面是vb具体程序,已经验证没有错误
Dim sngData(1, n) As Single         'n个 样本数据
Dim b(3) As Double      '最小二乘法 3次方程拟合输出的4个常数项

'输入数据的预处理程序
For i = 0 To n
    sngData(0, i) = xi
    sngData(1, i) = yi
Next i

Function subAccQuotiety(n As Integer)    'n 样点数 ,
Dim dblCurveMid(1, 20) As Double    '中间数据结果数组
Dim i As Integer
    dblCurveMid(0, 0) = n
    For i = 1 To n
        dblCurveMid(0, 1) = dblCurveMid(0, 1) + sngData(0, i)         '∑xi
        dblCurveMid(0, 2) = dblCurveMid(0, 2) + sngData(0, i) ^ 2     '∑xi ^ 2
        dblCurveMid(0, 3) = dblCurveMid(0, 3) + sngData(0, i) ^ 3     '∑xi ^ 3
        dblCurveMid(0, 4) = dblCurveMid(0, 4) + sngData(0, i) ^ 4     '∑xi ^ 4
        dblCurveMid(0, 5) = dblCurveMid(0, 5) + sngData(0, i) ^ 5     '∑xi ^ 5
        dblCurveMid(0, 6) = dblCurveMid(0, 6) + sngData(0, i) ^ 6     '∑xi ^ 6
        dblCurveMid(0, 7) = dblCurveMid(0, 7) + sngData(1, i)         '∑yi
        dblCurveMid(0, 8) = dblCurveMid(0, 8) + sngData(1, i) * sngData(0, i)       '∑yixi
        dblCurveMid(0, 9) = dblCurveMid(0, 9) + sngData(1, i) * sngData(0, i) ^ 2   '∑yixi ^ 2
        dblCurveMid(0, 10) = dblCurveMid(0, 10) + sngData(1, i) * sngData(0, i) ^ 3 '∑yixi ^ 3
    Next i
    dblCurveMid(1, 0) = dblCurveMid(0, 0) * dblCurveMid(0, 4) - dblCurveMid(0, 1) * dblCurveMid(0, 3)
    dblCurveMid(1, 1) = dblCurveMid(0, 1) * dblCurveMid(0, 4) - dblCurveMid(0, 2) * dblCurveMid(0, 3)
    dblCurveMid(1, 2) = dblCurveMid(0, 2) * dblCurveMid(0, 4) - dblCurveMid(0, 3) * dblCurveMid(0, 3)
    dblCurveMid(1, 3) = dblCurveMid(0, 7) * dblCurveMid(0, 4) - dblCurveMid(0, 8) * dblCurveMid(0, 3)
    dblCurveMid(1, 4) = dblCurveMid(0, 0) * dblCurveMid(0, 5) - dblCurveMid(0, 2) * dblCurveMid(0, 3)
    dblCurveMid(1, 5) = dblCurveMid(0, 1) * dblCurveMid(0, 5) - dblCurveMid(0, 3) * dblCurveMid(0, 3)
    dblCurveMid(1, 6) = dblCurveMid(0, 2) * dblCurveMid(0, 5) - dblCurveMid(0, 4) * dblCurveMid(0, 3)
    dblCurveMid(1, 7) = dblCurveMid(0, 7) * dblCurveMid(0, 5) - dblCurveMid(0, 9) * dblCurveMid(0, 3)
    dblCurveMid(1, 8) = dblCurveMid(0, 0) * dblCurveMid(0, 6) - dblCurveMid(0, 3) * dblCurveMid(0, 3)
    dblCurveMid(1, 9) = dblCurveMid(0, 1) * dblCurveMid(0, 6) - dblCurveMid(0, 4) * dblCurveMid(0, 3)
    dblCurveMid(1, 10) = dblCurveMid(0, 2) * dblCurveMid(0, 6) - dblCurveMid(0, 5) * dblCurveMid(0, 3)
    dblCurveMid(1, 11) = dblCurveMid(0, 7) * dblCurveMid(0, 6) - dblCurveMid(0, 10) * dblCurveMid(0, 3)

    dblCurveMid(1, 12) = dblCurveMid(1, 0) * dblCurveMid(1, 6) - dblCurveMid(1, 4) * dblCurveMid(1, 2)
    dblCurveMid(1, 13) = dblCurveMid(1, 1) * dblCurveMid(1, 6) - dblCurveMid(1, 5) * dblCurveMid(1, 2)
    dblCurveMid(1, 14) = dblCurveMid(1, 3) * dblCurveMid(1, 6) - dblCurveMid(1, 7) * dblCurveMid(1, 2)
    dblCurveMid(1, 15) = dblCurveMid(1, 0) * dblCurveMid(1, 10) - dblCurveMid(1, 8) * dblCurveMid(1, 2)
    dblCurveMid(1, 16) = dblCurveMid(1, 1) * dblCurveMid(1, 10) - dblCurveMid(1, 9) * dblCurveMid(1, 2)
    dblCurveMid(1, 17) = dblCurveMid(1, 3) * dblCurveMid(1, 10) - dblCurveMid(1, 11) * dblCurveMid(1, 2)

    dblCurveMid(1, 18) = dblCurveMid(1, 12) * dblCurveMid(1, 16) - dblCurveMid(1, 15) * dblCurveMid(1, 13)
    dblCurveMid(1, 19) = dblCurveMid(1, 14) * dblCurveMid(1, 16) - dblCurveMid(1, 17) * dblCurveMid(1, 13)
    dblCurveMid(0, 20) = dblCurveMid(1, 19) / dblCurveMid(1, 18)   '已经求得 B0

    dblCurveMid(1, 18) = dblCurveMid(1, 13) * dblCurveMid(1, 15) - dblCurveMid(1, 16) * dblCurveMid(1, 12)
    dblCurveMid(1, 19) = dblCurveMid(1, 14) * dblCurveMid(1, 15) - dblCurveMid(1, 17) * dblCurveMid(1, 12)
    dblCurveMid(0, 19) = dblCurveMid(1, 19) / dblCurveMid(1, 18)   '已经求得 B1


    dblCurveMid(1, 0) = dblCurveMid(0, 1) * dblCurveMid(0, 1) - dblCurveMid(0, 0) * dblCurveMid(0, 2)
    dblCurveMid(1, 1) = dblCurveMid(0, 1) * dblCurveMid(0, 2) - dblCurveMid(0, 0) * dblCurveMid(0, 3)
    dblCurveMid(1, 2) = dblCurveMid(0, 1) * dblCurveMid(0, 3) - dblCurveMid(0, 0) * dblCurveMid(0, 4)
    dblCurveMid(1, 3) = dblCurveMid(0, 7) * dblCurveMid(0, 1) - dblCurveMid(0, 8) * dblCurveMid(0, 0)
    dblCurveMid(1, 4) = dblCurveMid(0, 2) * dblCurveMid(0, 1) - dblCurveMid(0, 0) * dblCurveMid(0, 3)
    dblCurveMid(1, 5) = dblCurveMid(0, 2) * dblCurveMid(0, 2) - dblCurveMid(0, 0) * dblCurveMid(0, 4)
    dblCurveMid(1, 6) = dblCurveMid(0, 2) * dblCurveMid(0, 3) - dblCurveMid(0, 0) * dblCurveMid(0, 5)
    dblCurveMid(1, 7) = dblCurveMid(0, 7) * dblCurveMid(0, 2) - dblCurveMid(0, 9) * dblCurveMid(0, 0)
    dblCurveMid(1, 8) = dblCurveMid(0, 3) * dblCurveMid(0, 1) - dblCurveMid(0, 0) * dblCurveMid(0, 4)
    dblCurveMid(1, 9) = dblCurveMid(0, 3) * dblCurveMid(0, 2) - dblCurveMid(0, 0) * dblCurveMid(0, 5)
    dblCurveMid(1, 10) = dblCurveMid(0, 3) * dblCurveMid(0, 3) - dblCurveMid(0, 0) * dblCurveMid(0, 6)
    dblCurveMid(1, 11) = dblCurveMid(0, 7) * dblCurveMid(0, 3) - dblCurveMid(0, 10) * dblCurveMid(0, 0)

    dblCurveMid(1, 12) = dblCurveMid(1, 1) * dblCurveMid(1, 4) - dblCurveMid(1, 0) * dblCurveMid(1, 5)
    dblCurveMid(1, 13) = dblCurveMid(1, 2) * dblCurveMid(1, 4) - dblCurveMid(1, 0) * dblCurveMid(1, 6)
    dblCurveMid(1, 14) = dblCurveMid(1, 3) * dblCurveMid(1, 4) - dblCurveMid(1, 0) * dblCurveMid(1, 7)
    dblCurveMid(1, 15) = dblCurveMid(1, 1) * dblCurveMid(1, 8) - dblCurveMid(1, 0) * dblCurveMid(1, 9)
    dblCurveMid(1, 16) = dblCurveMid(1, 2) * dblCurveMid(1, 8) - dblCurveMid(1, 0) * dblCurveMid(1, 10)
    dblCurveMid(1, 17) = dblCurveMid(1, 3) * dblCurveMid(1, 8) - dblCurveMid(1, 0) * dblCurveMid(1, 11)

    dblCurveMid(1, 18) = dblCurveMid(1, 12) * dblCurveMid(1, 16) - dblCurveMid(1, 15) * dblCurveMid(1, 13)
    dblCurveMid(1, 19) = dblCurveMid(1, 14) * dblCurveMid(1, 16) - dblCurveMid(1, 17) * dblCurveMid(1, 13)
    dblCurveMid(0, 18) = dblCurveMid(1, 19) / dblCurveMid(1, 18)   '已经求得 B2

    dblCurveMid(1, 18) = dblCurveMid(1, 13) * dblCurveMid(1, 15) - dblCurveMid(1, 12) * dblCurveMid(1, 16)
    dblCurveMid(1, 19) = dblCurveMid(1, 14) * dblCurveMid(1, 15) - dblCurveMid(1, 17) * dblCurveMid(1, 12)
    dblCurveMid(0, 17) = dblCurveMid(1, 19) / dblCurveMid(1, 18)   '已经求得 B3

    b(0) = dblCurveMid(0, 20)
    b(1) = dblCurveMid(0, 19)
    b(2) = dblCurveMid(0, 18)
    b(3) = dblCurveMid(0, 17)
End Function

9 楼

高斯消去法,似乎有现成的、经典的程序阿!

我来回复

您尚未登录,请登录后再回复。点此登录或注册