文章目录
建模过程总结和第一个最优化函数
建模过程
此处我们是通过一个简单的例子,来介绍机器学习、包括深度学习的利用优化方法建模的一般思想,我们可以将其总结如下:
-
Step 1:提出基本模型
如本节中,我们试图利用一条直线(y=ax+b)去拟合二维平面空间中的点,这里我们所使用的这条直线,就是我们提出的基本模型。而在后续的深度学习的学习过程中,我们还将看到更为强大、同时也更加通用的神经网络模型。当然,不同的模型能够适用不同的场景,在提出模型时,我们往往会预设一些影响模型结构或者实际判别性能的参数,如简单线性回归中的a和b;
-
Step 2:确定损失函数和目标函数
接下来,围绕建模的目标,我们需要合理设置损失函数,并在此基础之上设置目标函数,当然,在很多情况下,这二者是相同的。例如,在上述简单线性回归中,我们的建模目标就是希望y=ax+b这条直线能够尽可能的拟合(1,2)、(3,4)这两个点,或者说尽可能"穿过"这两个点,因此我们设置了SSE作为损失函数,也就是预测值和真实值的差值平方和。当然,在计算过程中不难发现,SSE是一个包含了a和b这两个变量的方程,因此SSE本身也是一个函数(a和b的二元函数),并且在线性回归中,SSE既是损失函数(用于衡量真实值和预测值差值的函数),同时也是我们的目标函数(接下来需要优化、或者说要求最小值的函数)。这里尤其需要注意的是,损失函数不是模型,而是模型参数所组成的一个函数。
-
Step 3:根据目标函数特性,选择优化方法,求解目标函数
之前提到,目标函数既承载了我们优化的目标(让预测值和真实值尽可能接近),同时也是包含了模型参数的函数,因此完成建模需要确定参数、优化结果需要预测值尽可能接近真实值这两方面需求就统一到了求解目标函数最小值的过程中了,也就是说,当我们围绕目标函数求解最小值时,也就完成了模型参数的求解。当然,这个过程本质上就是一个数学的最优化过程,求解目标函数最小值本质上也就是一个最优化问题,而要解决这个问题,我们就需要灵活适用一些最优化方法。当然,在具体的最优化方法的选择上,函数本身的性质是重要影响因素,也就是说,不同类型、不同性质的函数会影响优化方法的选择。在简单线性回归中,由于目标函数是凸函数,我们根据凸函数性质,判断偏导函数取值为0的点就是最小值点,进而完成a、b的计算(也就是最小二乘法),其实就是通过函数本身的性质进行最优化方法的选取。
第一个最优化函数
前面提到,利用优化方法求解目标函数其实是机器学习建模过程中最为核心的环节,因此,我们有必要将围绕上述简单线性回归问题,进一步讨论最小二乘法背后的数学逻辑和优化思想,同时简单探讨数据的矩阵表示方法和基本矩阵运算。虽然最小二乘法并不是主流的深度学习损失函数的优化算法,但从最小二乘法入手了解优化算法背后的数学逻辑,却是非常有必要,同时,线性方程也是构建神经网络模型的基础,因此,我们有必要深入探讨线性模型建模细节以及最基本的优化算法:最小二乘法。
1.最小二乘法的代数表示方法
从更加严格的数学角度出发,最小二乘法有两种表示形式,分别是代数法表示和矩阵表示。我们先看最小二乘法的代数表示方法。
首先,假设多元线性方程有如下形式
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1x1+w2x2+...+wdxd+b
令 w = ( w 1 , w 2 , . . . w d ) w = (w_1,w_2,...w_d) w=(w1,w2,...wd), x = ( x 1 , x 2 , . . . x d ) x = (x_1,x_2,...x_d) x=(x1,x2,...xd),则上式可写为
f ( x ) = w T x + b f(x) = w^Tx+b f(x)=wTx+b
在机器学习领域,我们将线性回归自变量系数命名为w,其实是weight的简写,意为自变量的权重。
多元线性回归的最小二乘法的代数法表示较为复杂,此处先考虑简单线性回归的最小二乘法表示形式。在简单线性回归中,w只包含一个分量,x也只包含一个分量,我们令此时的 x i x_i xi就是对应的自变量的取值,此时求解过程如下:
优化目标可写为:
S S E = ∑ i = 1 m ( f ( x i ) − y i ) 2 = E ( w , b ) SSE = \sum^m_{i=1}(f(x_i)-y_i)^2 = E_(w,b) SSE=∑i=1m(f(xi)−yi)2=E(w,b)
通过偏导为0求得最终结果的最小二乘法求解过程为:
∂ S S E ( w , b ) ∂ ( w ) = 2 ( w ∑ i = 1 m x i 2 − ∑ i = 1 m ( y i − b ) x i ) = 0 \frac{\partial{SSE_(w,b)}}{\partial{(w)}} = 2(w\sum^m_{i=1}x^2_i - \sum^m_{i=1}(y_i-b)x_i) = 0 ∂(w)∂SSE(w,b)=2(wi=1∑mxi2−i=1∑m(yi−b)xi)=0
进而可得
w = ∑ i = 1 m y i ( x i − x ˉ ) ∑ i = 1 m x i 2 − 1 m ( ∑ i = 1 m x i ) 2 w = \frac{\sum^m_{i=1}y_i(x_i-\bar{x}) }{\sum^m_{i=1}x^2_i-\frac{1}{m}(\sum^m_{i=1}x_i)^2} w=∑i=1mxi2−m1(∑i=1mxi)2∑i=1myi(xi−xˉ)
b = 1 m ∑ i = 1 m ( y i − w x i ) b = \frac{1}{m}\sum^m_{i=1}(y_i-wx_i) b=m1i=1∑m(yi−wxi)
其中, x ˉ = 1 m ∑ i = 1 m x i , x i \bar x = \frac{1}{m}\sum^m_{i=1}x_i,x_i xˉ=m1∑i=1mxi,xi为x的均值,并且 ( x i , y i ) (x_i,y_i) (xi,yi)代表二维空间中的点。针对二维空间内的(1,2)和(3,4)两个点,我们可以使用torch中运算函数手动计算w和b。
2.最小二乘法的矩阵表示形式
对于线性方程组来说,矩阵表示是一种更加简洁的表示方式,并且对于支持数组运算的torch来说,线性方程组的矩阵表示也更贴近代码的实际书写形式。首先将上述方程转化为矩阵的过程。线性方程如下:
1 ∗ a + b = 2 1*a + b = 2 1∗a+b=2
3 ∗ a + b = 4 3*a + b = 4 3∗a+b=4
在转化为矩阵表示的过程中,我们令
A = [ 1 1 3 1 ] A = \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right] A=[1311]
B = [ 2 4 ] B = \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] B=[24]
X T = [ a b ] X^T = \left [\begin{array}{cccc} a \\ b \\ \end{array}\right] XT=[ab]
则原方程组可表示为
A ∗ X T = B A * X^T = B A∗XT=B
更为一般的情况下,多元线性回归方程为
f ( x ) = w 1 x 1 + w 2 x 2 + . . . + w d x d + b f(x) = w_1x_1+w_2x_2+...+w_dx_d+b f(x)=w1x1+w2x2+...+wdxd+b
令
w ^ = ( w 1 , w 2 , . . . , w d , b ) \hat w = (w_1,w_2,...,w_d,b) w^=(w1,w2,...,wd,b)
x ^ = ( x 1 , x 2 , . . . , x d , 1 ) \hat x = (x_1,x_2,...,x_d,1) x^=(x1,x2,...,xd,1)
- w ^ \hat w w^:方程系数所组成的向量,并且我们将自变量系数和截距放到了一个向量中,此处 w ^ \hat w w^就相当于前例中的a、b组成的向量(a,b);
- x ^ \hat x x^:方程自变量和1共同组成的向量;
因此,方程可表示为
f ( x ) = w ^ ∗ x ^ T f(x) = \hat w * \hat x^T f(x)=w^∗x^T
另外,我们将所有自变量的值放在一个矩阵中,并且和此前A矩阵类似,为了捕捉截距,添加一列全为1的列在矩阵的末尾,设总共有m组取值,则
X = [ x 11 x 12 . . . x 1 d 1 x 21 x 22 . . . x 2 d 1 . . . . . . . . . . . . 1 x m 1 x m 2 . . . x m d 1 ] X = \left [\begin{array}{cccc} x_{11} &x_{12} &... &x_{1d} &1 \\ x_{21} &x_{22} &... &x_{2d} &1 \\ ... &... &... &... &1 \\ x_{m1} &x_{m2} &... &x_{md} &1 \\ \end{array}\right] X= x11x21...xm1x12x22...xm2............x1dx2d...xmd1111
对应到前例中的A矩阵,A矩阵就是拥有一个自变量、两个取值的X矩阵。令y为因变量的取值,则有
y = [ y 1 y 2 . . . y m ] y = \left [\begin{array}{cccc} y_1 \\ y_2 \\ . \\ . \\ . \\ y_m \\ \end{array}\right] y= y1y2...ym
此时,SSE可表示为:
S S E = ∣ ∣ y − X w ^ T ∣ ∣ 2 2 = ( y − X w ^ T ) T ( y − X w ^ T ) = E ( w ^ ) SSE = ||y - X\hat w^T||_2^2 = (y - X\hat w^T)^T(y - X\hat w^T) = E(\hat w) SSE=∣∣y−Xw^T∣∣22=(y−Xw^T)T(y−Xw^T)=E(w^)
根据最小二乘法的求解过程,令 E ( w ^ ) E(\hat w) E(w^)对 w ^ \hat w w^求导方程取值为0,有
E ( w ^ ) ∂ w ^ = ∂ ∣ ∣ y − X w ^ T ∣ ∣ 2 2 ∂ w ^ = ∂ ( y − X w ^ T ) T ( y − X w ^ T ) ∂ w ^ ∵ ( A − B ) T = A T − B T 并且 ( A B ) T = B T ∗ A T ∴ 上式 = ∂ ( y T − w ^ X T ) ( y − X w ^ T ) ∂ w ^ = ∂ ( y T y − w ^ X T y − y T X w ^ T + w ^ X T X w ^ T ) ∂ w ^ = 0 − X T y − X T y + 2 X T X w ^ T = X T X w ^ T − X T y = 0 值得注意的是,在矩阵求导中, a 为常数,有如下规则: ∂ a ∂ A = 0 , ∂ A T B T C ∂ A = B T C , ∂ C T B A ∂ A = B T C , ∂ A T B A ∂ A = ( B + B T ) A \frac{E(\hat w)}{\partial{\boldsymbol{\hat w}}} = \frac{\partial{||\boldsymbol{y} - \boldsymbol{X\hat w^T}||_2}^2}{\partial{\boldsymbol{\hat w}}} \\ = \frac{\partial(\boldsymbol{y} - \boldsymbol{X\hat w^T})^T(\boldsymbol{y} - \boldsymbol{X\hat w^T})}{\partial{\boldsymbol{\hat w}}} \\ \\ \because \ (A-B)^T = A^T - B^T并且(AB)^T = B^T*A^T \\ \\ \therefore 上式=\frac{\partial(\boldsymbol{y}^T - \boldsymbol{\hat w X^T})(\boldsymbol{y} - \boldsymbol{X\hat w^T})}{\partial{\boldsymbol{\hat w}}} \\ =\frac{\partial(\boldsymbol{y}^T\boldsymbol{y} - \boldsymbol{\hat w X^Ty}-\boldsymbol{y}^T\boldsymbol{X \hat w^T} +\boldsymbol{\hat wX^T}\boldsymbol{X\hat w^T})} {\partial{\boldsymbol{\hat w}}}\\ = 0 - \boldsymbol{X^Ty} - \boldsymbol{X^Ty} + 2\boldsymbol{X^TX\hat w ^T}\\ = \boldsymbol{X^TX\hat w^T} - \boldsymbol{X^Ty} = 0 \\ 值得注意的是,在矩阵求导中,a为常数,有如下规则: \frac{\partial{a}}{\partial{A}} = 0, \frac{\partial{A^TB^TC}}{\partial{A}} = B^TC, \frac{\partial{C^TBA}}{\partial{A}} = B^TC, \frac{\partial{A^TBA}}{\partial{A}} = (B+B^T)A ∂w^E(w^)=∂w^∂∣∣y−Xw^T∣∣22=∂w^∂(y−Xw^T)T(y−Xw^T)∵ (A−B)T=AT−BT并且(AB)T=BT∗AT∴上式=∂w^∂(yT−w^XT)(y−Xw^T)=∂w^∂(yTy−w^XTy−yTXw^T+w^XTXw^T)=0−XTy−XTy+2XTXw^T=XTXw^T−XTy=0值得注意的是,在矩阵求导中,a为常数,有如下规则:∂A∂a=0,∂A∂ATBTC=BTC,∂A∂CTBA=BTC,∂A∂ATBA=(B+BT)A
进一步可得
X T X w ^ T = X T y X^TX\hat w^T = X^Ty XTXw^T=XTy
要使得此式有解,等价于 X T X X^TX XTX(也被称为矩阵的交叉乘积crossprod存在逆矩阵,若存在,则可解出
w ^ T = ( X T X ) − 1 X T y \hat w ^T = (X^TX)^{-1}X^Ty w^T=(XTX)−1XTy
3.最小二乘法的简单实现
回到最初的例子,不难发现,有如下对应关系:
X = A = [ 1 1 3 1 ] X = A = \left [\begin{array}{cccc} 1 &1 \\ 3 &1 \\ \end{array}\right] X=A=[1311]
y = B = [ 2 4 ] y = B = \left [\begin{array}{cccc} 2 \\ 4 \\ \end{array}\right] y=B=[24]
w ^ T = X T = [ a b ] \hat w ^T = X^T = \left [\begin{array}{cccc} a \\ b \\ \end{array}\right] w^T=XT=[ab]
4.反向验证导数为零
当然,我们也可以反向验证,看下损失函数SSE在a=1,b=1时偏导数是否都为0。此时就需要借助PyTorch中的autograd模块来进行偏导计算。严格意义上来讲,autograd模块是PyTorch中的自动微分模块,我们可以通过autograd模块中的函数进行微分运算,在神经网络模型中,通过自动微分运算求解梯度是模型优化的核心。关于微分计算梯度进而执行优化的相关方法我们会在后续逐步介绍,此处我们仅适用autograd模块来进行简单的微分计算尝试,也就是对SSE进行偏导计算,判断a、b同时取值为1时偏导是否为0。
我们可以直接在张量Tensor中进行微分运算。目前市面上流通的PyTorch教材有些会介绍Variable类,在进行微分运算时需提前将Tensor类转化为Variable类,但其实在PyTorch 0.4版本以后Tensor就已经不仅仅是一个纯计算的载体,而是可以支持微分运算,Variable的概念被逐渐弱化,可微分性也变成了Tensor的一个基本属性,我们只需要在创建Tensor时,通过设置requires_grad属性为True、规定张量可微分即可。