机器学习笔记-多元线性回归
作者:星河滚烫兮
前言
线性回归作为机器学习入门算法,数学原理清晰透彻,展现了机器学习的重要思想,线性回归虽然简单,但也能够解决很多问题。下面讲解线性回归的数学原理与代码实现。
一、基本原理
如上图所示,我们有一些零散数据,我们希望用某个函数曲线拟合这些数据点,从而揭示数据分布的特征,预测未知样本。图中拟合出的是一条直线,但其实通过构造数据,多元线性回归可以拟合出任意曲线。
代价函数对于机器学习来说是核心问题。代价函数就是表征我们的人造曲线与实际标签之间的差值情况,又叫做损失函数。我们通过使代价函数收敛到全局(大多数是局部)最小值,从而得到最终理想模型。线性回归的代价函数使用平方损失函数,如下图所示:
我们想要使这个代价函数值最小,很简单的数学原理,当二次函数导数为零时达到极值。但由于我们事先并不知道所有的参数值
θ
\theta
θ,所以我们通过梯度下降算法
θ
=
θ
−
α
∂
J
(
θ
)
∂
θ
\theta=\theta-\alpha\frac{\partial J(\theta)}{\partial\theta}
θ=θ−α∂θ∂J(θ),可以不断地逼近最小值,
α
\alpha
α为学习率,学习率越大,下降的幅度越大,但过度会导致震荡产生;学习率越小,下降幅度越小,收敛较慢。
对于机器学习问题,我们需要训练集与测试集,学习深入后还会用到交叉验证。一般来说,将数据集的70%划分为训练集,30%划分为测试集。本文没有使用到大规模数据集,仅仅用的自己编造的数据,所以未使用测试集。大家根据实际问题选择。
另外说一下数据标准化,对于多个特征的样本数据,特征之间可能会存在较大数量级的差距,这样会过分强调高数量级的特征,而忽略掉小数量级的特征,为了避免此类情况,我们通常进行数据预处理,包括多种标准化方法,比如z-score标准化,将各个特征缩小至同一范围。
二、数学推导
假设样本有
n
n
n个特征,分别为
x
1
x_1
x1,
x
2
x_2
x2,
x
3
x_3
x3,
…
…
…,
x
n
x_n
xn,对应的权重参数为
θ
1
\theta_1
θ1,
θ
2
\theta_2
θ2,
θ
3
\theta_3
θ3,
…
…
…
θ
n
\theta_n
θn,偏置系数为
θ
0
\theta_0
θ0,为了简化表达,我们加入偏置项
x
0
=
1
x_0=1
x0=1。该样本标签为
y
y
y。设预测函数为
h
(
x
)
=
θ
0
x
0
+
θ
1
x
1
+
θ
2
x
2
+
…
+
θ
n
x
n
h(x)=\theta_0x_0+\theta_1x_1+\theta_2x_2+…+\theta_nx_n
h(x)=θ0x0+θ1x1+θ2x2+…+θnxn,整体代价函数为
J
(
θ
)
=
1
2
m
∑
i
=
1
m
[
y
(
i
)
−
h
(
x
(
i
)
)
]
2
J(\theta)=\frac{1}{2m}\sum_{i=1}^{m}[y(i)-h(x(i))]^2
J(θ)=2m1∑i=1m[y(i)−h(x(i))]2,其中,
m
m
m为样本数,
i
i
i表示第
i
i
i个样本。
根据以上条件,我们进行向量化公式推导(默认所有向量为列向量)。
将输入特征与参数向量化有:
x
(
i
)
=
(
x
0
x
1
x
2
⋮
x
n
)
x^{(i)}=\left(\begin{matrix}x_0\\\begin{matrix}x_1\\x_2\\\vdots\\\end{matrix}\\x_n\\\end{matrix}\right)
x(i)=⎝⎜⎜⎜⎜⎜⎛x0x1x2⋮xn⎠⎟⎟⎟⎟⎟⎞,
θ
=
(
θ
0
θ
1
θ
2
⋮
θ
n
)
\theta=\left(\begin{matrix}\theta_0\\\begin{matrix}\theta_1\\\theta_2\\\vdots\\\end{matrix}\\\theta_n\\\end{matrix}\right)
θ=⎝⎜⎜⎜⎜⎜⎛θ0θ1θ2⋮θn⎠⎟⎟⎟⎟⎟⎞,
x
=
(
x
0
(
1
)
⋯
x
0
(
m
)
⋮
⋱
⋮
x
n
(
1
)
⋯
x
n
(
m
)
)
x=\left(\begin{matrix}x_0^{(1)}&\cdots&x_0^{(m)}\\\vdots&\ddots&\vdots\\x_n^{(1)}&\cdots&x_n^{(m)}\\\end{matrix}\right)
x=⎝⎜⎜⎛x0(1)⋮xn(1)⋯⋱⋯x0(m)⋮xn(m)⎠⎟⎟⎞,代入单样本预测函数
h
(
x
)
h(x)
h(x)有:
h
(
x
(
i
)
)
=
θ
T
⋅
x
(
i
)
h(x^{(i)})=\theta^T\cdot x^{(i)}
h(x(i))=θT⋅x(i)
对整体向量化有:
h
(
x
)
=
x
T
⋅
θ
(
1
)
h(x)=x^T\cdot\theta\ \ \ \ \ (1)
h(x)=xT⋅θ (1)
根据梯度下降,对整体(全部样本)的第
j
j
j个特征
θ
j
(
i
)
\theta_j^{(i)}
θj(i)有:
θ
j
=
θ
j
−
α
∂
J
(
θ
)
∂
θ
j
(
2
)
\theta_j=\theta_j-\alpha\frac{\partial J(\theta)}{\partial\theta_j}\ \ \ \ \ (2)
θj=θj−α∂θj∂J(θ) (2)
向量化表示对整体的全部特征有:
θ
=
θ
−
α
∂
J
(
θ
)
∂
θ
(
3
)
\theta=\theta-\alpha\frac{\partial J(\theta)}{\partial\theta}\ \ \ \ \ (3)
θ=θ−α∂θ∂J(θ) (3)
其中,梯度即偏导项
∂
J
(
θ
)
∂
θ
j
\frac{\partial J\left(\theta\right)}{\partial\theta_j}
∂θj∂J(θ)计算有:
∂
J
(
θ
)
∂
θ
j
=
∂
∂
θ
j
[
1
2
m
∑
i
=
1
m
(
y
(
i
)
−
θ
(
i
)
T
⋅
x
(
i
)
)
2
]
\frac{\partial J\left(\theta\right)}{\partial\theta_j}=\frac{\partial}{\partial\theta_j}[\frac{1}{2m}\sum_{i=1}^{m}{(y^{(i)}-\theta^{{(i)}^T}\cdot x^{(i)})}^2]
∂θj∂J(θ)=∂θj∂[2m1i=1∑m(y(i)−θ(i)T⋅x(i))2]
计算偏导则消去其他无关项有:
∂
J
(
θ
)
∂
θ
j
=
−
1
m
∑
i
=
1
m
(
y
(
i
)
−
θ
(
i
)
T
⋅
x
(
i
)
)
x
j
(
i
)
=
−
1
m
∑
i
=
1
m
(
y
(
i
)
−
h
(
x
(
i
)
)
)
x
j
(
i
)
\frac{\partial J\left(\theta\right)}{\partial\theta_j}=-\frac{1}{m}\sum_{i=1}^{m}{(y^{(i)}-\theta^{{(i)}^T}\cdot x^{(i)})}x_j^{(i)}=-\frac{1}{m}\sum_{i=1}^{m}{(y^{(i)}-h(x^{(i)}))}x_j^{(i)}
∂θj∂J(θ)=−m1i=1∑m(y(i)−θ(i)T⋅x(i))xj(i)=−m1i=1∑m(y(i)−h(x(i)))xj(i)
将上述计算式对整体向量化有:
∂
J
(
θ
)
∂
θ
=
−
1
m
x
⋅
(
y
−
h
(
x
)
)
(
4
)
\frac{\partial J\left(\theta\right)}{\partial\theta}=-\frac{1}{m}x\cdot(y-h(x))\ \ \ \ \ (4)
∂θ∂J(θ)=−m1x⋅(y−h(x)) (4)
其中,
x
=
(
x
0
(
1
)
⋯
x
0
(
m
)
⋮
⋱
⋮
x
n
(
1
)
⋯
x
n
(
m
)
)
x=\left(\begin{matrix}x_0^{(1)}&\cdots&x_0^{(m)}\\\vdots&\ddots&\vdots\\x_n^{(1)}&\cdots&x_n^{(m)}\\\end{matrix}\right)
x=⎝⎜⎜⎛x0(1)⋮xn(1)⋯⋱⋯x0(m)⋮xn(m)⎠⎟⎟⎞(将单个样本作为列向量),将(4)式代入(3)式即得到最终的梯度下降公式:
θ
=
θ
+
α
1
m
x
⋅
(
y
−
h
(
x
)
)
(
5
)
\theta=\theta+\alpha\frac{1}{m}x\cdot(y-h(x))\ \ \ \ \ (5)
θ=θ+αm1x⋅(y−h(x)) (5)
三、公式整理
h
(
x
)
=
x
T
⋅
θ
(
1
)
h(x)=x^T\cdot\theta\ \ \ \ \ (1)
h(x)=xT⋅θ (1)
θ
=
θ
+
α
1
m
x
⋅
(
y
−
h
(
x
)
)
(
5
)
\theta=\theta+\alpha\frac{1}{m}x\cdot(y-h(x))\ \ \ \ \ (5)
θ=θ+αm1x⋅(y−h(x)) (5)
J
(
θ
)
=
1
2
m
∑
i
=
1
m
[
y
(
i
)
−
h
(
x
(
i
)
)
]
2
J(\theta)=\frac{1}{2m}\sum_{i=1}^{m}[y(i)-h(x(i))]^2
J(θ)=2m1i=1∑m[y(i)−h(x(i))]2
四、代码实现
class Mult_Linear_Regression:
"""
多元线性回归模型: y = a0x0 + b1x1 + b2x2 + ... + bnxn 其中,x0=1
x:二维矩阵(m,n)(单样本特征排列成行向量),需进行转置为(n,m)
y:二维矩阵(m,1)
"""
def __init__(self, x, y):
# 定义机器学习设置参数
self.EPOCH = 500 # 迭代次数
self.learning_rate = 0.1 # 学习率α
# 数据集
self.x = np.insert(x.T, 0, 1, axis=0) # 处理后的二维特征输入,每个样本为列向量,同时加入偏置项x0=1
self.y = y
# 参数a0,a1,a2,...,an
self.m = self.x.shape[1] # 样本数m
self.n = self.x.shape[0] # 样本特征数为n
self.a = np.zeros((self.n, 1)) # 参数向量a
def h(self):
# 整体预测函数,x为二维所有样本特征向量(列向量)
return self.x.T @ self.a # 以列向量形式返回行向量点乘列向量
def predict(self, xi):
# 对某个样本进行预测
xi = np.insert(xi, 0, 1)
return self.a.T @ xi
def J(self, h):
# 代价函数:j(β1,β2)
return 1/(2*self.m) * np.sum((self.y-h)**2) # 返回一个实数
def p(self, h):
# 梯度下降算法
gradient = -(1 / self.m) * (self.x.dot(self.y-h)) # 矩阵运算的形式
self.a = self.a - self.learning_rate * gradient # 更新梯度
def train(self):
for i in range(self.EPOCH):
h = self.h()
self.p(h)
print(f"第{i+1}轮损失值为:{self.J(h)}")
import numpy as np
import matplotlib.pyplot as plt
x = np.array([[0], [1], [3], [5], [6]])
y = np.array([0, 1.1, 3.1, 4.95, 6.05])
y = y.reshape((len(y), 1))
C = Mult_Linear_Regression(x, y)
C.train()
new_x = np.arange(-1, 7, 0.01)
plt.plot(new_x, new_x*C.a[1]+C.a[0], c='r')
plt.scatter(x, y)
plt.show()