回归模型可以做很多事情:如果你要做一个股票预测系统,输入股市的许多信息,输出是接下来的股市指数;如果你在设计自动驾驶应用,输入各种传感器的信息,输出是方向盘的角度;如果做推荐系统,输入是使用者和商品,输出是使用者购买商品的可能性。我们将通过宝可梦的 CP 值(战斗力) 预测,来讲解回归模型及其应用。如果我们可以精确地预测出一只宝可梦在进化后的 CP 值,就可以决定是否要进化这只宝可梦,如果你发现进化后的 CP 值很低,则可以节省糖果材料去进化其它的宝可梦。

案例分析:精灵宝可梦 CP 值预测

因此我们需要找出一个函数 $f$, 输入是某只宝可梦的相关信息,输出是该宝可梦进化后的 CP 值。如果我们将该宝可梦用 $x$ 表示,用 $x_{cp}$ 表示当前的 CP 值(下标通常用来指代某一个完整东西中其中的一部分,比如索引矩阵 $A$ 中 $i$ 行 $j$ 列的元素 $A_{i,j}$.) 用 $x_s$ 表示该宝可梦的物种归属(比如妙蛙种子), $x_{hp}$ 表示该宝可梦的生命力值,$x_{w}$ 代表重量,$x_{h}$ 代表高度。输出应该是进化后的 CP 值,使用 $y$ 来表示。

步骤一:定义模型(函数集合)

假设先写个简单的模型形式 $y=b+w \cdot x_{c p}$, 即认为进化后的 CP 值 $y$ 等于常数项 $b$ 加上某个数值 $w$ 乘上现在输入的宝可梦 $x$ 在进化前的 CP 值 $x_{cp}$. 在该模型中的 $w$ 和 $b$ 是参数(parameters), 可以是任何数值,通过不同的参数值可以得到不同的函数,比如:

不难发现函数可以有无数个,训练数据可以告诉我们其中哪个函数是合理的。而 $y=b+w \cdot x_{c p}$ 这种形式的模型被称为线性模型(Linear Model), 通常为 $y=b+\sum w_{i} x_{i}$ 这种形式。其中变量 $x_{i}$ 是输入的各种不同的属性(attribute), 也被称为特征(feature). 而参数 $w_{i}$ 被称为权重(weight), $b$ 被称为偏置(bias).

注:数学符号通常是取其代表含义的英文词首字母,如函数(function).

步骤二:评价函数的好坏

我们需要收集训练数据,才能找出最好的函数。监督学习的训练数据需要同时有函数的输入和输出,即特征与标签。我们使用上标来表示一个完整训练样本(包含多个特征) 的编号,如输入为 $x^1, x^2, \ldots$, 而对应的实际应有的输出使用 $\hat{y}^1,\hat{y}^2, \ldots$ 来表示。由于是回归问题,输出应该是一个标量值,没有不同的成分。但对于其他问题,输出可能是有结构(structure) 的, 因此还是需要使用上下标进行区分。

假设现在收集了 10 只宝可梦作为训练数据(数据来源), 图中每一个蓝色的点代表一只宝可梦,横轴代表原始的 CP 值,纵轴代表进化后的 CP 值,我们用 $x^n_{cp}$ 表示第 $n$ 个数据的 CP 值。

为了得到函数的好坏,我们需要再定义一个损失函数(Loss Function) $L$, 输入为一个函数,输出是该函数的好坏,损失即用多么不好来表示。因此损失函数可以写成 $L(f)=L(w,b)$, 输入为函数 $f$, 而 $f$ 又是由 $w$ 和 $b$ 决定的,所以损失函数其实是在衡量一组参数的好坏。

损失函数的定义方式很多,常见做法是:将 $w$ 和 $b$ 代入 $y=b+w \cdot x_{c p}$ 函数中,得到基于现在的函数得到的预测值 $y$. 而 $\hat{y}$ 是真正的数值,把真正的数值减掉预测的数值后取平方,就是在单个样本 $x$ 上的估测误差。将 10 只宝可梦的估测误差求和,就得到了最后的损失函数:

为了方便理解,我们可以将损失函数 $L(w,b)$ 的形状画出来,上图中的每一个点代表着一组 $w$ 和 $b$, 对应着一个函数。例如红色点代表着 $b=-180$ 且 $w=-2$ 时得到的函数 $y=-180-2 x_{cp}$. 而颜色代表根据定义的损失函数,使用当前的函数将会有多糟糕,越偏红色数值越大,越偏蓝色数值越小,因此最好的函数落在图中红叉标记的位置。

步骤三:找到最好的函数

我们已经定义了损失函数,可以衡量模型中每一个函数的好坏,现在需要挑选出最好的函数。写成公式的形式则是:

上面的第一个式子意味着,要找一个 $f$ 可以让 $L(f)$ 最小,这个可以让 $L(f)$ 最小的函数写为 $f^{\ast}$. 或者是由两个参数 $w$ 和 $b$ 来表示,找到能让 $L(w,b)$ 最小的也即是最好的 $w^{\ast}$ 和 $b^{\ast}$. 学习过线性代数的人应该知道这个方程理论上存在着闭式解(Closed-form Solution, 又叫解析解), 但求解起来比较麻烦,因此提出另外一种叫作梯度下降(Gradient Descent) 的方法,它适用于任何可微分的损失函数 $L$.

梯度下降

考虑损失函数 $L(w)$ 只有一个参数 $w$ 的情况,损失函数 $L(w)$ 可以是任何形式(只要满足其可微分). 现在要解决的问题是找到 $w^{\ast}=\arg \min _{w} L(w)$, 暴力的方法是穷举所有可能的 $w$ 并代入 $L(w)$ 后求值,这样虽可以找到全局最优点,却十分没有效率。而梯度下降的思想是这样的:

随机地选取初始值 $w^0$, 计算 $\left.\frac{d L}{d w}\right|_{w=w^{0}}$, 即参数 $w^0$ 位置 $w$ 对 $L$ 的微分,对微分不熟悉可以理解成在这一点切线的斜率。如果斜率为负,表明左边损失高而右边损失低,为了降低损失应该增加 $w$ 的值;反之应该减少 $w$ 的值。你也可以想象成有一个人想要下坡,站在 $w^0$ 处看了看前后,确定哪个方向是下坡的方向。

确定方向后,应该要改变多少 $w$ 的值呢?这个改变量通常写成 $\eta\left.\frac{d L}{d w}\right|_{w=w^{0}}$, 取决于现在的微分值和一个常数项 $\eta$, 叫作学习率(Learning Rate). 学习率是一个事先定好的数值,可以影响参数更新的速度,也就是学习的速度。这类无法自动学得,需要在学习过程之前人为给出的参数又叫作超参数(Hyperparameters). 由于微分为负需要增加 $w$ 的值,为正需要减少 $w$ 的值,所以应该是 $w^{1} \leftarrow w^{0}-\eta\left.\frac{d L}{d w}\right|_{w=w^{0}}$, 前面乘以负号,这样才能使 $L(w)$ 降低。

接下来重复前面的步骤,计算 $\eta\left.\frac{d L}{d w}\right|_{w=w^{1}}$, 更新 $w^{2} \leftarrow w^{1}-\eta\left.\frac{d L}{d w}\right|_{w=w^{1}}$. 经过很多次迭代或者说参数更新,最后会达到一个局部最优点(Local Minima) $w^T$,此时微分结果为零,参数不会再更新。你可能会想:我们希望找到全局最优点(Global Minima), 而梯度下降只能找到局部最优,效果是不是很差?而实际上对于线性回归问题,是没有局部最优解的,也即是说它的局部最优就是全局最优解,这会在后面进行讨论。

两个参数的情况

接下来考虑有两个参数 $w$ 和 $b$ 的情况,现在要解决的问题是找到 $w^{\ast}, b^{\ast}=\arg \min _{w, b} L(w, b)$. 方法其实也一样,随机选取两个初始值 $w^0$ 和 $b^0$, 同时计算 $\left.\frac{\partial L}{\partial w}\right|_{w=w^{0}, b=b^{0}}$ 和 $\left.\frac{\partial L}{\partial b}\right|_{w=w^{0} , b=b^{0}}$ 两个偏微分,再对两个参数同时进行更新 $w^{1} \leftarrow w^{0}-\eta\left.\frac{\partial L}{\partial w}\right|_{w=w^{0}, b=b^{0}}$, $b^{1} \leftarrow b^{0}-\eta\left.\frac{\partial L}{\partial b}\right|_{w=w^{0}, b=b^{0}}$. 重复上面的步骤直至找到局部最优点。需要注意的是,偏微分是同时计算的,参数也是同时更新的,不能计算出 $w^1$ 对 $L$ 的偏微分后,将 $w^1$ 更新为 $w^2$, 再计算 $b^1$ 对 $L$ 的偏微分,将 $b^1$ 更新为 $b^2$. 这是因为 $L(w,b)$ 是同时受到 $w$ 和 $b$ 两个参数影响的,推广到更多参数的情况也一样。

这个时候来理解一下“梯度”是什么,在这种情况下其实就是微积分中的

可以看出梯度其实就是将所有的偏微分项排成一个向量。

借助上图可以理解有两个参数的梯度下降情况,横轴是 $b$, 纵轴是 $w$, 它们决定函数长什么样子。而图中的颜色代表损失函数 $L(w,b)$ 的数值,越偏蓝色代表数值越小。图中红色点代表一组参数 $(w,b)$, 它的移动代表着参数更新的过程,参数更新的方向其实就是图中点所在的等高线的法线方向。相较于之前下坡的例子,现在假设一个人准备下山,他在某个坐标 $(w^0,b^0)$ 环顾四周,找到了最陡的下山路线,然后走出一步(这一步有多远会受到学习率的影响); 然后再环顾四周,再沿着最陡峭的方向向下走… 重复这一过程,目的是为了降低自己所处的高度,即损失函数 $L(w,b)$.

模型泛化能力

假设现在针对模型 $y=b+w \cdot x_{c p}$, 我们从训练数据(Training Data) 中通过梯度下降学到了当前最好的参数 $w$ 和 $b$, 来得到最优的函数 $f^\ast$, 即上边左图中红色的线。而我们发现,这条线似乎没有办法完全正确评定所有宝可梦的 CP 值,如果计算一下误差(Error), 即每个蓝色点和红色直线之间的离差如 $e^1$ 和 $e^2$, 可以得到在训练数据上的平均误差。

但我们实际关心的是模型的泛化(Generalization) 能力,即假设抓到一只新的宝可梦,使用现在的模型去预测,会有多少的预测误差。也即是说关心在没有出现过的新的数据,即测试数据(Testing Data) 上,误差会是多少。因此又抓了 10 只宝可梦作为测试数据,可以发现测试数据(右图) 和训练数据(左图) 的分布还是挺接近的。用在训练数据上学得的红色的线,大致上也能预测从未见过的宝可梦进化后的 CP 值,同样地可以用离差求和后取平均,来量化这个模型在测试数据上的表现。

做得更好:模型设计与选择

我们观察一下上面的数据,可以发现在原始 CP 值特别大与特别小的地方,预测比较不准。任天堂在设计游戏的时候一定是设计好了程序,计算出宝可梦进化后的 CP 值,比如根据原始 CP 值和一些其它的数据去生成进化后的 CP 值。正确的函数应该究竟是什么样的呢?对此我们可能需要设计不同的模型,从而去学习里面的参数。这里我们引入多项式模型的概念:

训练数据和测试数据依旧是原先的两组数据,每组有 10 个样本。我们设计了不同的模型,可以看出从左图到右图,模型参数 $w$ 越来越多,$x_{cp}$ 的最高次幂也越来越高,也即是说模型变得越来越复杂。通过在训练数据上的学习,我们会得到不同的红色曲线,采用同样的方式计算训练误差和测试误差,我们会发现:如果总是能找到最好的函数参数,模型如果越复杂,在训练数据上的训练误差会越小。

但是模型变复杂并不意味着总是能够在测试数据上取得较好的性能,我们看右图可以发现。虽然在训练数据的误差上已经很小很小,但用新数据进行测试时,会带来很大的误差。这种情况被称为过拟合(Overfitting), 意味着在训练数据上进行了过度学习。以后会解释产生这种情况的原因,但现在可以发现,选择一个好的模型显得尤其重要。

收集更多的数据,考虑更多的特征

只收集 10 只宝可梦的数据用于训练实在不太可靠,当我们收集 60 只宝可梦的数据时,可能会发现更多的信息——是不是有什么隐藏的因素没有被考虑进去——比如宝可梦的物种,我们用不同的颜色来表示不同的宝可梦物种。

我们回到机器学习流程的第一步,重新定义我们的模型:

  • 如果输入的宝可梦物种 $x_s$ 是 Pidgey, 输出 $y=b_{1}+w_{1} \cdot x_{c p}$
  • 如果输入的宝可梦物种 $x_s$ 是 Weedle, 输出 $y=b_{2}+w_{2} \cdot x_{c p}$
  • 如果输入的宝可梦物种 $x_s$ 是 Caterpie, 输出 $y=b_{3}+w_{3} \cdot x_{c p}$
  • 如果输入的宝可梦物种 $x_s$ 是 Eevee, 输出 $y=b_{4}+w_{4} \cdot x_{c p}$

存在这么多的条件,这样还是线性模型的形式吗?实际上上面的公式可以改写成:

整体来看依旧是 $y=b+\sum w_{i} x_{i}$ 的形式,其中

因此如果满足 $x_{s}=\text { Pidgey }$, 整个公式会变成 $y=b_{1}+w_{1} \cdot x_{c p}$ (舍去了其中为零的项).

将宝可梦的种类也作为一种特征考虑进去后,结果会得到下图中的曲线,不同颜色代表不同种类:

还有其它可能的特征会影响宝可梦进化后的 CP 值,比如体重 $x_w$、高度 $x_h$、生命值 $x_{hp}$ 等等。因此不妨将所有的特征都考虑进去,写出一个最复杂的模型:

  • 如果输入的宝可梦物种 $x_s$ 是 Pidgey, 输出 $y^{\prime}=b_{1}+w_{1} \cdot x_{c p}+w_{5} \cdot\left(x_{c p}\right)^{2}$
  • 如果输入的宝可梦物种 $x_s$ 是 Weedle, 输出 $y^{\prime}=b_{2}+w_{2} \cdot x_{c p}+w_{5} \cdot\left(x_{c p}\right)^{2}$
  • 如果输入的宝可梦物种 $x_s$ 是 Caterpie, 输出 $y^{\prime}=b_{3}+w_{3} \cdot x_{c p}+w_{5} \cdot\left(x_{c p}\right)^{2}$
  • 如果输入的宝可梦物种 $x_s$ 是 Eevee, 输出 $y^{\prime}=b_{4}+w_{4} \cdot x_{c p}+w_{5} \cdot\left(x_{c p}\right)^{2}$

如何设计模型完全取决于你,但是上面的这个复杂的模型测试误差远超过训练误差,即发生了过拟合。如何处理这种情况呢,如果能知道哪些特征或哪些次幂是无效项,当然是最好的了。实际上这很难实现,因此为了避免过拟合,人们有对应的处理办法。

正则化:避免过拟合的技术

我们回到机器学习流程的第二步,在评价函数好坏的时候,重新设计损失函数——将一些人为约束放进去,从而找到更好的函数。假设我们的模型形式依旧为:

原始的损失函数为:

这个损失函数只考虑了训练数据的预测值和实际值之间的误差带来的损失,可以看成是一种训练经验,因此常常被称为经验损失。而正则化(Regularization) 就是向其中添加额外的惩罚项(Penalty), 惩罚参数变换带来的优化影响,通常为 $\lambda \sum\left(w_{i}\right)^{2}$. 其中 $\lambda$ 是一个常数,称为惩罚系数。完整的损失函数形式为:

惩罚项有时候被称为结构损失,即参数给模型结构造成的影响,所以也可以算作损失函数的一部分。


在优化问题的角度,有的人为了区分新的目标函数和原有的损失函数 $L$, 使用 $J$ 作为目标函数的符号,因此你在文献中可看到的目标函数优化框架往往如下:


当参数 $w_i$ 值越小(接近零) 时,惩罚项越小,损失函数的值也会越小。这是因为参数值比较接近零时,函数显得比较平滑,即输入有变化的时候,输出对这种变化表现得不敏感。我们假设输入变化为 $\Delta x_{i}$, 此时可以发现输出

可以理解成,如果训练数据中的输入存在着一些噪声数据,由于函数比较平滑,所以能减弱这种数据带来的影响。通过实验可以发现,惩罚系数 $\lambda$ 越大,函数越平滑,对误差的考虑越少,在训练数据上得到的训练误差会越大,但在测试数据上得到的测试误差可能会越小。而如果惩罚系数 $\lambda$ 过大,函数过于平滑(极端情况下是水平线), 则无法完成任何任务,因此调整 $\lambda$ 参数的大小也十分关键。

正则化时不需要考虑参数 $b$, 即偏置项。因为我们希望让函数变得平滑,而偏置项只是起到了一个平移的作用,它对于函数的形状变化没有任何影响。我们会在后面的不同阶段再次提到正则化,目前只需知其然,再合适的时候知其所以然。

二元最小二乘闭式解推导(可选)

提示:这一部分暂时看不懂也没有关系,后面会有对线性模型的总结文章。

对于有 $m$ 个的训练数据 $D=\left\{\left(x_{i}, y_{i}\right)\right\}_{i=1}^{m}$, 注意此时下标代表的是索引顺序,即第 $i$ 个样本。此时有预测值 $f\left(x_{i}\right)=w x_{i}+b$, 真实值为 $y_i$, 因此损失函数为:

求解 $w$ 和 $b$ 使 $E_{(w, b)}$ 最小化的过程,称为线性回归模型的最小二乘“参数估计”(parameter estimation). 我们可以将 $E_{(w, b)}$ 分别对 $w$ 和 $b$ 求导,得到

这两个偏微分值为零时可得 $w$ 和 $b$ 的最优解,过程如下:

常用的等价变形公式为

令 $\frac{\partial E_{(w, b)}}{\partial w}=0$, 可得 $ w \sum_{i=1}^{m} x_{i}^{2}=\sum_{i=1}^{m} y_{i} x_{i}-\sum_{i=1}^{m} b x_{i} $.

令 $\frac{\partial E_{(w, b)}}{\partial b}=0$, 可得 $b=\frac{1}{m} \sum_{i=1}^{m}\left(y_{i}-w x_{i}\right) = \overline{y}-w \overline{x}$. 代入上式有

将 $w$ 项整理至一边有:

上面这个公式是周志华教授西瓜书中给出的结果,实际上可进一步简化为向量化形式:

若令 $\boldsymbol{x}=\left(x_{1}, x_{2}, \ldots, x_{m}\right)$ , $\boldsymbol{y}=\left(y_{1}, y_{2}, \ldots, y_{m}\right)$. 且 $\boldsymbol{x}_d=\boldsymbol{x}-\boldsymbol{\overline{x}}$, $\boldsymbol{y}_d=\boldsymbol{y}-\boldsymbol{\overline{y}}$, 则有:

向量化这种形式的意义在于,可通过矩阵运算的形式一次性地完成计算,提升计算机的运算效率(矩阵运算优于循环计算). 在求解多元线性回归模型时我们将偏置项 $b$ 吸收,从而不用进行去均值的操作. 多元线性回归的最优解为:

先不考虑符号的含义,仅观察它和二元情况下的相似性,学习过矩阵形式的线性回归后,感触会更深。