Brief
此程序不通用,属于个人学习记录。前面的推导是可以看的。
今天算是被自己蠢到了,最小二乘法给理解出了很大的问题,结果导致对问题没有很想清楚。我们知道一般最小二乘法是拟合多项式函数的。也就是对形如:
y
=
a
k
k
+
a
k
−
1
k
−
1
+
.
.
.
+
a
1
+
a
0
y=a_{k}^{k}+a_{k-1}^{k-1}+...+a_{1}^{}+a_{0}
y=akk+ak−1k−1+...+a1+a0的函数。然后我们假设
Y
i
Y_i
Yi是测量值,
Y
i
‾
\overline{Y_i}
Yi是拟合函数当
x
=
x
i
x=x_i
x=xi时的函数值,那么 我们的目标就是对于全局的测量数据
(
X
,
Y
)
(X,Y)
(X,Y),我们要使得每一个测量点的
Y
Y
Y值和预测出的
Y
‾
\overline{Y}
Y的差的平方和最小,也就是拟合点到对应的测量数据的距离和最小,即是下面这个函数:
M
i
n
∑
i
=
1
n
(
Y
i
−
Y
i
‾
)
2
Min\sum_{i=1}^{n}(Y_i-\overline{Y_i})^2
Mini=1∑n(Yi−Yi)2这里面的
n
n
n表示测量的样本个数。
问题描述
收到的数据含有一个固定的公式,如下:
F
N
=
4
×
R
∗
1
2
×
E
∗
×
δ
n
3
2
3
F_N=\frac{4\times{{R^*}^{\frac{1}{2}}}\times{E^*}\times{\delta_n^{\frac{3}{2}}}}{3}
FN=34×R∗21×E∗×δn23
其中的
R
∗
R^*
R∗为一个常数值,
δ
n
和
F
N
\delta_n和F_N
δn和FN是实验测试出来的数据,我们的目标就是采用一种拟合的方式求解这个参数
E
∗
E^*
E∗,所以整合一下数据,这其实也就是一个正比例函数关系,拟合一个正比例的系数就可了。如下:
令
:
x
=
4
×
R
∗
1
2
×
δ
n
3
2
3
y
=
F
N
t
h
e
n
:
y
=
E
∗
x
令:x=\frac{4\times{{R^*}^{\frac{1}{2}}}\times{\delta_n^{\frac{3}{2}}}}{3}\\y=F_N\\ then:\\ y=E^*x
令:x=34×R∗21×δn23y=FNthen:y=E∗x
问题解决
最开始这里的理解出现了比较大的问题。因为以前求解一次关系的函数:
y
=
k
x
+
b
y=kx+b
y=kx+b
都是通过单个算式的方式,而不是直接用矩阵的方式去求解,采取算法的方式即是:
k
=
∑
1
n
x
i
y
i
−
n
×
x
‾
×
y
‾
∑
1
n
x
i
2
−
n
×
x
‾
2
b
=
y
‾
−
w
×
x
‾
k=\frac{\sum_{1}^{n}x_iy_i-n\times\overline{x}\times\overline{y}}{\sum_{1}^{n}x_i^2 -n\times\overline{x}^2}\\b=\overline{y}-w\times\overline{x}
k=∑1nxi2−n×x2∑1nxiyi−n×x×yb=y−w×x
然后看着公式我就陷入了深深的疑惑,我这个函数没有
b
b
b呀!也就是说我要过定点
(
0
,
0
)
(0,0)
(0,0)去拟合这这个参数
E
∗
E^*
E∗,好吧。那也没关系,我可以求一个斜率的范围,然后通过程序暴力遍历也可以找到一个大致的值,好的,准备动手,emmm。先画一张图来看看y和新的x之间的关系吧,如下:
好的,看到这么大一个的数字,这个暴力遍历的方法算是破灭了。于是我又开始了我的疑惑,按照上诉的y=kx+b的回归方程,我传进去数据肯定会得到两个参数,一个k,一个b,我要如何才能只得到k而没有b呢。所以就是这么一个思想让我觉得这不是一个一般的拟合。其实是我对其中的内在求解没有理解。
回到最开始的问题:我们在优化测量值和拟合函数值的平方和。怎么做的这个过程?实际上是先建立目标函数:
M
i
n
∑
i
=
1
n
(
y
i
−
(
k
x
i
+
b
)
)
2
Min\sum_{i=1}^{n}(y_i-(kx_i+b))^2
Mini=1∑n(yi−(kxi+b))2
目标函数分别对参数
k
和
参
数
b
k和参数b
k和参数b求导就得到了对应的更新公式。尽管在最后k的表达式和b无关,也就是:
k
=
∑
1
n
x
i
y
i
−
n
×
x
‾
×
y
‾
∑
1
n
x
i
2
−
n
×
x
‾
2
b
=
y
‾
−
w
×
x
‾
k=\frac{\sum_{1}^{n}x_iy_i-n\times\overline{x}\times\overline{y}}{\sum_{1}^{n}x_i^2 -n\times\overline{x}^2}\\\\\\b=\overline{y}-w\times\overline{x}
k=∑1nxi2−n×x2∑1nxiyi−n×x×yb=y−w×x
这是因为目标函数对b求导是:
b
=
y
‾
−
w
×
x
‾
b=\overline{y}-w\times\overline{x}
b=y−w×x带回了原来的式子中,导致了这么一个结果。如果我需要b=0;就是相当于多加了一个约束调价而已。没有什么差别。哎。头秃!被自己蠢哭了。
后续解决
既然是一样的,那就开始解决吧,这里先给多项式的拟合形式,就会觉得采用矩阵运算比上面的公式简单过来。
考虑超定方程组(超定指未知数小于方程个数):
∑
j
=
1
n
X
i
j
β
i
j
=
y
i
,
(
i
=
1
,
2
,
3
,
.
.
.
m
)
\sum{j=1}^{n}X_{ij}\beta_{ij}=y_i,(i=1,2,3,...m)
∑j=1nXijβij=yi,(i=1,2,3,...m)
其中m代表有m个等式,n代表有 n 个未知数
β
\beta
β ,m>n ;将其进行向量化后为:
X
β
=
y
X\beta=y
Xβ=y
其中:
、
、
显然该方程组一般而言没有解,所以为了选取最合适的
β
\beta
β 让该等式"尽量成立",引入残差平方和函数S:
S
(
β
)
=
∥
X
β
−
y
∥
S(\beta)=\left \| X\beta-y \right \|
S(β)=∥Xβ−y∥
当
β
=
β
^
\beta=\widehat{\beta}
β=β
时, 取最小值,记作:
β
^
=
a
r
g
m
i
n
(
S
(
β
)
)
\widehat{\beta}=argmin(S(\beta))
β
=argmin(S(β))
通过对
S
(
β
)
S({\beta})
S(β)进行微分求最值,也就是矩阵对向量求导,可以得到:
X
T
X
β
=
X
T
y
X^TX\beta=X^Ty
XTXβ=XTy
如果矩阵
X
T
X
X^TX
XTX 非奇异则 有唯一解:
β
^
=
(
X
T
X
β
)
−
1
X
T
y
\widehat{\beta}=(X^TX\beta)^{-1}X^Ty
β
=(XTXβ)−1XTy
但是这里依旧存在着这个问题,矩阵中都是没有常数项的,那我们怎们半呢。这里就不打公式了,就直接叙述,假如需要常数项,那么我们就需要在X矩阵的最右边添加以列全1,在
β
\beta
β最后加上那个常数就可以了。
代码
好的,那门问题就此解决了,我们采用矩阵的方式撸了一份matlab和一份python的代码,可惜的是我手贱把matlab给删掉了。都怪他太占空间,我就忍不住删掉了。
Python版本:
import numpy as np
import pandas as pd
from matplotlib import pyplot as plt
file_path='./00.xlsx'
save_path='./pics/'
el = []
for i in range(6):
df = pd.read_excel(file_path,sheet_name='Sheet'+str(i + 1), usecols=[0, 1, 2])
df=np.array(df)
# print (df)
y, delta= df[:, 0], df[:, 1]
y=np.expand_dims(y,-1)
R=df[1][2]
print(R)
x=(delta**(3/2))*(4/3)*np.power(R,1/2)
# print(x, y)
print(x.shape, y.shape)
xt=np.expand_dims(x,-1)
# print(x.shape, xt.shape, y.shape)
#print(x)
e=1 / (np.matmul(x, xt))*np.matmul(x, y)
e = e[0]
el.append(e)
y = y[:, 0]
# print(x)
lx = np.linspace(0, 1.1*max(x), 1000)
# print(lx)
ly = e * lx
for t in range(2):
if t==1:
plt.plot(lx, ly, label='Fitted:$F_n$')
# \frac{4}{3}\times{R^*}^{\frac{1}{3}}\times{\delta_n^{\frac{3}{2}}}
plt.plot(x, y, 'ro', label=r'$x=\frac{4}{3}\times{R^*}^{\frac{1}{3}}\times{\delta_n^{\frac{3}{2}}}$')
plt.plot(delta, y, 'bo', label='original data')
plt.legend()
plt.title("Sheet" + str(i + 1) + ":$F_n-x-{\delta}_n$")
plt.savefig(save_path+"Sheet"+str(i+1)+"_1.jpg")
plt.show()
elif t==0:
plt.plot(lx, ly, label='Fitted:$F_n$')
# \frac{4}{3}\times{R^*}^{\frac{1}{3}}\times{\delta_n^{\frac{3}{2}}}
plt.plot(x, y, 'ro', label=r'$x=\frac{4}{3}\times{R^*}^{\frac{1}{3}}\times{\delta_n^{\frac{3}{2}}}$')
#plt.plot(delta, y, 'bo', label='original data')
plt.legend()
plt.title("Sheet" + str(i + 1) + ":$F_n-x$")
plt.text(0.5*max(x), 0.2*max(y), "$E^* =$"+str(e),alpha=0.8)
plt.text(-1, 3, r'$E^* =$',fontdict={ 'color': 'b'})
plt.savefig(save_path + "Sheet" + str(i+1) + "_2.jpg")
plt.show()
# print(e)
print (el)
效果可以在拟合的曲线上画出来拟合的值,如下: