目录
- 1 最小二乘拟合(方法一)
- 1.1 数学推导
- 1.2 算例
- 1.3 Python 代码
- 2.最小二乘拟合(方法二)
- 2.1 数学推导
- 2.2 算例
- 2.3 Python 代码
- 3 最小二乘法拟合(方法三)
- 3.1 数学推导
- 3.2 算例
- 3.3 Python 代码
- 4 利用sklearn.linear_model()
- 4.1 参考资料
- 4.2 Python 代码
1 最小二乘拟合(方法一)
本章介绍的是我在上研究生课程《数值分析》时所学的内容,也是最一般的解法,可以对任意函数进行拟合。
1.1 数学推导
对一组数据,要在某个函数类
中构造一个函数
,使得
取得极小值。
此处的函数类就是指很多种类函数的集合,例如幂函数、三角函数、指数函数、有理函数、多项式函数等。例如,常用的多项式函数类有
,
。其中
为n阶多项式,
为n元一阶多项式,分别对应着多项式拟合和多维线性回归。
残差函数定义为
令对系数
的偏导为0,即可求出使残差函数
最小的系数
的值
简便起见,记
则可写成如下形式
化简为
注意到,公式中的系数中
,则实际上的操作步骤为分别对每个系数求偏导,并令偏导为0,从而求出使残差函数
取到极小值的所有的系数。写成矩阵的形式
上式方程组称为法方程组(Normal Equation),向量称为回归系数(Regression Coefficients)。用更一般的形式将上式再次改写
则可通过矩阵求逆的方式求出回归系数
1.2 算例
利用一阶多项式通过1.1节的方法对如下数据进行最小二乘拟合。
Independent variable x | Dependent variable y |
0 | 394.33 |
4 | 329.50 |
8 | 291.00 |
12 | 255.17 |
16 | 229.33 |
20 | 204.83 |
24 | 179.00 |
28 | 163.83 |
32 | 150.33 |
则法方程组为
带入数据
求解得到
则可得到线性回归方程
拟合结果如下
1.3 Python 代码
#%% import neccesary packages
import numpy as np
import matplotlib.pyplot as plt
#%% generate the dataset
x = np.arange(0,33,4)
y = np.array([394.33, 329.50, 291.00, 255.17, 229.33, 204.83, 179.00, 163.83, 150.33])
print(x)
#%% calculate the normal equation
A11 = 9
A12 = np.sum(x)
A21 = A12
A22 = np.sum(np.power(x,2))
A = np.array([[A11,A12],[A21,A22]])
print(A)
b1 = np.sum(y)
b2 = np.sum(x*y)
b=np.array([b1, b2])
print(b)
#%% solve the polynamial coefficient a0 & a1
a = np.linalg.inv(A).dot(b)
a0 = a[0]
a1 = a[1]
print(a)
#%% plot the picture
fig, ax = plt.subplots(1, 1, figsize=(6, 3))
ax.scatter(x, y, color='black')
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
ax.plot(x, a0 + a1 * x)
plt.show()
2.最小二乘拟合(方法二)
本章介绍我自己的推导思路,本文以多项式拟合为例说明思路,其他函数的拟合思路相同。
2.1 数学推导
对一组数据进行多项式拟合,假设多项式为
对任意数据点,它与多项式
在
轴方向上的距离称为残差
,定义为
拟合的目标是寻找一组多项式系数使得残差函数
取最小值,本章将直接利用最小二乘法求解。将每个数据点的残差写成矩阵形式
定义残差函数为
要使残差函数最小,本质上是求如下方程的最小二乘解
上式可写成一般形式
(1)当为方阵时,其最小二乘解为
(2)在大多数情况下,不为方阵,可用Moore-Penrose逆
求解
定理1: 设是秩为
的矩阵,且
的满秩分解为
则
定理2: 设有解的充要条件是
其通解为
其唯一极小范数最小二乘解为
2.2 算例
本章算例与1.2节相同,以作对照。
利用一阶多项式对如下数据进行最小二乘拟合。
Independent variable x | Dependent variable y |
0 | 394.33 |
4 | 329.50 |
8 | 291.00 |
12 | 255.17 |
16 | 229.33 |
20 | 204.83 |
24 | 179.00 |
28 | 163.83 |
32 | 150.33 |
列写的一般形式
利用命令
求解矩阵
的
逆,并求其唯一极小范数最小二乘解
求解结果与第一章相同。
2.3 Python 代码
#%% import neccesary packages
import numpy as np
import matplotlib.pyplot as plt
#%% generate the dataset
x = np.arange(0,33,4)
y = np.array([394.33, 329.50, 291.00, 255.17, 229.33, 204.83, 179.00, 163.83, 150.33])
print(x)
#%% solve the polynamial coefficient a0 & a1
A = np.vstack((np.array([1]*9), x))
print(A)
pinv_A = np.linalg.pinv(A).T
print(pinv_A)
a = pinv_A.dot(y)
print(a)
a0 = a[0]
a1 = a[1]
#%% plot the picture
fig, ax = plt.subplots(1, 1, figsize=(6, 3))
ax.scatter(x, y, color='black')
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
ax.plot(x, a0 + a1 * x)
plt.show()
3 最小二乘法拟合(方法三)
本章重点介绍线性回归算法。其实该算法本质上和第一章方法一样,只不过将其限定为一阶多项式,推导出更直观的表达方法。
3.1 数学推导
假设线性回归模型如下
式中为模型噪声服从高斯分布:
。
假设需要对一组数据进行线性回归,定义残差函数
优化目标为最小化残差函数
和第一章方法一样,令残差函数对系数
的偏导为0
联立式(1)和式(2)解方程得到的代数表达式
为表达简便,记
其中,分别为拟合数据
的平均值,
则的表达式可改写为
3.2 算例
本章算例与1.2节相同,以作对照。
对如下数据进行线性回归。
Independent variable x | Dependent variable y |
0 | 394.33 |
4 | 329.50 |
8 | 291.00 |
12 | 255.17 |
16 | 229.33 |
20 | 204.83 |
24 | 179.00 |
28 | 163.83 |
32 | 150.33 |
计算系数
计算结果和第一章、第二章结果一致。
3.3 Python 代码
#%% import neccesary packages
import numpy as np
import matplotlib.pyplot as plt
#%% generate the dataset
x = np.arange(0,33,4)
y = np.array([394.33, 329.50, 291.00, 255.17, 229.33, 204.83, 179.00, 163.83, 150.33])
print(x)
#%%
x_bar = np.sum(x)/9
y_bar = np.sum(y)/9
Sxy = np.sum((x-x_bar)*(y-y_bar))
Sxx = np.sum(np.power(x-x_bar,2))
beta_1 = Sxy/Sxx
beta_0 = y_bar - x_bar * beta_1
print(beta_0)
print(beta_1)
#%%
fig, ax = plt.subplots(1, 1, figsize=(6, 3))
ax.scatter(x, y, color='black')
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
ax.plot(x, beta_0 + beta_1 * x)
plt.show()
4 利用sklearn.linear_model()
4.1 参考资料
官网链接:Scikit-learn官网链接 教学1:python-sklearn学习笔记 第一节 linear_model 教学2:numpy中newaxis函数的基本用法及其理解(傻瓜版)
4.2 Python 代码
#%% import neccesary packages
import numpy as np
import matplotlib.pyplot as plt
import sklearn.linear_model as lm
#%% generate the dataset
x = np.arange(0,33,4)
y = np.array([394.33, 329.50, 291.00, 255.17, 229.33, 204.83, 179.00, 163.83, 150.33])
print(x)
#%%
x_lr = np.linspace(0,40,500)
lr = lm.LinearRegression()
lr.fit(x[:, np.newaxis],y)
y_lr = lr.predict(x_lr[:, np.newaxis])
#%%
fig, ax = plt.subplots(1, 1, figsize=(6, 3))
ax.scatter(x, y, color='black')
plt.xlabel("x")
plt.ylabel("y")
plt.grid()
ax.plot(x_lr, y_lr)