0. 概要
线性回归,其实我们在高中时期就已经学习过——最小二乘法,这也正是本文中提到的正规方程。本文从单变量、多变量两个方面介绍线性回归,并指出模型评估的标准——损失函数,以及如何求出损失函数最小时的解——梯度下降、正规方程。
1. 单变量线性回归
在数据集中,特征(这里指自变量)x 的类数为1,从 x 到 y 建立线性回归方程。它是一种监督学习,因为对于每个数据,我们给出了“正确的答案”。为了描述回归问题,有以下常见变量:
- m:代表训练集中实例的个数
- x:代表特征 / 输入变量
- y:代表目标变量 / 输出变量
- (x, y) :代表训练集中的实例
- h:代表学习算法的解决方案或函数,也成为假设(hypothesis)
如何表达假设函数h,对于单变量线性而言,一般应为:
h
θ
(
𝑥
)
=
θ
0
+
θ
1
x
ℎ_θ(𝑥) = θ_0 + θ_1x
hθ(x)=θ0+θ1x
2. 代价函数
代价函数也称之为平方误差(代价)函数。我们将模型所预测的值与训练集中实际值之间的差距称为建模误差,通过平均误差来反映模型好坏。于是就有了代价函数:
𝐽
(
θ
0
,
θ
1
)
=
1
2
m
∑
(
h
θ
(
𝑥
𝑖
)
−
𝑦
i
)
𝐽(θ_0, θ_1) =\frac{1}{2m}∑ (ℎ_θ(𝑥^𝑖) − 𝑦^i)
J(θ0,θ1)=2m1∑(hθ(xi)−yi)
为什么是 1 / 2m:这里的目标是要求出代价函数最小时,对应的 θ 的解,因此乘一个常数是不影响结果的。而之所以是这个,是因为后面的求和项,在求导以会出现2m。
3. 梯度下降
梯度下降是一个用来求函数最小值的算法,我们将使用梯度下降算法来求出代价函数 𝐽(𝜃0, 𝜃1) 的最小值。
梯度下降背后的思想是:开始时我们随机选择一个参数的组合(𝜃0, 𝜃1, . . . . . . , 𝜃𝑛 ),计算代价函数,然后我们寻找下一个能让代价函数值下降最多的参数组合。我们持续这么做直到找到一个局部最小值。梯度下降的公式为:
r
e
p
e
a
t
u
n
t
i
l
c
o
n
v
e
r
g
e
n
c
e
{
θ
j
:
=
θ
j
−
α
∂
∂
θ
j
J
(
θ
0
,
θ
1
)
(
f
o
r
j
=
0
a
n
d
j
=
1
)
}
repeat \ until \ convergence \{\ \\ θ_j:=θ_j- α \frac{∂}{∂θ_j} J(θ_0,θ_1) \quad (for \ j=0 \ and \ j = 1) \}
repeat until convergence{ θj:=θj−α∂θj∂J(θ0,θ1)(for j=0 and j=1)}
对于单变量线性回归,每一次迭代应该表示为:
t
e
m
p
0
:
=
θ
0
−
α
∂
∂
θ
0
J
(
θ
0
,
θ
1
)
t
e
m
p
1
:
=
θ
1
−
α
∂
∂
θ
1
J
(
θ
0
,
θ
1
)
θ
0
:
=
t
e
m
p
0
θ
1
:
=
t
e
m
p
1
temp_0:=θ_0- α \frac{∂}{∂θ_0} J(θ_0,θ_1) \\ temp_1:=θ_1- α \frac{∂}{∂θ_1} J(θ_0,θ_1) \\ θ_0:=temp_0 \\ θ_1:=temp_1
temp0:=θ0−α∂θ0∂J(θ0,θ1)temp1:=θ1−α∂θ1∂J(θ0,θ1)θ0:=temp0θ1:=temp1
值得注意的是,我们需要同时更新两个 θ 的值。同步更新是更加自然的实现方法,即使不同步程序也能正常运行。实现梯度下降算法的代码如下所示:
def gradient_descent(f, init_x, lr=0.01, step_num=100):
# lr代表学习率,step_num是梯度下降的重复次数
x = init_x
for i in range(step_num):
grad = numerical_gradient(f, x)
x -= lr * grad
return x
numerical_gradient()是求偏导或者导数的函数,对于线性回归,我们可以直接得到它的导数公式;但对于一些深度学习回归,可能就只有通过导数的定义来求解了。
4. 学习率
上述公式中,其中 α 是学习率(learning rate),它决定了我们沿着能让代价函数下降程度最大的方向 向下迈出的步子有多大,在批量梯度下降中,我们每一次都同时让所有的参数减去学习速率 乘以代价函数的导数。
如果 α 太小,程序移动的速度会非常慢;而如果 α 太大,则梯度下降法可能会越过最低点,甚至无法收敛。
在代价函数接近局部最低点时,导数值会自动变得越来越小,即使学习率保持不变,梯度下降也会自动采取较小的幅度,所以实际上没有必要再另外减小学习率 α 。
5. 多变量线性回归
当原始数据有更多特征时,即拥有更多自变量 x ,对应的便是多变量线性回归。此时的假设函数如下:
h
θ
(
𝑥
)
=
θ
T
x
=
θ
0
+
θ
1
𝑥
1
+
θ
2
𝑥
2
+
.
.
.
+
θ
𝑛
𝑥
n
ℎθ(𝑥) = θ^T x = θ_0 + θ_1𝑥_1 + θ_2𝑥_2+. . . +θ_𝑛𝑥_n
hθ(x)=θTx=θ0+θ1x1+θ2x2+...+θnxn
多变量回归的损失函数,也是所有建模误差的平均平方和:
𝐽
(
θ
0
,
θ
1
,
.
.
.
,
θ
n
)
=
1
2
m
∑
(
h
θ
(
𝑥
𝑖
)
−
𝑦
i
)
𝐽(θ_0, θ_1,...,θ_n) =\frac{1}{2m} ∑ (ℎ_θ(𝑥^𝑖) − 𝑦^i)
J(θ0,θ1,...,θn)=2m1∑(hθ(xi)−yi)
批量梯度下降算法本质也与上述相同,初步求导以后,公式为:
r
e
p
e
a
t
{
θ
j
:
=
θ
j
−
α
1
m
Σ
[
(
h
θ
(
x
i
)
−
y
i
)
⋅
x
i
]
(
s
i
m
u
l
t
a
n
e
o
u
s
l
y
u
p
d
a
t
e
θ
j
f
o
r
j
=
0
,
1
,
2
,
.
.
.
,
n
)
}
repeat \{\ \\ θ_j:=θ_j- α \frac{1}{m} Σ[\ (h_θ(x^i)-y^i) \ · \ x^i\ ] \ \\ (simultaneously \quad update \quad θ_j \\ for \quad j=0,1,2,...,n) \}
repeat{ θj:=θj−αm1Σ[ (hθ(xi)−yi) ⋅ xi ] (simultaneouslyupdateθjforj=0,1,2,...,n)}
6. 特征缩放
在我们面对多维特征问题的时候,我们要保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛。
解决的方法是尝试将所有特征的尺度都尽量缩放到 -1 到 1 之间。
(1)最大最小值归一化:将数值映射到[0, 1]上。
x
n
e
w
=
x
−
m
i
n
(
x
)
m
a
x
(
x
)
−
m
i
n
(
x
)
x^{new} = \frac{x-min(x)}{max(x)-min(x)}
xnew=max(x)−min(x)x−min(x)
(2)z标准化:将数值缩放到0附近,且数据的分布变为均值为0,标准差为1的标准正态分布。
x
n
e
w
=
x
−
x
ˉ
σ
x^{new} = \frac{x-\bar x}{σ}
xnew=σx−xˉ
7. 正规方程
正规方程,其实是通过求解下面方程,找出使得代价函数最小的参数:
∂
∂
θ
j
J
(
θ
j
)
=
0
\frac{∂}{∂θ_j}\ J(θ_j) = 0
∂θj∂ J(θj)=0
其实本质上似乎就是最小二乘法,不过这里在运算时进行了向量化。利用正规方程求解出结果为:
θ
=
(
X
T
X
)
−
1
X
T
y
θ = (X^TX)^{-1}X^Ty
θ=(XTX)−1XTy
正规方程的代码实现如下:
# 正规方程
def normalEqn(X, y):
X_T = np.transpose(X)
theta = numpy.linalg.inv(X_T*X)*X_T*y
return theta
梯度下降与正规方程进行比较:
梯度下降 | 正规方程 |
---|---|
需要选择学习率 α | 不需要 |
需要多次迭代 | 一次运算得出 |
适用于n各种情况 | n较大时运算代价大 |
适用各种模型 | 只适用于线性模型 |
8. 更多
本文所做的,只是以机器学习初学者视角,对线性回归做出比较基础的解释。事实上,回归,即使仅仅说是线性回归,都是一个非常深的数学领域,像回归的决定系数、均方误差,多元回归的异方差、共线性,t检验F检验等等等等,这些依旧不算很深入,都值得我们去做进一步的学习。