目錄
1.最小二乘法的原理和解決的問題
2.最小二乘法的公式解法
2.1? 擬合h(x)?= a * x
2.2 擬合 h(x) = a0 + a1*x
2.3擬合 h(x) = a0 + a1 *x + a3 * x^3
?因為采用矩陣法來進(jìn)行最小二乘法的函數(shù)擬合時,會出現(xiàn)系數(shù)矩陣的逆矩陣不存在的情況有一定的局限性,所以本篇對公式法進(jìn)行簡單說明。并用c++進(jìn)行代碼的書寫。
1.最小二乘法的原理和解決的問題
最下二乘法的形式:
目標(biāo)函數(shù) =???(觀測值? -? 理論值)^2
? ? ? ? 觀測值就是我們實際數(shù)據(jù)中的值,理論值就是我們進(jìn)行函數(shù)擬合后用擬合函數(shù)計算出的值。
本篇中我們以最簡單的線性回歸為例進(jìn)行說明。
? ? ? ? 我們有n組樣本(Xi,Yi) i = (1,2,3,……,n)
? ? ? ? 擬合函數(shù)的形式:h(x)?= a0 + a1 * x + a2 *x^2 + a3 *x^3.
? ? ? ? 最小二乘法要做的就是找到最小的一組 a(a0 、a1、a2、a3……),使得
? ? ? ???(h(x) -? yi)^2最小。方法就是對各個系數(shù)求偏導(dǎo),并讓偏導(dǎo)數(shù)等于0即可。
2.最小二乘法的公式解法
2.1? 擬合h(x)?= a * x
??? ? 對a求偏導(dǎo)得:
?2 *??= 0
?化簡得:a = Lxy / Lxx
?其中??Lxx =?? ,? ?Lxy =?,ex為x的均值,ey為y的均值
代碼如下:
double calculate(std::vector<double> xs,std::vector<double> ys){
int len = xs.size();
double Lxy = 0;
double Lxx = 0;
for(int i = 0; i < len ; i++){
Lxy += xs[i] * ys[i];
Lxx += qPow(xs[i],2);
}
double ret = 0;
ret = Lxy / Lxx;
return ret;
}
2.2 擬合 h(x) = a0 + a1*x
對a0和a1分別求偏導(dǎo)的得:
a0:?= 0
a1:? ?2 *?= 0
?聯(lián)立兩個方程解得:a0 = ey - a1 * ex?
? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?a1 = Lxy / Lxx(ex、ey、Lxy 和Lxx的含義同上)
代碼如下:
double *calculate1(std::vector<double> xs,std::vector<double> ys){
int len = xs.size();
//結(jié)果
double *ret = new double[2];
double ex = 0;//x坐標(biāo)的均值
double ey = 0;//y坐標(biāo)的均值
double Lxx = 0;//x坐標(biāo)的平方差*len
double Lxy = 0;//(Xi-ex)*(Yi-ey)
//輔助計算
double xsum = 0;//x的和
double ysum = 0;//y的和
//計算xusm
for(int i = 0; i < len ; i++){
xsum += xs[i];
ysum += ys[i];
}
ex = xsum / len;
ey = double(ysum / len);
for(int i = 0; i < len ; i++){
Lxx += pow(xs[i]-ex,2);
Lxy += (xs[i]-ex)*(ys[i]-ey);
}
ret[1] = Lxy / Lxx;//計算a1
ret[0] = ey - ret[1]*ex;//計算a0
return ret;
}
2.3擬合 h(x) = a0 + a1 *x + a3 * x^3
對a0、a1和a3分別求偏導(dǎo)的得:
a0:? ? 2*?= 0;
a1:? ?2*?= 0;
a3 :? ?2*?= 0
聯(lián)立方程組解得:
a0?= ey - a1*ex - a3 * ex^3( ey為y 的均值,ex 為x的均值,ex^3為x^3的均值)
a1 = (Lxy * L(x^3)(x^3)?- Lx^3 y * Lxy) / (Lxx *L(x^3)(x^3) - Lxy*Lyx)
a3 = (Lx^3y * Lxx - Lxy * L(x^3)*x) / (Lxx*L(x^3*x^3) - Lxy*Lyx)
Lxy、Lxx含義同上
L(x^3)(x^3)表示:
Lx3y表示:
?代碼如下:文章來源:http://www.zghlxwxcb.cn/news/detail-534605.html
double *calculate(std::vector<double> xs,std::vector<double> ys){
int len = xs.size();
double ey = 0;//y的均值
double ex1 = 0;//x的均值
double ex3 = 0;//x的三次方的均值
double L11 = 0;//x的平方差
double L12 = 0;//x的3次方的平方差*len
double L21= 0;//等于L12
double L1y = 0;//(Xi-ex)*(Yi-ey)的和
double L2y = 0;//(Xi^3-ex3)*(Yi-ey)的和
double L22 = 0;//x的3次方的平方差*len
double Lyy = 0;//y的平方差*len
double ysum = 0;
double xsum1 = 0;
double xsum3 = 0;
//計算均值
for(int i = 0; i < len; i++){
ysum += ys[i];//y的總和
xsum1 += xs[i];//x的總和
xsum3 += std::pow(xs[i],3);//x的3次方的總和
}
//計算各個值
ey = ysum / len;
ex1 = xsum1 / len;
ex3 = xsum3 / len;
for(int i = 0 ; i < len ;i++){
L11 += qPow(xs[i]-ex1,2);//x的方差*len
L12 += (xs[i]-ex1)*(qPow(xs[i],3)-ex3);
L1y += (xs[i]-ex1)*(ys[i]-ey);
L2y += (qPow(xs[i],3)-ex3)*(ys[i]-ey);
L22 += qPow((qPow(xs[i],3)-ex3),2);//x的3次方的方差*len
Lyy += qPow(ys[i]-ey,2);
}
L21 = L12;
double ret[3];
ret[2] = (L2y * L11 - L1y * L21)/(L11 * L22 - L12 * L21);
ret[1] = (L1y * L22 - L2y * L12)/(L11 * L22 - L12 * L21);
ret[0] = ey - ret[1]*ex1 - ret[2]*ex3;
return ret;
}
以上是我在編寫一個插值函數(shù)時遇到矩陣法不可以求出擬合函數(shù)后,從原始的概念入手進(jìn)行的函數(shù)擬合,如有差錯之處歡迎批評指正。文章來源地址http://www.zghlxwxcb.cn/news/detail-534605.html
到了這里,關(guān)于最小二乘法的幾種擬合函數(shù)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!