线性回归
许久不见,最近刚刚完成了转正答辩,大概也有两个月没有更新博客了(主要是因为懒哈哈哈),大数据那部分也会继续更,这边也要开一个新坑了,争取把机器学习和深度学习的基本算法都整理出来,与大伙一起分享学习。首先先从监督学习中最基本的线性回归开始,这个系列基本分为以下两个部分:数学原理介绍和代码实战,因为talk is cheap, show me the code!
数学原理
我们先从数学原理来阐述线性回归,线性回归是统计学中最基础的数学模型,机器学习和深度学习也在一定程度上有一些线性回归算法的影子。因此,从线性回归开始,我认为是学习机器学习技术的一个最好的起点了。
一元线性回归
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y = w x + b y=wx+b </math>y=wx+b
首先构建一个最基础的一元线性回归数学模型,是不是很熟悉,大家初中应该都学过的一元线性方程,我们可以基于数据集对其进行建模,学习参数 w 和 b 。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> L ( y ^ , y ) = ( y i ^ − y ) 2 L(\hat{y},y)=(\hat{y_i}-y)^2 </math>L(y^,y)=(yi^−y)2
但是,我们如何去学习呢?假设我们已经得到了一组参数 w 和 b ,将自变量 x 代入,可以得到预测的 y ,将其与实际的 y 值构造损失函数,损失函数也称为代价函数(cost function),这个代价函数计算了模型预测值和实际值之间的差异程度。对于线性回归,最简单的损失函数为预测值和实际值误差的平方了,即预测值和真实值的平均平方距离,称之为均方误差MSE。目标是求解最小化L时w和b的值。公式如上。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> L ( y ^ , y ) = 1 N ∑ i = 1 N ( y ^ − y ) 2 = 1 N ∑ i = 1 N [ ( w x i + b ) − y ] 2 \begin{aligned} L(\hat{y},y) &= \frac{1}{N}\sum_{i=1}^N(\hat{y}-y)^2 \\ &= \frac{1}{N}\sum_{i=1}^N[(wx_i+b)-y]^2 \end{aligned} </math>L(y^,y)=N1i=1∑N(y^−y)2=N1i=1∑N[(wxi+b)−y]2
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> w ∗ , b ∗ = a r g m i n L ( w , b ) = a r g m i n 1 N ∑ i = 1 N [ ( w x i + b ) − y i ] 2 \begin{aligned} w^*,b^*&=argminL(w,b) \\ &= argmin\frac{1}{N}\sum_{i=1}^N[(wx_i+b)-y_i]^2 \end{aligned} </math>w∗,b∗=argminL(w,b)=argminN1i=1∑N[(wxi+b)−yi]2
接下来把一元线性方程带入代价函数公式,并且寻找使得代价函数最小的参数 w 和 b 。argmin是一种常见的数学符号,指的是令所求函数最小的所需参数值
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∂ ∂ w L ( w , b ) = 2 N ∑ i = 1 N x i ( w x i + b − y i ) = 0 \begin{aligned} \frac{\partial}{\partial{w}}L(w,b)&=\frac 2N\sum_{i=1}^Nx_i(wx_i+b-y_i) \\ &= 0 \end{aligned} </math>∂w∂L(w,b)=N2i=1∑Nxi(wxi+b−yi)=0
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∂ ∂ b L ( w , b ) = 2 N ∑ i = 1 N w x i + b − y i = 0 \begin{aligned} \frac{\partial}{\partial{b}}L(w,b)&=\frac 2N\sum_{i=1}^Nwx_i+b-y_i \\ &= 0 \end{aligned} </math>∂b∂L(w,b)=N2i=1∑Nwxi+b−yi=0
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> w ∗ = ∑ i = 1 N x i y i − b ∗ ∑ i = 1 N x i ∑ i = 1 N x i 2 b ∗ = y ‾ − w ∗ x ‾ w^*=\frac{\sum_{i=1}^Nx_iy_i-b^*\sum_{i=1}^Nx_i}{\sum_{i=1}^Nx_i^2}\\ b^*=\overline{y}-w^*\overline{x} </math>w∗=∑i=1Nxi2∑i=1Nxiyi−b∗∑i=1Nxib∗=y−w∗x
接下来,对 w 和 b 分别求偏导,并使其为0,可以得到 w 和 b 的最优值。这就是最小二乘法的数学求解过程,当然这种简单的数学模型是有解析解的,之后的例如神经网络,卷积神经网络是很难求解出解析解的,只能使用梯度下降法求出数值解,梯度下降法之后再详细介绍。
多元线性回归
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y i = ∑ d = 1 D w d x i , d + b b = w D + 1 y i = ∑ d = 1 D + 1 w d x i , d y_i=\sum_{d=1}^Dw_dx_{i,d}+b \\ b=w_{D+1} \\ y_i=\sum_{d=1}^{D+1}w_dx_{i,d} \\ </math>yi=d=1∑Dwdxi,d+bb=wD+1yi=d=1∑D+1wdxi,d
现在我们将自变量扩展成多元的情况,也就是有多个特征影响预测值,这也是和现实问题比较接近的数学模型,因为一件事情的结果往往不可能是只有一个因素决定的。我们将 b 也作为一个 w ,d表示维度,i表示第 i 个样本,这样就可以将D维特征扩展成D+1维
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> w = [ w 1 w 2 ⋮ w D w D + 1 ] \boldsymbol{w}=\begin{bmatrix} w_1 \\ w_2 \\ \vdots \\ w_D \\ w_{D+1} \end{bmatrix} </math>w=⎣ ⎡w1w2⋮wDwD+1⎦ ⎤
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> X = [ x 1 x 2 ⋮ x N ] = ( x 1 , 1 x 1 , 2 ⋯ x 1 , D 1 x 2 , 1 x 2 , 2 ⋯ x 2 , D 1 ⋮ ⋮ ⋱ ⋮ ⋮ x N , 1 x N , 2 ⋯ x N , D 1 ) \boldsymbol{X}=\begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_N \end{bmatrix} =\begin{pmatrix} x_{1,1} & x_{1,2} & \cdots & x_{1,D} & 1\\ x_{2,1} & x_{2,2} & \cdots & x_{2,D} & 1\\ \vdots & \vdots & \ddots & \vdots & \vdots\\ x_{N,1} & x_{N,2} & \cdots & x_{N,D} & 1\\ \end{pmatrix} </math>X=⎣ ⎡x1x2⋮xN⎦ ⎤=⎝ ⎛x1,1x2,1⋮xN,1x1,2x2,2⋮xN,2⋯⋯⋱⋯x1,Dx2,D⋮xN,D11⋮1⎠ ⎞
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y = [ y 1 y 2 ⋮ y N ] \boldsymbol{y}=\begin{bmatrix} y_1 \\ y_2 \\ \vdots \\ y_N \end{bmatrix} </math>y=⎣ ⎡y1y2⋮yN⎦ ⎤
接下来将各个变量用矩阵形式表示, w 、X 和 y 的表示如上
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> y i = ∑ d = 1 D + 1 w d x i , d = w T x i = X w y_i=\sum_{d=1}^{D+1}w_dx_{i,d}\\ =\boldsymbol{w}^T\boldsymbol{x}_i\\ =\boldsymbol{Xw} </math>yi=d=1∑D+1wdxi,d=wTxi=Xw
机器学习更喜欢这种矩阵相乘的形式,看起来更加简洁,同样的计算机也更加喜欢矩阵计算。值得一提的是,在数学公式中,黑体符号一般指的都是向量形式。
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> L ( w ) = ( X w − y ) T ( X w − y ) = ∣ ∣ X w − y ∣ ∣ 2 2 L(w)=(\boldsymbol{Xw}-\boldsymbol{y})^T(\boldsymbol{Xw}-\boldsymbol{y})=||\boldsymbol{Xw}-\boldsymbol{y}||^2_2 </math>L(w)=(Xw−y)T(Xw−y)=∣∣Xw−y∣∣22
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> ∂ ∂ w L ( w ) = 2 X T ( X w − y ) = 0 \frac{\partial}{\partial{\boldsymbol{w}}}L(\boldsymbol{w})=2\boldsymbol{X}^T(\boldsymbol{Xw}-\boldsymbol{y})=0 </math>∂w∂L(w)=2XT(Xw−y)=0
<math xmlns="http://www.w3.org/1998/Math/MathML" display="block"> X T X w = X T y ( X T X ) − 1 X T X w = ( X T X ) − 1 X T y w ∗ = ( X T X ) − 1 X T y \boldsymbol{X}^T\boldsymbol{X}\boldsymbol{w}=\boldsymbol{X}^T\boldsymbol{y} \\ (\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{X}\boldsymbol{w}=(\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{y}\\ \boldsymbol{w}^*=(\boldsymbol{X}^T\boldsymbol{X})^{-1}\boldsymbol{X}^T\boldsymbol{y}\\ </math>XTXw=XTy(XTX)−1XTXw=(XTX)−1XTyw∗=(XTX)−1XTy
多元线性回归的代价函数和一元线性回归的代价函数是一样的,同样使用最小二乘法对参数 w 进行计算,得到以上结果。最小二乘法可以得到一个确定的最优解,这些最优解可以组成一个最优超平面。
代码实战
首先先导入kaggle上的波士顿房屋价格预测数据集,看一下数据量和特征数
python
# 导入必要的库
import numpy as np
import matplotlib.pyplot as plt
from sklearn.datasets import load_boston
from sklearn.model_selection import train_test_split
from sklearn.linear_model import LinearRegression
# 加载波士顿房屋数据集
boston = load_boston()
print('数据量:{}'.format(len(boston.data))) # 数据量:506
print('特征数:{}'.format(len(boston.data[0]))) # 特征数:13
再来看看有哪些特征
python
print(boston.feature_names)
# ['CRIM' 'ZN' 'INDUS' 'CHAS' 'NOX' 'RM' 'AGE' 'DIS' 'RAD' 'TAX' 'PTRATIO' 'B' 'LSTAT']
接下来再准备一下数据集
python
# 数据准备
X = boston.data
y = boston.target
# 将数据集划分为训练集和测试集
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.2, random_state=42)
# 创建线性回归模型实例
model = LinearRegression()
# 模型训练
model.fit(X_train, y_train)
# 模型预测
y_pred = model.predict(X_test)
# 计算均方误差
mse = np.mean((y_pred - y_test) ** 2)
print("均方误差:", mse)
# 结果可视化
plt.scatter(y_test, y_pred)
plt.plot([y_test.min(), y_test.max()], [y_test.min(), y_test.max()], 'k--', lw=2)
plt.xlabel('true_price')
plt.ylabel('predict_price')
plt.title('linear')
plt.show()
我们可以很明显的看出,这个数据集中的预测值是非线性的,而线性回归是需要预测的变量和特征是线性的,所以线性回归比较难以拟合实际值,这也是线性回归的一个局限性。那么,什么情况下才会使用线性回归进行建模呢?
- 首先,需要建模的问题得是一个回归问题
- 要预测的变量和特征是线性关系
- 多元线性回归中不同特征之间应该相互独立,避免线性相关