线性回归
为了让我们的房屋案例更有意思,咱们稍微对数据集进行一下补充,增加上每一个房屋的卧室数目:
居住面积(平方英尺) | 卧室数目 | 价格(千美元) |
---|---|---|
$2104$ | $3$ | $400$ |
$1600$ | $3$ | $330$ |
$2400$ | $3$ | $369$ |
$1416$ | $2$ | $232$ |
$3000$ | $4$ | $540$ |
$\vdots$ | $\vdots$ | $\vdots$ |
现在,输入特征 $x$ 就是在 $R^2$ 范围取值的一个二维向量了。例如 $x_1^{(i)}$ 就是训练集中第 $i$ 个房屋的面积,而 $x_2^{(i)}$ 就是训练集中第 $i$ 个房屋的卧室数目。(通常来说,设计一个学习算法的时候,选择哪些输入特征都取决于你,所以如果你不在波特兰收集房屋信息数据,你也完全可以选择包含其他的特征,例如房屋是否有壁炉,卫生间的数量啊等等。关于特征筛选的内容会在后面的章节进行更详细的介绍,不过目前来说就暂时先用给定的这两个特征了。)
要进行这个监督学习,咱们必须得确定好如何在计算机里面对这个函数/假设 $h$ 进行表示。咱们现在刚刚开始,就来个简单点的,咱们把 $y$ 假设为一个以 $x$ 为变量的线性函数:
\[h_\theta (x) = \theta_0 + \theta_1 \times x_1 + \theta_2 \times x_2\]这里的$\theta_i$是参数(也可以叫做权重),是从 $x$ 到 $y$ 的线性函数映射的空间参数。在不至于引起混淆的情况下,咱们可以把$h_\theta(x)$ 里面的 $\theta$ 省略掉,就简写成 $h(x)$。另外为了简化公式,咱们还设 $x_0 = 1$(这个为 截距项 intercept term)。这样简化之后就有了:
\[h(x) = \sum^n_{i=0} \theta_i x_i = \theta^T x\]等式最右边的 $\theta$ 和 $x$ 都是向量,等式中的 $n$ 是输入变量的个数(不包括$x_0$)。
现在,给定了一个训练集,咱们怎么来挑选/学习参数 $\theta$ 呢?一个看上去比较合理的方法就是让 $h(x)$ 尽量逼近 $y$,至少对咱已有的训练样本能适用。用公式的方式来表示的话,就要定义一个函数,来衡量对于每个不同的 $\theta$ 值,$h(x^{(i)})$ 与对应的 $y^{(i)}$ 的距离。这样用如下的方式定义了一个 成本函数 (cost function):
\[J(\theta) = \frac 12 \sum^m_{i=1}(h_\theta(x^{(i)})-y^{(i)})^2\]如果之前你接触过线性回归,你会发现这个函数和常规最小二乘法 拟合模型中的最小二乘法成本函数非常相似。不管之前接触过没有,咱们都接着往下进行,以后就会发现这是一个更广泛的算法家族中的一个特例。
1 最小均方算法(LMS algorithm)
我们希望选择一个能让 $J(\theta)$ 最小的 $\theta$ 值。怎么做呢,咱们先用一个搜索的算法,从某一个对 $\theta$ 的“初始猜测值”,然后对 $\theta$ 值不断进行调整,来让 $J(\theta)$ 逐渐变小,最好是直到我们能够达到一个使 $J(\theta)$ 最小的 $\theta$。具体来说,咱们可以考虑使用梯度下降法(gradient descent algorithm),这个方法就是从某一个 $\theta$ 的初始值开始,然后逐渐重复更新:$^1$
\[\theta_j := \theta_j - \alpha \frac \partial {\partial\theta_j}J(\theta)\](上面的这个更新要同时对应从 $0$ 到 $n$ 的所有$j$ 值进行。)这里的 $\alpha$ 也称为学习速率。这个算法是很自然的,逐步重复朝向 $J$ 降低最快的方向移动。
1 本文中 $:= $ 表示的是计算机程序中的一种赋值操作,是把等号右边的计算结果赋值给左边的变量,$a := b$ 就表示用 $b$ 的值覆盖原有的$a$值。要注意区分,如果写的是 $a == b$ 则表示的是判断二者相等的关系。(译者注:在 Python 中,单个等号 $=$ 就是赋值,两个等号 $==$ 表示相等关系的判断。)
要实现这个算法,咱们需要解决等号右边的导数项。首先来解决只有一组训练样本 $(x, y)$ 的情况,这样就可以忽略掉等号右边对 $J$ 的求和项目了。公式就简化下面这样:
\[\begin{aligned} \frac \partial {\partial\theta_j}J(\theta) & = \frac \partial {\partial\theta_j} \frac 12(h_\theta(x)-y)^2\\ & = 2 \cdot\frac 12(h_\theta(x)-y)\cdot \frac \partial {\partial\theta_j} (h_\theta(x)-y) \\ & = (h_\theta(x)-y)\cdot \frac \partial {\partial\theta_j}(\sum^n_{i=0} \theta_ix_i-y) \\ & = (h_\theta(x)-y) x_j \end{aligned}\]对单个训练样本,更新规则如下所示:
\[\theta_j := \theta_j + \alpha (y^{(i)}-h_\theta (x^{(i)}))x_j^{(i)}\]这个规则也叫 LMS 更新规则 (LMS 是 “least mean squares” 的缩写,意思是最小均方),也被称为 Widrow-Hoff 学习规则。这个规则有几个看上去就很自然直观的特性。例如,更新的大小与$(y^{(i)} − h_\theta(x^{(i)}))$成正比;另外,当我们遇到训练样本的预测值与 $y^{(i)}$ 的真实值非常接近的情况下,就会发现基本没必要再对参数进行修改了;与此相反的情况是,如果我们的预测值 $h_\theta(x^{(i)})$ 与 $y^{(i)}$ 的真实值有很大的误差(比如距离特别远),那就需要对参数进行更大地调整。
当只有一个训练样本的时候,我们推导出了 LMS 规则。当一个训练集有超过一个训练样本的时候,有两种对这个规则的修改方法。第一种就是下面这个算法:
$
\begin{aligned}
&\qquad 重复直到收敛 {
&\qquad\qquad\theta_j := \theta_j + \alpha \sum^m_{i=1}(y^{(i)}-h_\theta (x^{(i)}))x_j^{(i)}\quad(对每个j)
&\qquad}
\end{aligned}
$
读者很容易能证明,在上面这个更新规则中求和项的值就是$\frac {\partial J(\theta)}{\partial \theta_j}$ (这是因为对 $J$ 的原始定义)。所以这个更新规则实际上就是对原始的成本函数 $J $进行简单的梯度下降。这一方法在每一个步长内检查所有整个训练集中的所有样本,也叫做批量梯度下降法(batch gradient descent)。这里要注意,因为梯度下降法容易被局部最小值影响,而我们要解决的这个线性回归的优化问题只能有一个全局的而不是局部的最优解;因此,梯度下降法应该总是收敛到全局最小值(假设学习速率 $\alpha$ 不设置的过大)。$J$ 很明确是一个凸二次函数。下面是一个样例,其中对一个二次函数使用了梯度下降法来找到最小值。
上图的椭圆就是一个二次函数的轮廓图。图中还有梯度下降法生成的规矩,初始点位置在$(48,30)$。图中的画的 $x$ (用直线连接起来了)标记了梯度下降法所经过的 $\theta$ 的可用值。
对咱们之前的房屋数据集进行批量梯度下降来拟合 $\theta$ ,把房屋价格当作房屋面积的函数来进行预测,我们得到的结果是 $\theta_0 = 71.27, \theta_1 = 0.1345$。如果把 $h_{\theta}(x)$ 作为一个定义域在 $x$ 上的函数来投影,同时也投上训练集中的已有数据点,会得到下面这幅图:
如果在数据集中添加上卧室数目作为输入特征,那么得到的结果就是 $\theta_0 = 89.60, \theta_1 = 0.1392, \theta_2 = −8.738$
这个结果就是用批量梯度下降法来获得的。此外还有另外一种方法能够替代批量梯度下降法,这种方法效果也不错。如下所示:
在这个算法里,我们对整个训练集进行了循环遍历,每次遇到一个训练样本,根据每个单一训练样本的误差梯度来对参数进行更新。这个算法叫做随机梯度下降法(stochastic gradient descent),或者叫增量梯度下降法(incremental gradient descent)。批量梯度下降法要在运行第一步之前先对整个训练集进行扫描遍历,当训练集的规模 $m$ 变得很大的时候,引起的性能开销就很不划算了;随机梯度下降法就没有这个问题,而是可以立即开始,对查询到的每个样本都进行运算。通常情况下,随机梯度下降法查找到足够接近最低值的 $\theta$ 的速度要比批量梯度下降法更快一些。(也要注意,也有可能会一直无法收敛(converge)到最小值,这时候 $\theta$ 会一直在 $J(\theta)$ 最小值附近震荡;不过通常情况下在最小值附近的这些值大多数其实也足够逼近了,足以满足咱们的精度要求,所以也可以用。$^2$)由于这些原因,特别是在训练集很大的情况下,随机梯度下降往往比批量梯度下降更受青睐。
2 当然更常见的情况通常是我们事先对数据集已经有了描述,并且有了一个确定的学习速率$\alpha$,然后来运行随机梯度下降,同时逐渐让学习速率 $\alpha$ 随着算法的运行而逐渐趋于 $0$,这样也能保证我们最后得到的参数会收敛到最小值,而不是在最小值范围进行震荡。(译者注:由于以上种种原因,通常更推荐使用的都是随机梯度下降法,而不是批量梯度下降法,尤其是在训练用的数据集规模大的时候。)