Notes
深度学习
线性回归

线性回归

回归(Regtession)是指确定两种或两种以上变量间相互依赖的定量关系的一种统计分析方法。线性回归是回归分析中的一种,它是利用称为线性回归方程的最佳拟合直线(或曲线)来建立自变量和因变量之间的关系。

线性回归基于几个简单的假设。

  1. 假设自变量和因变量之间存在线性关系。即 y 可以表示为向量 x 中的元素的加权和。
  2. 假设观测数据中存在噪声,噪声服从正态分布。

线性模型

为了解释线性回归,我们举一个实际的例子。我们希望根据房屋的面积和房龄来预测房屋的价格,开发一个模型。这里有一些概念:

  • 训练数据集(training data set):我们会收集一些房屋的数据,包括面积、房龄和价格。这些数据被用来训练模型。
  • 样本(sample):每一条数据被称为一个样本。
  • 特征(feature):每个样本的属性被称为特征。在这个例子中,面积和房龄是特征。又称协变量(covariate)。
  • 标签(label):我们希望预测的结果被称为标签。在这个例子中,价格是标签。

对于这个需求,我们可以得出下面的式子:

price=warea×area+wage×age+bprice = w_{area} \times area + w_{age} \times age + b

其中,wareaw_{area}wagew_{age} 是权重(weight),bb 是偏置(bias)。这个式子就是线性模型。

偏置指当所有的特征都为 0 时,预测值为多少。

在机器学习领域,我们常常使用的是高维数据集,因此我们可以使用线性代数的符号来表示线性模型。我们可以将所有的特征放在一个向量中,将所有的权重放在一个向量中,这样我们可以将线性模型表示为:

y^=wTx+b\hat{y} = \mathbf{w}^T \mathbf{x} + b

我们可以将其展开为向量相乘的形式:

wTx=[w1w2wn][x1x2xn]=w1x1+w2x2++wnxn\mathbf{w}^T \mathbf{x} = \begin{bmatrix} w_1 & w_2 & \ldots & w_n \end{bmatrix} \begin{bmatrix} x_1 \\ x_2 \\ \vdots \\ x_n \end{bmatrix} = w_1 \cdot x_1 + w_2 \cdot x_2 + \ldots + w_n \cdot x_n

w 本身为一个列向量,x 也为一个列向量,为了使其相乘为一个标量,我们需要将 w 进行转置。

仅有数据集我们是无法确定向量 w 和 b 的值的,这就引入了我们下面要讲的损失函数。

损失函数

损失函数(loss function)是用来衡量模型的预测值与真实值之间的差距的函数。我们希望通过调整模型的参数,使得损失函数的值最小。

当损失函数最小时,我们此时取得的 w 和 b 就是最优的。

回归问题中,我们常常使用均方误差(mean squared error)作为损失函数。均方误差是预测值与真实值之差的平方的平均值。

li(w,b)=12(y^iyi)2l_{i}(w, b) = \frac{1}{2} (\hat{y}_i - y_i)^2

其中,y^i\hat{y}_i 是预测值,yiy_i 是真实值。常数 12\frac{1}{2} 是为了方便求导,使得导数的系数为 1。

在一维的情况下,我们可以画出下面的图象:

为了度量整个数据集的损失,我们可以将所有的损失函数的值求和:

L(w,b)=1ni=1nli(w,b)=1ni=1n12(y^iyi)2=1ni=1n12(wTxi+byi)2L(w, b) = \frac{1}{n} \sum_{i=1}^{n} l_{i}(w, b) = \frac{1}{n} \sum_{i=1}^{n} \frac{1}{2} (\hat{y}_i - y_i)^2 = \frac{1}{n} \sum_{i=1}^{n} \frac{1}{2} (\mathbf{w}^T \mathbf{x}_i + b - y_i)^2

解析解

解析解是指通过一些数学公式直接求解出模型的参数。如果一个模型有解析解,那么我们可以直接通过公式求解出模型的参数。

线性回归问题有解析解(analytical solution)。即解可以用一个公式表示出来。

首先我们将偏置 b 合并到权重 w 中,方法是在包含所有参数的矩阵中添加一列。

w=[bw1w2wn]T\mathbf{w} = \begin{bmatrix} b & w_1 & w_2 & \ldots & w_n \end{bmatrix}^T

在合并偏置项 bb 到参数向量中后,线性回归模型可以写成矩阵形式为:

y^=Xw\hat{y} = \mathbf{X}' \mathbf{w}'

矩阵相乘的过程如下:

[y^1y^2y^m]=[1x1,1x1,2x1,n1x2,1x2,2x2,n1xm,1xm,2xm,n][bw1w2wn]=[b+w1x1,1+w2x1,2++wnx1,nb+w1x2,1+w2x2,2++wnx2,nb+w1xm,1+w2xm,2++wnxm,n]\begin{bmatrix} \hat{y}_1 \\ \hat{y}_2 \\ \vdots \\ \hat{y}_m \end{bmatrix} = \begin{bmatrix} 1 & x_{1,1} & x_{1,2} & \ldots & x_{1,n} \\ 1 & x_{2,1} & x_{2,2} & \ldots & x_{2,n} \\ \vdots & \vdots & \vdots & \ddots & \vdots \\ 1 & x_{m,1} & x_{m,2} & \ldots & x_{m,n} \end{bmatrix} \begin{bmatrix} b \\ w_1 \\ w_2 \\ \vdots \\ w_n \end{bmatrix} = \begin{bmatrix} b + w_1 \cdot x_{1,1} + w_2 \cdot x_{1,2} + \ldots + w_n \cdot x_{1,n} \\ b + w_1 \cdot x_{2,1} + w_2 \cdot x_{2,2} + \ldots + w_n \cdot x_{2,n} \\ \vdots \\ b + w_1 \cdot x_{m,1} + w_2 \cdot x_{m,2} + \ldots + w_n \cdot x_{m,n} \end{bmatrix}

那么我们的预测问题是最小化损失函数:

yXw2\|\mathbf{y} - \mathbf{X}\mathbf{w}\|^2

在数学中,双竖线表示向量的范数(norm),而 yXw2\|\mathbf{y} - \mathbf{X}\mathbf{w}\|^2 表示向量 yXw\mathbf{y} - \mathbf{X}\mathbf{w} 的平方范数。

具体而言,对于一个向量 v=[v1,v2,,vn]\mathbf{v} = [v_1, v_2, \ldots, v_n],其平方范数定义为:

v2=v12+v22++vn2\|\mathbf{v}\|^2 = v_1^2 + v_2^2 + \ldots + v_n^2

令损失关于 w 的导数等于 0,我们可以得到解析解:

w=(XTX)1XTy\mathbf{w}' = (\mathbf{X}'^T \mathbf{X}')^{-1} \mathbf{X}'^T \mathbf{y}

这里为啥要将 w 的导数设为 0 呢?

我们知道,对于一个函数 f(x)f(x),当 f(x)=0f'(x) = 0 时,f(x)f(x) 取得极值。因此,我们可以通过求导来找到函数的极值。找到这个点可能是整个区域损失的极小点。

像线性回归这样的简单问题存在解析解,但是大多数深度学习模型并没有解析解。解析解对问题的限制很严格,导致它在实际中的应用受到了很大的限制。

随机梯度下降

对于那些没有解析解的问题,我们仍然可以有效训练模型,我们可以使用一种叫做梯度下降(gradient descent)的方法。这种方法基本可以优化所有的深度学习模型。

梯度下降的思路是,我们不断地迭代参数,使得损失函数的值不断减小。具体而言,我们首先随机初始化参数的值,然后不断迭代参数的值,使得损失函数的值不断减小。

梯度下降的过程如下:

  1. 随机初始化参数的值。
  2. 计算损失函数关于参数的导数。
  3. 更新参数的值。

我们可以通过下面的公式来更新参数的值:

wt=wt1αLwt1w_t = w_{t-1} - \alpha \frac{\partial L}{\partial w_{t-1}}

其中,α\alpha 是学习率(learning rate)。学习率是一个超参数(hyperparameter),需要我们自己来设置。学习率的值决定了参数更新的幅度。选取合适的学习率的方法将在后面的章节中讲到。

但我们往往不会使用全部的数据来计算损失函数的值,因为这样计算量太大。我们可以小批量的数据来计算损失函数的值,这种方法被称为小批量随机梯度下降(mini-batch stochastic gradient descent)。

随机采样 b 个样本,使用 i1, i2, ..., ib 来近似损失。

1/bj=1bl(xj,yj,w)1/b \sum_{j=1}^{b} l(x_{j}, y_{j}, w)

b 是另外一个超参数,称为批量大小(batch size)。批量大小决定了我们一次迭代使用多少个样本。

代码实现

生成数据集