本人最近一直在学习Aurélien Géron所写的《Hands-On Machine Learning with Scikit-Learn & TensorFlow》一书,觉得这本书非常适合机器学习的入门,该书并没有很深地介绍算法的各种细节(繁多的数学公式,容易造成只见树木,不见森林的情况),而是通过浅显易懂的文字描述、少量数学公式以及大量的图示对各种算法的基本原理、适用条件、库函数调用、性能评价指标等方面进行了说明,从而使读者对不同的机器学习算法有一个宏观、直观且完整的了解和认识,并在掌握算法优缺点的基础上能够灵活使用已有的库函数来解决实际问题。通过学习该书,应该能够建立起机器学习的基本知识框架,从而为后续具体算法的深入学习和研究打下基础。
学习这本书最初源于MIT的Gilbert Strang大牛(18.06 “Linear Algebra”这门课的可爱老教授)为他的新课18.065 “Matrix Methods In Data Analysis, Signal Processing, And Machine Learning”所写的新书《Linear Algebra and Learning from Data》,该书的序言推荐了这本书。该书的作者曾领导Google YouTube视频分类团队,因此作者在机器学习领域有着深厚的理论基础和丰富的工程经验。该书内容逻辑紧密,表述清晰,并在GitHub上有配套程序,在此推荐给大家。
本人将书中线性回归模型的相关内容进行了小结、补充和扩展,现分享给大家,欢迎指正。
线性回归(Linear Regression)是一种最简单的预测模型且该模型具有非常好的数学性质,该模型可以表示为:
y ^ = θ 0 + θ 1 x 1 + θ 2 x 2 + ⋯ + θ n x n = θ 0 x 0 + θ 1 x 1 + θ 2 x 2 + ⋯ + θ n x n ( 1 ) \hat{y} =\theta_0 + \theta_1x_1+\theta_2x_2+\dots+\theta_nx_n \\ \qquad \qquad =\theta_0x_0 + \theta_1x_1+\theta_2x_2+\dots+\theta_nx_n \quad \red{(1)} y^=θ0+θ1x1+θ2x2+⋯+θnxn=θ0x0+θ1x1+θ2x2+⋯+θnxn(1)
其中, n n n表示样本特征(feature)的数量, x i ( i = 1 , 2 , … , n ) x_i (i=1,2,\dots,n) xi(i=1,2,…,n)表示样本第 i i i个特征且 x 0 ≡ 1 x_0 \equiv 1 x0≡1, θ i ( i = 0 , 1 , 2 , … , n ) \theta_i(i=0,1,2,\dots,n) θi(i=0,1,2,…,n)表示线性回归模型的系数, y ^ \hat{y} y^表示预测值。
为了表达简洁,使用向量形式重新表示公式(1)得到
y ^ = h θ ( x ) = θ T x ( 2 ) \hat{y}=h_{\bm{\theta}}(\textbf{x})=\bm{\theta}^T\textbf{x} \quad \red{(2)} y^=hθ(x)=θTx(2)
其中, θ = [ θ 0 , θ 1 , θ 2 , … , θ n ] T \bm{\theta}=\left[\theta_0,\theta_1,\theta_2,\dots,\theta_n\right]^T θ=[θ0,θ1,θ2,…,θn]T表示模型的参数向量(parameter vector), x = [ x 0 , x 1 , x 2 , … , x n ] T \textbf{x}=\left[x_0,x_1,x_2,\dots,x_n\right]^T x=[x0,x1,x2,…,xn]T表示样本的特征向量(feature vector), h θ h_{\bm{\theta}} hθ表示假设函数(hypothesis function)或预测函数,且该函数使用模型的参数向量 θ \bm{\theta} θ作为参数。
对于预测模型,最常使用的性能评价指标是均方根误差(Root Mean Square Error, RMSE)。在实际中,为了方便计算,使用均方误差(Mean Square Error, MSE)而不是RMSE(带根号不方便计算)来训练模型。因为,使MSE达到最小值和使RMSE达到最小值所对应的的参数向量 θ \bm{\theta} θ是同一个,我们也将MSE定义为线性回归模型的代价函数(cost function)。因此,线性回归模型的训练就是要根据训练样本集(training set)确定模型的参数向量 θ \bm{\theta} θ从而使代价函数取最小值。线性回归模型的代价函数(即MSE)可以表示为
J ( θ ) = MSE ( θ ) = 1 m ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) 2 ( 3 ) J\left( \bm{\theta} \right)=\text{MSE}\left( \bm{\theta} \right)=\frac{1}{m}\sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)^2 \quad \red{(3)} J(θ)=MSE(θ)=m1i=1∑m(θTx(i)−y(i))2(3)
其中, m m m表示训练样本集中样本的个数, x ( i ) = [ x 0 ( i ) , x 1 ( i ) , x 2 ( i ) , … , x n ( i ) ] T \textbf{x}^{(i)}=\left[x_0^{(i)},x_1^{(i)},x_2^{(i)},\dots,x_n^{(i)}\right]^T x(i)=[x0(i),x1(i),x2(i),…,xn(i)]T表示第 i i i个样本的特征向量, y ( i ) y^{(i)} y(i)表示第 i i i个样本的标签值(label)。在很多情况下,训练模型所使用的的代价函数和评价模型性能的指标函数是不同的,其原因在于性能评价指标函数在计算便利性、可导性上有欠缺,或者需要在训练中对参数加以额外的限制(即正则化(Regularization))。
如何求解模型的参数向量 θ \bm{\theta} θ使公式(3)的代价函数 J ( θ ) J\left( \bm{\theta} \right) J(θ)在给定的训练样本集上达到最小值?这里介绍两种基本方法:一种是基于闭式解(Close-Form Solution)或解析解(Analytical Solution)的方法,另一种是基于梯度下降(Gradient Descent, GD)的方法。
对于线性回归模型,通过最小化代价函数来求解模型的参数向量 θ \bm{\theta} θ这个数学问题是有闭式解或解析解的(其他模型不一定有这样好的数学性质),即可以通过数学公式求解。
将训练样本集中每个样本的特征向量和标签值都带入公式(1)所示的线性模型中,得到
y ( 1 ) = θ 0 x 0 ( 1 ) + θ 1 x 1 ( 1 ) + θ 2 x 2 ( 1 ) + ⋯ + θ n x n ( 1 ) y ( 2 ) = θ 0 x 0 ( 2 ) + θ 1 x 1 ( 2 ) + θ 2 x 2 ( 2 ) + ⋯ + θ n x n ( 2 ) ⋮ y ( m ) = θ 0 x 0 ( m ) + θ 1 x 1 ( m ) + θ 2 x 2 ( m ) + ⋯ + θ n x n ( m ) y^{(1)}=\theta_0x_0^{(1)} + \theta_1x_1^{(1)}+\theta_2x_2^{(1)}+\dots+\theta_nx_n^{(1)} \\ y^{(2)}=\theta_0x_0^{(2)} + \theta_1x_1^{(2)}+\theta_2x_2^{(2)}+\dots+\theta_nx_n^{(2)} \\ \vdots \\ y^{(m)}=\theta_0x_0^{(m)} + \theta_1x_1^{(m)}+\theta_2x_2^{(m)}+\dots+\theta_nx_n^{(m)} y(1)=θ0x0(1)+θ1x1(1)+θ2x2(1)+⋯+θnxn(1)y(2)=θ0x0(2)+θ1x1(2)+θ2x2(2)+⋯+θnxn(2)⋮y(m)=θ0x0(m)+θ1x1(m)+θ2x2(m)+⋯+θnxn(m)
该方程组共有 m m m个方程,需要求解 n + 1 n+1 n+1个未知数,即 θ = [ θ 0 , θ 1 , θ 2 , … , θ n ] T \bm{\theta}=\left[\theta_0,\theta_1,\theta_2,\dots,\theta_n\right]^T θ=[θ0,θ1,θ2,…,θn]T。一般情况下,训练样本集中样本的数量要远大于每个样本特征的数量,即 m ≫ n m \gg n m≫n。因此,该方程组中方程的个数远远多于未知数的个数,该方程组为超定(overdetermined)方程组。
将该超定方程组写成矩阵的形式:
X θ = y ( 4 ) \textbf{X}\bm{\theta}=\bm{y} \quad \red{(4)} Xθ=y(4)
其中, X \textbf{X} X表示以所有训练样本的特征向量为行向量所组成的矩阵,其形式为
X = [ x ( 1 ) T x ( 2 ) T ⋮ x ( m ) T ] = [ x 0 ( 1 ) x 1 ( 1 ) x 2 ( 1 ) … x n ( 1 ) x 0 ( 2 ) x 1 ( 2 ) x 2 ( 2 ) … x n ( 2 ) ⋮ ⋮ ⋮ … ⋮ x 0 ( m ) x 1 ( m ) x 2 ( m ) … x n ( m ) ] , \textbf{X}= \left[ \begin{matrix} {\textbf{x}^{(1)}}^T \\ {\textbf{x}^{(2)}}^T \\ \vdots\\ {\textbf{x}^{(m)}}^T \end{matrix} \right] =\left[ \begin{matrix} x_0^{(1)} & x_1^{(1)} & x_2^{(1)} & \dots & x_n^{(1)} \\ x_0^{(2)} & x_1^{(2)} & x_2^{(2)} & \dots & x_n^{(2)} \\ \vdots & \vdots & \vdots & \dots & \vdots \\ x_0^{(m)} & x_1^{(m)} & x_2^{(m)} & \dots & x_n^{(m)} \end{matrix} \right], X=⎣⎢⎢⎢⎢⎡x(1)Tx(2)T⋮x(m)T⎦⎥⎥⎥⎥⎤=⎣⎢⎢⎢⎢⎡x0(1)x0(2)⋮x0(m)x1(1)x1(2)⋮x1(m)x2(1)x2(2)⋮x2(m)…………xn(1)xn(2)⋮xn(m)⎦⎥⎥⎥⎥⎤,
y = [ y ( 1 ) , y ( 2 ) , … , y ( m ) ] T \bm{y}=\left[ y^{(1)}, y^{(2)},\dots, y^{(m)} \right]^T y=[y(1),y(2),…,y(m)]T表示标签向量(label vector)。
公式(4)所对应的矩阵方程可以使用正规方程(Normal Equation)求解,其公式为
θ ^ = ( X T X ) − 1 X T y . ( 5 ) \hat{\bm{\theta}}=\left( {\textbf{X}}^T\textbf{X} \right)^{-1}{\textbf{X}}^T\bm{y}. \quad \red{(5)} θ^=(XTX)−1XTy.(5)
通过正规方程求解出参数向量的估计值 θ ^ \hat{\bm{\theta}} θ^,从而完成线性回归模型的训练。
基于正规方程的方法的优点:
基于正规方程的方法的缺点:
综上所述,当样本特征数量较小且内存可以放入全部训练样本集时,可以使用正规方程来完成线性回归模型的训练。
由于基于正规方程的方法存在“ X T X {\textbf{X}}^T\textbf{X} XTX不一定可逆”和“计算复杂度”高的缺点,可以使用基于“伪逆”(Pseudoinverse或Moore-Penrose Pseudoinverse)的方法来求解矩阵方程(4)。
首先,对矩阵 X \textbf{X} X进行奇异值分解(Singular Value Decomposition,SVD),得到
X = U Σ V T \textbf{X}= \bm{U}\bm{\Sigma}{\bm{V}}^T X=UΣVT
其中 Σ \bm{\Sigma} Σ是半正定 m × ( n + 1 ) m\times(n+1) m×(n+1)阶对角矩阵。
则矩阵 X \textbf{X} X的“伪逆”定义为
X + = V Σ + U T \textbf{X}^{+}= \bm{V}\bm{\Sigma}^{+}{\bm{U}}^T X+=VΣ+UT
其中 Σ + \bm{\Sigma}^{+} Σ+是将 Σ \bm{\Sigma} Σ中的对角线非零元素取倒数后再进行矩阵转置的结果。
通过使用“伪逆”矩阵 X + \textbf{X}^{+} X+,方程(4)的解为
θ ^ = X + y . ( 6 ) \hat{\bm{\theta}}=\textbf{X}^{+}\bm{y}. \quad \red{(6)} θ^=X+y.(6)
公式(5)和(6)同为闭式解,相比于正规方程,基于“伪逆”的方法的优点在于:
因此,Scikit-Learn库的LinearRegression函数使用基于“伪逆”的方法求解参数向量的估计值 θ ^ \hat{\bm{\theta}} θ^。但基于“伪逆”的方法的局限性在于:
当样本特征数量很大或内存放不下全部训练样本集时,可以使用基于梯度下降(Gradient Descent, GD)的方法来完成线性回归模型的训练。
不同于基于闭式解/解析解中仅仅使用一个公式就完成线性回归模型的训练,梯度下降方法采用多次迭代逐步逼近最优解的方法得到参数向量的估计值 θ ^ \hat{\bm{\theta}} θ^,从而完成线性回归模型的训练,如图1所示。
梯度下降法可以这样比喻:你在山上迷路了,周边充满了浓雾,你只能感受到你脚下周边地面的坡度。那么,一种能够最快达到山底的方法就是每次都沿着脚下向下最陡的方向下山。
对于线性回归模型,它的MSE函数具有很好的数学性质,它是关于参数向量 θ \bm{\theta} θ的凸函数,具有唯一的极值点,这个极值点也即最小值点,如图1所示。当 θ \bm{\theta} θ为二维向量时( θ = [ θ 0 , θ 1 ] T \bm{\theta}=\left[\theta_0,\theta_1\right]^T θ=[θ0,θ1]T),其MSE函数形状类似于开口向上的抛物线;当 θ \bm{\theta} θ为三维向量时( θ = [ θ 0 , θ 1 , θ 2 ] T \bm{\theta}=\left[\theta_0,\theta_1,\theta_2\right]^T θ=[θ0,θ1,θ2]T),其MSE函数形状类似于开口向上的“碗”;当 θ \bm{\theta} θ为高维向量时( θ = [ θ 0 , θ 1 , θ 2 , … , θ n ] T \bm{\theta}=\left[\theta_0,\theta_1,\theta_2,\dots,\theta_n\right]^T θ=[θ0,θ1,θ2,…,θn]T),其MSE函数形状类似于高维空间中开口向上的“碗”。对于其他模型的训练,它的代价函数可能不是凸函数,函数图形存在许多“陷阱”,比如局部极值点、脊(ridge)、高原(plateau)等不规则形状,如图2所示,从而给最小值的迭代求解带来困难。
函数在某点处的梯度是一个向量,这个向量指向函数值变化最快的方向(即方向导数绝对值最大的方向),它的方向垂直于函数在该点处的等值线/面且指向函数值增大的方向。因此,可以随机选择 θ \bm{\theta} θ的初始值,然后每次沿着梯度的反方向(向下最陡的方向)下降一段距离,更新 θ ^ \hat{\bm{\theta}} θ^的估计值,即
θ ^ ( next step ) = θ ^ − η ∇ θ J ( θ ) ( 7 ) \hat{\bm{\theta}}^{(\text{next step})} = \hat{\bm{\theta}}-\eta \nabla_{\bm{\theta}}J(\bm{\theta}) \quad \red{(7)} θ^(next step)=θ^−η∇θJ(θ)(7)
其中, ∇ θ J ( θ ) \nabla_{\bm{\theta}}J(\bm{\theta}) ∇θJ(θ)表示代价函数的梯度向量, η \eta η是一个实数,称为学习率(learning rate),它表示每次下降的距离。学习率设置过小的话,则需要很多次迭代更新后才能收敛到最小值点,耗时长;学习率设置过大的话,则可能跳过最小值点造成算法不收敛。因此,如何设置合适的学习率也是一个重要问题,但在这里不做详细讨论。
由于线性回归模型的代价函数 J ( θ ) J(\bm{\theta}) J(θ)是关于 θ \bm{\theta} θ的凸函数,因此,当选择合适的学习率并等待足够长的时间后,运用公式(7)将使 θ ^ \hat{\bm{\theta}} θ^一步步收敛到最优估计值附近,那么什么时候终止迭代呢?从理论上讲,当梯度为零向量时,代价函数就达到了最小值,此时对应的参数向量就是估计值 θ ^ \hat{\bm{\theta}} θ^。在工程中,一种简单的方法是:首先设置一个很大的迭代次数,再设置一个提前终止条件:当梯度向量变得很小时,即梯度向量的模小于预设的一个很小阈值 ϵ \epsilon ϵ时,就认为已经近似达到代价函数的最小值点,而这个预设的小阈值 ϵ \epsilon ϵ称为容许度(tolerance)。如果尚未达到最大迭代次数而提前终止条件满足时,就可停止迭代;反之,就要迭代到最大迭代次数再终止。迭代停止后,将最新的 θ ^ \hat{\bm{\theta}} θ^作为参数向量的估计值,从而完成线性回归模型的训练。
此外,使用梯度下降法需要对样本各个特征的取值范围进行归一化(feature scaling),如图3所示。从左图中可以看出当各个特征取值范围归一化后,代价函数的图形是一个较为均匀的“碗”状,而迭代过程中梯度近乎沿直线朝最小值下降,路径较短,迭代次数较少,从而节省时间。但如果没有进行特征取值范围归一化,且不同特征间取值范围相差很大的话,则代价函数的图形如右图所示的一个拉长的“碗”状(对于取值范围小的那些特征,只有当它们对应的参数变化量很大时,才能使代价函数有较明显的变化;对于取值范围大的那些特征,当它们对应的参数变化量不大时,就能使代价函数有较明显的变化,因此,特征取值范围不同将造成参数取值范围不同),而迭代过程中梯度沿着类似“L”形(即先竖直再水平)的路径朝最小值下降,路径较长,迭代次数较多,耗时长。
图3. “特征归一化”对梯度下降法的影响。
下面的问题是如何计算公式(7)中的梯度向量 ∇ θ J ( θ ) \nabla_{\bm{\theta}}J(\bm{\theta}) ∇θJ(θ)。函数 f ( x 1 , x 2 , … , x n ) f(x_1,x_2,\dots,x_n) f(x1,x2,…,xn)的梯度计算公式为
∇ f = [ ∂ ∂ x 1 f ∂ ∂ x 2 f ⋮ ∂ ∂ x n f ] . \nabla{f} = \left[ \begin{matrix} \frac{\partial}{\partial x_1} f\\ \frac{\partial}{\partial x_2} f \\ \vdots\\ \frac{\partial}{\partial x_n} f \end{matrix} \right]. ∇f=⎣⎢⎢⎢⎡∂x1∂f∂x2∂f⋮∂xn∂f⎦⎥⎥⎥⎤.
因此,代价函数的梯度计算公式为
∇ θ J ( θ ) = [ ∂ ∂ θ 0 J ( θ ) ∂ ∂ θ 1 J ( θ ) ⋮ ∂ ∂ θ n J ( θ ) ] . ( 8 ) \nabla_{\bm{\theta}}J(\bm{\theta}) = \left[ \begin{matrix} \frac{\partial}{\partial \theta_0} J(\bm{\theta})\\ \frac{\partial}{\partial \theta_1} J(\bm{\theta})\\ \vdots\\ \frac{\partial}{\partial \theta_n} J(\bm{\theta}) \end{matrix} \right]. \quad \red{(8)} ∇θJ(θ)=⎣⎢⎢⎢⎡∂θ0∂J(θ)∂θ1∂J(θ)⋮∂θn∂J(θ)⎦⎥⎥⎥⎤.(8)
从公式(3)可以计算 J ( θ ) J(\bm{\theta}) J(θ)相对于 θ j ( j = 0 , 1 , 2 , … , n ) \theta_j(j=0,1,2,\dots,n) θj(j=0,1,2,…,n)的偏导数:
∂ ∂ θ j J ( θ ) = ∂ ∂ θ j [ 1 m ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) 2 ] = ∂ ∂ θ j [ 1 m ∑ i = 1 m ( θ 0 x 0 ( i ) + θ 1 x 1 ( i ) + ⋯ + θ j x j ( i ) + ⋯ + θ n x n ( i ) − y ( i ) ) 2 ] = 1 m ∑ i = 1 m 2 ( θ 0 x 0 ( i ) + θ 1 x 1 ( i ) + ⋯ + θ j x j ( i ) + ⋯ + θ n x n ( i ) − y ( i ) ) x j ( i ) = 2 m ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) x j ( i ) . ( 9 ) \frac{\partial}{\partial \theta_j} J(\bm{\theta}) = \frac{\partial}{\partial \theta_j} \left[ \frac{1}{m}\sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)^2 \right] \\ = \frac{\partial}{\partial \theta_j} \left[ \frac{1}{m}\sum_{i=1}^{m}\left( \theta_0x_0^{(i)}+\theta_1x_1^{(i)}+ \dots+\theta_jx_j^{(i)}+\dots+\theta_nx_n^{(i)}-y^{(i)} \right )^2 \right] \\ =\frac{1}{m}\sum_{i=1}^{m} 2\left( \theta_0x_0^{(i)}+\theta_1x_1^{(i)}+ \dots+\theta_jx_j^{(i)}+\dots+\theta_nx_n^{(i)}-y^{(i)} \right )x_j^{(i)} \\ = \frac{2}{m}\sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)x_j^{(i)}. \quad \red{(9)} ∂θj∂J(θ)=∂θj∂[m1i=1∑m(θTx(i)−y(i))2]=∂θj∂[m1i=1∑m(θ0x0(i)+θ1x1(i)+⋯+θjxj(i)+⋯+θnxn(i)−y(i))2]=m1i=1∑m2(θ0x0(i)+θ1x1(i)+⋯+θjxj(i)+⋯+θnxn(i)−y(i))xj(i)=m2i=1∑m(θTx(i)−y(i))xj(i).(9)
将公式(9)的结果带入公式(8)得到梯度向量:
∇ θ J ( θ ) = [ ∂ ∂ θ 0 J ( θ ) ∂ ∂ θ 1 J ( θ ) ⋮ ∂ ∂ θ n J ( θ ) ] = 2 m [ ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) x 0 ( i ) ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) x 1 ( i ) ⋮ ∑ i = 1 m ( θ T x ( i ) − y ( i ) ) x n ( i ) ] = 2 m [ [ x 0 ( 1 ) , x 0 ( 2 ) , … , x 0 ( m ) ] [ θ T x ( 1 ) − y ( 1 ) θ T x ( 2 ) − y ( 2 ) ⋮ θ T x ( m ) − y ( m ) ] [ x 1 ( 1 ) , x 1 ( 2 ) , … , x 1 ( m ) ] [ θ T x ( 1 ) − y ( 1 ) θ T x ( 2 ) − y ( 2 ) ⋮ θ T x ( m ) − y ( m ) ] ⋮ [ x n ( 1 ) , x n ( 2 ) , … , x n ( m ) ] [ θ T x ( 1 ) − y ( 1 ) θ T x ( 2 ) − y ( 2 ) ⋮ θ T x ( m ) − y ( m ) ] ] = 2 m [ x 0 ( 1 ) x 0 ( 2 ) … x 0 ( m ) x 1 ( 1 ) x 1 ( 2 ) … x 1 ( m ) ⋮ x n ( 1 ) x n ( 2 ) … x n ( m ) ] [ θ T x ( 1 ) − y ( 1 ) θ T x ( 2 ) − y ( 2 ) ⋮ θ T x ( m ) − y ( m ) ] = 2 m [ x 0 ( 1 ) x 0 ( 2 ) … x 0 ( m ) x 1 ( 1 ) x 1 ( 2 ) … x 1 ( m ) ⋮ x n ( 1 ) x n ( 2 ) … x n ( m ) ] [ θ T x ( 1 ) − y ( 1 ) θ T x ( 2 ) − y ( 2 ) ⋮ θ T x ( m ) − y ( m ) ] = 2 m [ x 0 ( 1 ) x 0 ( 2 ) … x 0 ( m ) x 1 ( 1 ) x 1 ( 2 ) … x 1 ( m ) ⋮ x n ( 1 ) x n ( 2 ) … x n ( m ) ] ( [ x 0 ( 1 ) x 1 ( 1 ) … x n ( 1 ) x 0 ( 2 ) x 1 ( 2 ) … x n ( 2 ) ⋮ x 0 ( m ) x 1 ( m ) … x n ( m ) ] [ θ 0 θ 1 ⋮ θ n ] − [ y ( 1 ) y ( 2 ) ⋮ y ( m ) ] ) = 2 m X T ( X θ − y ) ( 10 ) \nabla_{\bm{\theta}}J(\bm{\theta}) = \left[ \begin{matrix} \frac{\partial}{\partial \theta_0} J(\bm{\theta})\\ \frac{\partial}{\partial \theta_1} J(\bm{\theta})\\ \vdots\\ \frac{\partial}{\partial \theta_n} J(\bm{\theta}) \end{matrix} \right] =\frac{2}{m}\left[ \begin{matrix} \sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)x_0^{(i)}\\ \sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)x_1^{(i)}\\ \vdots\\ \sum_{i=1}^{m}\left( \bm{\theta}^T\textbf{x}^{(i)} - y^{(i)} \right)x_n^{(i)} \end{matrix} \right] \\ =\frac{2}{m}\left[ \begin{matrix} \left[ x_0^{(1)},x_0^{(2)},\dots,x_0^{(m)}\right]\left[ \begin{matrix} \bm{\theta}^T\textbf{x}^{(1)} - y^{(1)}\\ \bm{\theta}^T\textbf{x}^{(2)} - y^{(2)}\\ \vdots\\ \bm{\theta}^T\textbf{x}^{(m)} - y^{(m)} \end{matrix} \right]\\ \left[ x_1^{(1)},x_1^{(2)},\dots,x_1^{(m)}\right]\left[ \begin{matrix} \bm{\theta}^T\textbf{x}^{(1)} - y^{(1)}\\ \bm{\theta}^T\textbf{x}^{(2)} - y^{(2)}\\ \vdots\\ \bm{\theta}^T\textbf{x}^{(m)} - y^{(m)} \end{matrix} \right]\\ \vdots\\ \left[ x_n^{(1)},x_n^{(2)},\dots,x_n^{(m)}\right]\left[ \begin{matrix} \bm{\theta}^T\textbf{x}^{(1)} - y^{(1)}\\ \bm{\theta}^T\textbf{x}^{(2)} - y^{(2)}\\ \vdots\\ \bm{\theta}^T\textbf{x}^{(m)} - y^{(m)} \end{matrix} \right] \end{matrix} \right]\\ =\frac{2}{m} \left[ \begin{matrix} x_0^{(1)} & x_0^{(2)} &\dots & x_0^{(m)}\\ x_1^{(1)} & x_1^{(2)} & \dots & x_1^{(m)}\\ & & \vdots\\ x_n^{(1)} & x_n^{(2)}& \dots &x_n^{(m)} \end{matrix}\right]\left[ \begin{matrix} \bm{\theta}^T\textbf{x}^{(1)} - y^{(1)}\\ \bm{\theta}^T\textbf{x}^{(2)} - y^{(2)}\\ \vdots\\ \bm{\theta}^T\textbf{x}^{(m)} - y^{(m)} \end{matrix} \right] \\ =\frac{2}{m} \left[ \begin{matrix} x_0^{(1)} & x_0^{(2)} &\dots & x_0^{(m)}\\ x_1^{(1)} & x_1^{(2)} & \dots & x_1^{(m)}\\ & & \vdots\\ x_n^{(1)} & x_n^{(2)}& \dots &x_n^{(m)} \end{matrix}\right] \left[ \begin{matrix} \bm{\theta}^T\textbf{x}^{(1)} - y^{(1)}\\ \bm{\theta}^T\textbf{x}^{(2)} - y^{(2)}\\ \vdots\\ \bm{\theta}^T\textbf{x}^{(m)} - y^{(m)} \end{matrix} \right] \\ =\frac{2}{m} \left[ \begin{matrix} x_0^{(1)} & x_0^{(2)} &\dots & x_0^{(m)}\\ x_1^{(1)} & x_1^{(2)} & \dots & x_1^{(m)}\\ & & \vdots\\ x_n^{(1)} & x_n^{(2)}& \dots &x_n^{(m)} \end{matrix}\right] \left( \left[ \begin{matrix} x_0^{(1)} & x_1^{(1)} &\dots & x_n^{(1)}\\ x_0^{(2)} & x_1^{(2)} & \dots & x_n^{(2)}\\ & & \vdots\\ x_0^{(m)} & x_1^{(m)}& \dots &x_n^{(m)} \end{matrix}\right] \left[ \begin{matrix} \theta_0\\ \theta_1\\ \vdots\\ \theta_n \end{matrix}\right] - \left[ \begin{matrix} y^{(1)}\\ y^{(2)}\\ \vdots\\ y^{(m)} \end{matrix}\right] \right) \\ =\frac{2}{m}\textbf{X}^T\left( \textbf{X}\bm{\theta} - \bm{y}\right) \quad \red{(10)} ∇θJ(θ)=⎣⎢⎢⎢⎡∂θ0∂J(θ)∂θ1∂J(θ)⋮∂θn∂J(θ)⎦⎥⎥⎥⎤=m2⎣⎢⎢⎢⎢⎢⎢⎡∑i=1m(θTx(i)−y(i))x0(i)∑i=1m(θTx(i)−y(i))x1(i)⋮∑i=1m(θTx(i)−y(i))xn(i)⎦⎥⎥⎥⎥⎥⎥⎤=m2⎣⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎢⎡[x0(1),x0(2),…,x0(m)]⎣⎢⎢⎢⎡θTx(1)−y(1)θTx(2)−y(2)⋮θTx(m)−y(m)⎦⎥⎥⎥⎤[x1(1),x1(2),…,x1(m)]⎣⎢⎢⎢⎡θTx(1)−y(1)θTx(2)−y(2)⋮θTx(m)−y(m)⎦⎥⎥⎥⎤⋮[xn(1),xn(2),…,xn(m)]⎣⎢⎢⎢⎡θTx(1)−y(1)θTx(2)−y(2)⋮θTx(m)−y(m)⎦⎥⎥⎥⎤⎦⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎥⎤=m2⎣⎢⎢⎢⎢⎡x0(1)x1(1)xn(1)x0(2)x1(2)xn(2)……⋮…x0(m)x1(m)xn(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎡θTx(1)−y(1)θTx(2)−y(2)⋮θTx(m)−y(m)⎦⎥⎥⎥⎤=m2⎣⎢⎢⎢⎢⎡x0(1)x1(1)xn(1)x0(2)x1(2)xn(2)……⋮…x0(m)x1(m)xn(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎡θTx(1)−y(1)θTx(2)−y(2)⋮θTx(m)−y(m)⎦⎥⎥⎥⎤=m2⎣⎢⎢⎢⎢⎡x0(1)x1(1)xn(1)x0(2)x1(2)xn(2)……⋮…x0(m)x1(m)xn(m)⎦⎥⎥⎥⎥⎤⎝⎜⎜⎜⎜⎛⎣⎢⎢⎢⎢⎡x0(1)x0(2)x0(m)x1(1)x1(2)x1(m)……⋮…xn(1)xn(2)xn(m)⎦⎥⎥⎥⎥⎤⎣⎢⎢⎢⎡θ0θ1⋮θn⎦⎥⎥⎥⎤−⎣⎢⎢⎢⎡y(1)y(2)⋮y(m)⎦⎥⎥⎥⎤⎠⎟⎟⎟⎟⎞=m2XT(Xθ−y)(10)
因此,通过随机选择 θ \bm{\theta} θ的初始值,并将公式(10)带入公式(7)就可以通过迭代求解出参数向量的估计值 θ ^ \hat{\bm{\theta}} θ^,从而完成线性回归模型的训练。
由于每次迭代都需要重新计算一次梯度向量 ∇ θ J ( θ ) \nabla_{\bm{\theta}}J(\bm{\theta}) ∇θJ(θ),而从公式(10)可以看出每次梯度向量的计算都要使用全部训练样本集 X \textbf{X} X,这种梯度计算方法称为Batch GD(批量梯度下降)。
Batch GD算法的优点在于:
Batch GD方法的缺点在于:
Batch GD算法的收敛速率(convergence rate):当代价函数是凸函数且其斜率没有突变(比如MSE代价函数)的情况下,使用固定学习率 η \eta η的Batch GD算法的收敛速率为 O ( 1 迭代次数 ) O \left( \frac{1}{\text{迭代次数}} \right) O(迭代次数1),即当你将容许度 ϵ \epsilon ϵ设置为原值的 1 10 \frac{1}{10} 101(提升估计精度),则算法的迭代次数将比原来多10倍。
不同于Batch GD算法使用全部训练样本集数据(一个极端)来计算梯度,Stochastic GD(随机梯度下降)算法仅随机选取一个训练样本数据(另一个极端)来计算梯度。因此,随机梯度下降算法的计算复杂度大幅度降低。
假设从训练样本集中随机选取第 k k k个样本,则偏导数计算结果就变为
∂ ∂ θ j J ( θ ) = ∂ ∂ θ j ( θ T x ( k ) − y ( k ) ) 2 = 2 ( θ T x ( k ) − y ( k ) ) x j ( k ) . ( 11 ) \frac{\partial}{\partial \theta_j} J(\bm{\theta}) = \frac{\partial}{\partial \theta_j} \left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right)^2 = 2\left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right)x_j^{(k)}. \quad \red{(11)} ∂θj∂J(θ)=∂θj∂(θTx(k)−y(k))2=2(θTx(k)−y(k))xj(k).(11)
对比公式(9)和(11),发现公式(11)就是公式(9)中仅使用第 k k k个样本的形式。
将(11)式带入公式(8)得到梯度向量为
∇ θ J ( θ ) = [ ∂ ∂ θ 0 J ( θ ) ∂ ∂ θ 1 J ( θ ) ⋮ ∂ ∂ θ n J ( θ ) ] = 2 [ ( θ T x ( k ) − y ( k ) ) x 0 ( k ) ( θ T x ( k ) − y ( k ) ) x 1 ( k ) ⋮ ( θ T x ( k ) − y ( k ) ) x n ( k ) ] = 2 [ x 0 ( k ) x 1 ( k ) ⋮ x n ( k ) ] ( θ T x ( k ) − y ( k ) ) = 2 x ( k ) ( x ( k ) T θ − y ( k ) ) . ( 12 ) \nabla_{\bm{\theta}}J(\bm{\theta}) = \left[ \begin{matrix} \frac{\partial}{\partial \theta_0} J(\bm{\theta})\\ \frac{\partial}{\partial \theta_1} J(\bm{\theta})\\ \vdots\\ \frac{\partial}{\partial \theta_n} J(\bm{\theta}) \end{matrix} \right] =2\left[ \begin{matrix} \left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right)x_0^{(k)}\\ \left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right)x_1^{(k)}\\ \vdots\\ \left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right)x_n^{(k)} \end{matrix}\right] \\ =2\left[ \begin{matrix} x_0^{(k)}\\ x_1^{(k)}\\ \vdots\\ x_n^{(k)} \end{matrix}\right]\left( \bm{\theta}^T\textbf{x}^{(k)} - y^{(k)} \right) =2\textbf{x}^{(k)}\left( {\textbf{x}^{(k)}}^T\bm{\theta} - y^{(k)} \right). \quad \red{(12)} ∇θJ(θ)=⎣⎢⎢⎢⎡∂θ0∂J(θ)∂θ1∂J(θ)⋮∂θn∂J(θ)⎦⎥⎥⎥⎤=2⎣⎢⎢⎢⎢⎢⎢⎡(θTx(k)−y(k))x0(k)(θTx(k)−y(k))x1(k)⋮(θTx(k)−y(k))xn(k)⎦⎥⎥⎥⎥⎥⎥⎤=2⎣⎢⎢⎢⎢⎡x0(k)x1(k)⋮xn(k)⎦⎥⎥⎥⎥⎤(θTx(k)−y(k))=2x(k)(x(k)Tθ−y(k)).(12)
对比公式(10)和(12),发现公式(12)就是公式(10)中仅使用第 k k k个样本的形式。
通过将(12)式带入公式(7)就实现了参数向量 θ \bm{\theta} θ的迭代求解。
Stochastic GD算法的优点在于:
另一方面,Stochastic GD算法的缺点在于:
图5. 二维参数空间中Stochastic GD算法迭代收敛示意图。
这种“跳跃性”带来了一个好处,它可能能够帮助梯度下降算法从局部极小值点跳出,从而最终达到全局最小值点。一种比较好的策略是:先将学习率 η \eta η设置为较大值,从而帮助避免陷入局部极小值;再将学习率 η \eta η逐步降低,从而使算法收敛于全局最小值附近很小的一个区域中,从而达到较为精确的参数向量估计值 θ ^ \hat{\bm{\theta}} θ^,这种方法称为模拟退火(simulated anneling),而学习率 η \eta η的调整方法称为学习安排(learning schedule),其具体方法不在本文做介绍。
Mini-Batch GD算法介于Batch GD算法和Stochastic GD算法之间,是一种比较折中的方法,它每次都随机选取一部分训练样本(称为mini-batch)来计算梯度。
为了表示方便且不失一般性,假设从训练样本集中随机选取第 k k k到第 k + l k+l k+l个样本,则根据公式(10)和(12)的形式容易写出梯度为
∇ θ J ( θ ) = 2 l + 1 X ∗ T ( X ∗ θ − y ∗ ) ( 13 ) \nabla_{\bm{\theta}}J(\bm{\theta}) =\frac{2}{l+1}\textbf{X}_*^T\left( \textbf{X}_*\bm{\theta} - \bm{y}_*\right) \quad \red{(13)} ∇θJ(θ)=l+12X∗T(X∗θ−y∗)(13)
其中,
X ∗ = [ x 0 ( k ) x 1 ( k ) … x n ( k ) x 0 ( k + 1 ) x 1 ( k + 1 ) … x n ( k + 1 ) ⋮ ⋮ ⋮ ⋮ x 0 ( k + l ) x 1 ( k + l ) … x n ( k + l ) ] , \textbf{X}_*=\left[ \begin{matrix} x_0^{(k)} & x_1^{(k)} & \dots & x_n^{(k)} \\ x_0^{(k+1)} & x_1^{(k+1)} & \dots & x_n^{(k+1)} \\ \vdots & \vdots & \vdots & \vdots \\ x_0^{(k+l)} & x_1^{(k+l)} & \dots & x_n^{(k+l)} \end{matrix} \right], X∗=⎣⎢⎢⎢⎢⎡x0(k)x0(k+1)⋮x0(k+l)x1(k)x1(k+1)⋮x1(k+l)……⋮…xn(k)xn(k+1)⋮xn(k+l)⎦⎥⎥⎥⎥⎤,
y ∗ = [ y ( k ) , y ( k + 1 ) , … , y ( k + l ) ] T . \bm{y}_*=\left[ y^{(k)}, y^{(k+1)},\dots, y^{(k+l)} \right]^T. y∗=[y(k),y(k+1),…,y(k+l)]T.
通过将(13)式带入公式(7)就实现了参数向量 θ \bm{\theta} θ的迭代求解,从而完成了线性回归模型的训练。
Mini-Batch GD算法的优点在于:
Mini-Batch GD算法的缺点在于:相比于Stochastic GD算法,Mini-Batch GD算法可能更难跳出局部极小值点。
表1对线性归回模型的训练算法进行了小结和对比。
表1. 线性回归模型的训练算法对比。
算法 | 计算速度( m m m值很大) | Out-of-core | 计算速度( n n n值很大) | 超参数量 | 特征归一化 | Scikit-Learn函数 |
---|---|---|---|---|---|---|
正规方程 | 快 | 不支持 | 慢 | 0 | 不需要 | n/a |
“伪逆” | 快 | 不支持 | 慢 | 0 | 不需要 | LinearRegression |
Batch GD | 慢 | 不支持 | 快 | 2 | 需要 | n/a |
Stochastic GD | 快 | 支持 | 快 | ≥ \geq ≥ 2 | 需要 | SGDRegressor |
Mini-Batch GD | 快 | 支持 | 快 | ≥ \geq ≥ 2 | 需要 | n/a |
虽然线性回归模型的训练方法不同,但训练得到的模型结果是类似的。当线性回归模型训练好后,其预测过程十分简单:只需要将待预测样本的特征向量带入公式(1)或(2)就可计算出预测值,其预测过程的计算复杂度是 O ( n ) O(n) O(n)和 O ( m ) O(m) O(m),十分高效。
本文系统介绍了线性回归模型的表示、训练和预测,其中模型训练可以采用数学闭式解/解析解和梯度下降两种方法完成,文中分析了不同方法的优缺点和适用场合。虽然线性回归模型是一种最简单的机器学习模型,但对其深入理解有助于神经网络模型的理解、建模和训练。
[1]. A. Géron, Hands-On Machine Learning with Scikit-Learn & TensorFlow. CA: O’Reilly Media Inc., 2017.
[2]. https://github.com/ageron/handson-ml/issues/184
[3]. G. Strang, Introduction to Linear Algebra, 3rd ed. . MA: Wellesley-Cambridge Press, 2003.