最小二乘法算法
最小二乘法(又称最小平方法)是一种数学优化技术。它通过最小化误差的平方和寻找数据的最佳函数匹配。利用最小二乘法可以简便地求得未知的数据,并使得这些求得的数据与实际数据之间误差的平方和为最小。最小二乘法还可用于曲线拟合。其他一些优化问题也可通过最小化能量或最大化熵用最小二乘法来表达。
拟合
在实际问题中,常常给定一组测定的离散数据,
x
i
,
y
i
x_i, y_i
xi,yi, 欲求自变量和因变量的近似表达式. 由于测量值本身就带有误差,并且测量数据往往数据量很大,因此使用插值法工作量会很大,效果也往往不好,解决该类问题最常用的方法就是最小二乘法. 下面通过一个简单的例题进行说明.
综上对于给定的拟合数据
x
和
y
x和y
x和y我们只需要构造出他们对应的矩阵,那么我们便可以通过矩阵的逆运算得到系数矩阵
a
a
a
代码
#include<bits/stdc++.h>
using namespace std
;
const int maxn
= 100;
double x
[maxn
][maxn
],y
[maxn
][maxn
],maze
[maxn
][maxn
],w
[maxn
],inv
[maxn
][maxn
];
double yy
[maxn
],a
[maxn
];
double getA(double arcs
[maxn
][maxn
],int n
)
{
if(n
==1)
{
return arcs
[0][0];
}
double ans
= 0;
double temp
[maxn
][maxn
]={0.0};
int i
,j
,k
;
for(i
=0;i
<n
;i
++)
{
for(j
=0;j
<n
-1;j
++)
{
for(k
=0;k
<n
-1;k
++)
{
temp
[j
][k
] = arcs
[j
+1][(k
>=i
)?k
+1:k
];
}
}
double t
= getA(temp
,n
-1);
if(i
%2==0)
{
ans
+= arcs
[0][i
]*t
;
}
else
{
ans
-= arcs
[0][i
]*t
;
}
}
return ans
;
}
void getAStart(double arcs
[maxn
][maxn
],int n
,double ans
[maxn
][maxn
])
{
if(n
==1)
{
ans
[0][0] = 1;
return;
}
int i
,j
,k
,t
;
double temp
[maxn
][maxn
];
for(i
=0;i
<n
;i
++)
{
for(j
=0;j
<n
;j
++)
{
for(k
=0;k
<n
-1;k
++)
{
for(t
=0;t
<n
-1;t
++)
{
temp
[k
][t
] = arcs
[k
>=i
?k
+1:k
][t
>=j
?t
+1:t
];
}
}
ans
[j
][i
] = getA(temp
,n
-1);
if((i
+j
)%2 == 1)
{
ans
[j
][i
] = - ans
[j
][i
];
}
}
}
}
bool
GetMatrixInverse(double src
[maxn
][maxn
],int n
,double des
[maxn
][maxn
])
{
double flag
=getA(src
,n
);
double t
[maxn
][maxn
];
if(flag
==0)
{
return false
;
}
else
{
getAStart(src
,n
,t
);
for(int i
=0;i
<n
;i
++)
{
for(int j
=0;j
<n
;j
++)
{
des
[i
][j
]=t
[i
][j
]/flag
;
}
}
}
return true
;
}
int main()
{
int m
,n
;
freopen("txt/li4-2.txt","r",stdin);
freopen("txt/li4-2_out.txt","w+",stdout);
while(~scanf("%d",&m
)) {
for(int i
=0;i
<m
;i
++) x
[i
][0] = 1;
for(int i
=0;i
<m
;i
++) y
[i
][0] = 1;
for(int i
=0;i
<m
;i
++) scanf("%lf",&x
[i
][1]);
for(int i
=0;i
<m
;i
++) scanf("%lf",&y
[i
][1]);
for(int i
=0;i
<m
;i
++) scanf("%lf",&w
[i
]);
scanf("%d",&n
);
for(int i
=2;i
<2*n
-1;i
++) {
for(int j
=0;j
<m
;j
++) {
x
[j
][i
] = x
[j
][i
-1]*x
[j
][1];
y
[j
][i
] = y
[j
][i
-1]*y
[j
][1];
}
}
printf("矩阵 X[][]\n");
for(int i
=0;i
<n
;i
++) {
for(int j
=0;j
<n
;j
++) {
maze
[i
][j
] = 0;
for(int k
=0;k
<m
;k
++) {
maze
[i
][j
] += w
[k
]*x
[k
][i
+j
];
}
printf("%.2f ",maze
[i
][j
]);
}
printf("\n");
}
printf("矩阵 Y[][]\n");
for(int i
=0;i
<n
;i
++) {
yy
[i
] = 0;
for(int j
=0;j
<m
;j
++) {
yy
[i
] += w
[j
]*x
[j
][i
]*y
[j
][1];
}
printf("%.2f\n",yy
[i
]);
}
printf("矩阵 X[][]的逆\n");
if(GetMatrixInverse(maze
,n
,inv
)) {
for(int i
=0;i
<n
;i
++) {
for(int j
=0;j
<n
;j
++) printf("%.2f ",inv
[i
][j
]);
printf("\n");
}
}
printf("系数矩阵 a[][]\n");
for(int i
=0;i
<n
;i
++) {
a
[i
] = 0;
for(int j
=0;j
<n
;j
++) {
a
[i
] += inv
[i
][j
] * yy
[j
];
}
printf("%.2f\n",a
[i
]);
}
}
return 0;
}