一、多维特征
目前为止,我们探讨了单变量/特征的回归模型,现在我们对房价模型增加更多的特征,例如房间数、楼层、房龄等,构成一个含有多个变量的模型,模型中的特征为 ( x 1 , x 2 , x 3 , . . . , x n ) (x_1,x_2,x_3,...,x_n) (x1,x2,x3,...,xn) 。

增添更多特征后,我们引入一系列新的表示方式:
n n n = 表示特征的数量
m m m = 表示样本的数量
x ( i ) x^{(i)} x(i) = 表示第 i i i 个训练样本的输入特征值,是特征矩阵中的第 i i i 行,是一个向量
如上图的 x ( 2 ) = [ 1416 3 2 40 ] x^{(2)} = \begin{bmatrix} 1416 \\ 3 \\ 2 \\ 40 \end{bmatrix} x(2)= 14163240
x j ( i ) x^{(i)}_j xj(i) = 表示第 i i i 个训练样本中的第 j j j 个特征
如上图的 x 3 ( 2 ) = 2 x^{(2)}_3 = 2 x3(2)=2
这个公式中有 n + 1 n+1 n+1 个参数和 n n n 个特征变量,为了使得公式简化一些,引入 x 0 = 1 x_{0} = 1 x0=1 ,则公式转化为: h θ ( x ) = θ 0 x 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n h_\theta \left( x \right)=\theta_{0}x_{0} + \theta_{1}x_{1} + \theta_{2}x_{2} + ... + \theta_{n}x_{n} hθ(x)=θ0x0+θ1x1+θ2x2+...+θnxn
现在特征向量
X
X
X 是一个从
0
0
0 开始标记的
n
+
1
n+1
n+1 维的向量,同时参数
θ
θ
θ 也看做一个
n
+
1
n+1
n+1 维的向量。
x
=
[
x
0
x
1
x
2
.
.
.
x
n
]
=
R
n
+
1
θ
=
[
θ
0
θ
1
θ
2
.
.
.
θ
n
]
x = \begin{bmatrix} x_0 \\ x_1 \\ x_2 \\ . \\ . \\ . \\ x_n \end{bmatrix} = R^{n+1} \qquad \theta = \begin{bmatrix} \theta_0 \\ \theta_1 \\ \theta_2 \\ . \\ . \\ . \\ \theta_n \end{bmatrix}
x=
x0x1x2...xn
=Rn+1θ=
θ0θ1θ2...θn
因此公式可以简化为: h θ ( x ) = θ T X h_\theta \left( x \right)=\theta^{T}X hθ(x)=θTX ,其中上标 T T T 代表矩阵转置。
二、多变量梯度下降
本节课程介绍如何使用梯度下降法来处理多变量线性回归,下面是本节用到的公式。
假设函数: h θ ( x ) = θ T X = θ 0 x 0 + θ 1 x 1 + θ 2 x 2 + . . . + θ n x n h_\theta \left( x \right)=\theta^{T}X=\theta_{0}x_{0} + \theta_{1}x_{1} + \theta_{2}x_{2} + ... + \theta_{n}x_{n} hθ(x)=θTX=θ0x0+θ1x1+θ2x2+...+θnxn
模型参数: θ 0 , θ 1 , . . . , θ n \theta_0,\theta_1,...,\theta_n θ0,θ1,...,θn
代价函数: J ( θ 0 , θ 1 , . . . , θ n ) = J ( θ ) = 1 2 m ∑ i = 1 m ( h θ ( x ( i ) ) − y ( i ) ) 2 J(\theta_0, \theta_1, ..., \theta_n) = J(\theta) = \frac{1}{2m} \sum_{i=1}^{m} \left( h_\theta(x^{(i)}) - y^{(i)} \right)^2 J(θ0,θ1,...,θn)=J(θ)=2m1∑i=1m(hθ(x(i))−y(i))2
目标是找出使得代价函数最小的一系列参数,即: min θ 0 , θ 1 , . . . , θ n J ( θ 0 , θ 1 , . . . , θ n ) \min_{\theta_0,\, \theta_1, ..., \theta_n} J(\theta_0, \theta_1, ..., \theta_n) minθ0,θ1,...,θnJ(θ0,θ1,...,θn)
多变量的梯度下降法的数学定义如下,要不断同时更新每个
θ
j
\theta_j
θj 参数,直到收敛。

∂ ∂ θ j J ( θ 0 , θ 1 , . . . , θ n ) = ∂ ∂ θ j J ( θ ) \frac{\partial}{\partial \theta_j} J(\theta_0, \theta_1, ..., \theta_n) = \frac{\partial}{\partial \theta_j} J(\theta) ∂θj∂J(θ0,θ1,...,θn)=∂θj∂J(θ) 是代价函数 J J J 对 θ j \theta_j θj 的偏导数。
根据微积分公式,推导出多变量代价函数的偏导数公式如下。
∂
∂
θ
j
J
(
θ
)
=
1
m
∑
i
=
1
m
(
(
h
θ
(
x
(
i
)
)
−
y
(
i
)
)
∗
x
j
(
i
)
)
\frac{\partial}{\partial \theta_j} J(\theta) = \frac{1}{m} \sum_{i=1}^{m} \left(( h_\theta(x^{(i)}) - y^{(i)} )*x^{(i)}_j\right)
∂θj∂J(θ)=m1i=1∑m((hθ(x(i))−y(i))∗xj(i))
将推导出的偏导数公式带入梯度下降法中,如下。

三、梯度下降法实践1—特征缩放
在面对多维特征问题的时候,如果能保证这些特征都具有相近的尺度,这将帮助梯度下降算法更快地收敛。
以房价问题为例,假设我们使用两个特征,房屋的尺寸和房间的数量,尺寸的值为 0-2000 平方英尺,而房间数量的值则是 0-5,以两个参数分别为横纵坐标,绘制代价函数的等高线图,看出图像会显得很扁,梯度下降算法会沿着一条复杂的路径来找到全局最小值,需要非常多次的迭代才能收敛。

解决的方法是尝试将所有特征的尺度都尽量缩放到-1到+1之间。绘制代价函数的等高线图,图像看起来更圆一些,梯度下降算法会找到一条更直接的路径通向全局最小,花更少的时间实现收敛。

一般而言,执行特征缩放的目的是将特征的取值约束到 -1 到 +1 的范围内。-1 和 +1 这两个数字并不是太重要,比如 0 ⩽ x 1 ⩽ 3 0\leqslant x_1 \leqslant 3 0⩽x1⩽3 或者 − 2 ⩽ x 2 ⩽ 0.5 -2\leqslant x_2 \leqslant 0.5 −2⩽x2⩽0.5 ,非常接近-1 到 +1 的合适范围都可以。因此不用过于担心特征是否都在完全相同的范围内,只要它们足够接近就可以了,目的只是为了让梯度下降算法能够更快收敛。
在特征缩放中,除了将特征除以最大值的方式以外,也可以采用均值归一化的方式。具体做法是将除了 x 0 x_0 x0 外的特征值 x i x_i xi 替换为 ( x i − μ i ) / s i (x_i-\mu_i)/s_i (xi−μi)/si ,使特征值的均值近似为 0, μ i \mu_i μi 是特征值的平均值, s i s_i si 是特征值的标准差,即最大值减去最小值。
四、梯度下降法实践2—学习率
本节课程将介绍什么是“调试”,和一些小技巧确保梯度下降是正常工作的,以及如何选择学习率
α
\alpha
α 梯度下降算法收敛所需要的迭代次数根据模型的不同而不同,我们不能提前预知,我们可以绘制迭代次数和代价函数的图表来观测算法在何时趋于收敛,确保梯度下降算法正常工作。

x x x 轴表示梯度下降算法的迭代次数, y y y 轴表示迭代一定次数后代价函数 J ( θ ) J(\theta) J(θ) 对应的值。如果梯度下降算法正常工作的话,每一步迭代之后代价函数 J ( θ ) J(\theta) J(θ) 的值都应该下降,最终当迭代到一定次数后(图中400次左右), J ( θ ) J(\theta) J(θ) 的值将变化不大,梯度下降算法已经收敛。因此通过这条曲线可以帮助你判断梯度下降算法是否已经收敛。
也有一些自动测试是否收敛的方法,例如将代价函数的变化值与某个很小的阀值 ε \varepsilon ε(例如0.001)进行比较,如果小于阈值就判断函数已收敛,但通常要选择一个合适的阈值 ε \varepsilon ε 是相当困难的,因此更倾向于看上面的曲线图来判断梯度下降算法是否已经收敛。
梯度下降算法的每次迭代受到学习率的影响,如果学习率 α \alpha α 过小,则达到收敛所需的迭代次数会非常多,收敛速度慢;如果学习率 α \alpha α 过大,每次迭代可能不会减小代价函数,可能会越过局部最小值导致无法收敛。为了调试所有情况,通常绘制 J ( θ ) J(\theta) J(θ) 随迭代次数变化的曲线,可以帮助你弄清楚到底发生了什么。
通常可以考虑尝试如下的学习率,按3的倍数来取值
α
=
0.001
,
0.003
,
0.01
,
0.03
,
0.1
,
0.3
,
1
,
3
,
10
\alpha = 0.001, 0.003, 0.01, 0.03, 0.1, 0.3, 1, 3, 10
α=0.001,0.003,0.01,0.03,0.1,0.3,1,3,10
五、特征和多项式回归
本节课程将介绍一些可供选择的特征以及如何得到不同的学习算法,当选择了合适的特征后,这些算法往往是非常有效的。另外也会介绍多项式回归,它能够使用线性回归的方法来拟合非常复杂的函数,甚至是非线性函数。
以预测房价为例,假设有两个特征,分别是房子的临街宽度(frontage)和房子的纵向深度(depth),如下图。

有这两个特征就可以建立线性回归模型: h θ ( x ) = θ 0 + θ 1 x 1 + θ 2 x 2 h_\theta \left( x \right)=\theta_{0} + \theta_{1}x_{1} + \theta_{2}x_{2} hθ(x)=θ0+θ1x1+θ2x2 ,其中 x 1 = f r o n t a g e x_1 = frontage x1=frontage , x 2 = d e p t h x_2 = depth x2=depth 。其实可以创造新的特征,即房子拥有的土地面积 x = f r o n t a g e ∗ d e p t h x = frontage * depth x=frontage∗depth,那么线性回归模型变为: h θ ( x ) = θ 0 + θ 1 x h_\theta \left( x \right)=\theta_{0} + \theta_{1}x hθ(x)=θ0+θ1x 。有时通过定义新的特征,可能会得到一个更好的模型。
与选择特征密切相关的一个概念被称为多项式回归。假设有如下图房子大小和住房价格的数据集,线性回归并不适用来拟合,可能会有多个不同的模型用于拟合,比如二次函数: h θ ( x ) = θ 0 + θ 1 x + θ 2 x 2 h_\theta \left( x \right)=\theta_{0} + \theta_{1}x + \theta_{2}x^{2} hθ(x)=θ0+θ1x+θ2x2 或者三次函数: h θ ( x ) = θ 0 + θ 1 x + θ 2 x 2 + θ 3 x 3 h_\theta \left( x \right)=\theta_{0} + \theta_{1}x + \theta_{2}x^{2} + \theta_{3}x^{3} hθ(x)=θ0+θ1x+θ2x2+θ3x3

通常我们需要先观察数据然后再决定准备尝试怎样的模型,我们可以令: x 1 = x , x 2 = x 2 , x 3 = x 3 x_1=x, x_2=x^2, x_3=x^3 x1=x,x2=x2,x3=x3 ,从而将模型转化为线性回归模型。如果这样选择特征,特征范围差别比较大,那么在运行梯度下降算法前,特征缩放就变得很重要了。

除了建立三次函数模型以外,也可以选择其它的特征,比如: h θ ( x ) = θ 0 + θ 1 x + θ 2 x h_\theta \left( x \right)=\theta_{0} + \theta_{1}x + \theta_{2}\sqrt{x} hθ(x)=θ0+θ1x+θ2x ,通过选择不同的特征,有时可以得到更好的模型。

六、代码实现
下面以 Coursera 上的多元线性回归数据集 ex1data2.txt 为例实现代码:
import numpy as np
import matplotlib.pyplot as plt
# load data, data.shape = (47, 3)
data = np.genfromtxt("ex1data2.txt", delimiter=',')
(m, n) = data.shape
X = data[:, :-1]
y = data[:, -1]
# normalization
mu = X.mean(axis=0)
sigma = X.std(axis=0, ddof=1)
X = (X - mu) / sigma
X = np.c_[np.ones(m), X] # 增加一列 1
# parameters
alpha = 0.01
num_iters = 1500
theta = np.zeros(n)
J_history = np.zeros(num_iters)
# Gradient Descent
for i in range(0, num_iters):
error = (X @ theta).flatten() - y # error.shape = (47, )
theta -= (alpha / m) * np.sum(X * error[:, np.newaxis], 0)
J_history[i] = np.sum(np.power(error, 2)) / (2 * m)
# predict
predict = (np.array([1650, 3]) - mu) / sigma
predict = np.r_[1, predict]
print(predict @ theta)
# plot the convergence graph
plt.plot(np.arange(J_history.size), J_history)
plt.xlabel('Number of iterations')
plt.ylabel('Cost J')
plt.show()
得到的 ( θ 0 , θ 1 , θ 2 ) (\theta_0, \theta_1, \theta_2) (θ0,θ1,θ2) 结果是: [ 340412.6595 , 110631.0484 , − 6649.4724 ] [340412.6595, 110631.0484, -6649.4724] [340412.6595,110631.0484,−6649.4724],预测在 ( x 1 = 1650 , x 2 = 3 ) (x_1 = 1650, x_2 = 3) (x1=1650,x2=3) 时的房价为 293101.0568574823 293101.0568574823 293101.0568574823。
绘制的迭代收敛曲线如下:

1524

被折叠的 条评论
为什么被折叠?



