(由于平台稿件格式问题,公式格式不能正确写上;如若读写困难可後台私信我要完整电子版)
目录
4.1 梯度下降法
4.1.1 梯度下降法在深度学习中的应用
通过前面的学习,我们知道了函数的极小值、极大值及它们对应的条件。在机器学习中,理想情况下,我们所谓的训练就是通过训练数据找到 Loss 函数的最小值所对应的自变量(待学习参数)。但是,找到最小值是一件非常困难的事情,因为需要遍历整个定义域才能得到,而算力不支持如此庞大的运算量。因此,我们往往退而求其次,降低要求,把求最小值简化成求极小值。
例如,在线性回归中,为了简化问题,假设特征维度为1,损失函数如下。
Loss=1/N ∑_(i=1)^N▒〖(wx_((i) )+w_0-y_((i) ))〗^2
其中,w 和 w_0 为自变量,x_((i) ) 和 y_((i) ) 为常数且 x_((i) ) 至少有一个不为0。如果所有 x_((i) )=0,则损失函数没有意义。
要想求得 Loss 的极小值所对应的 w=w^* 和 w_0=w_0^*,应该怎么做呢?
之前有过证明,线性回归的损失函数 Loss 为凸函数,它只存在极小值。因此,我们只
需要令一阶导数 ∂Loss/∂w=0,∂Loss/(∂w_0 )=0,即可求出极小值对应的 w^* 和 w_0^*,具体如下。
∂Loss/∂w |_(w=w^*,w_0=w_0^* )=2/N ∑_(i=1)^N▒〖x_((i) ) (w^* x_((i) )+w_0^*-y_((i) ))〗=0
∂Loss/(∂w_0 ) |_(w=w^*,w_0=w_0^* )=2/N ∑_(i=1)^N▒〖(w^* x_((i) )+w_0^*-y_((i) ))〗=0
易得
w^*=(∑_(i=1)^N▒〖(x_((i) )-x ̅)(y_((i) )-y ̅)〗)/(∑_(i=1)^N▒〖(x_((i) )-x ̅)〗^2 )
w_0^*=w^* x ̅-y ̅
其中
x ̅=1/N ∑_(i=1)^N▒x_((i) )
y ̅=1/N ∑_(i=1)^N▒y_((i) )
但是,并不是所有的函数都容易找到 w^* 和 w_0^* 的解析解。例如,当函数为多元函数时,有
Loss(w_0,w_1,⋯,w_m)=1/N ∑_(i=1)^N▒〖(w_0+w_1 x_((i),1)+w_2 x_((i),2)+⋯+w_m x_((i),m)-y_((i) ))〗^2
其中,x_((i),1)~x_((i),m) 为常数,w_0~w_m 为变量。
我们记 w=[■(w_1@⋮@w_m )],x=[■(x_1@⋮@x_m )],Loss 可简写成
Loss(w_0,w)=1/N ∑_(i=1)^N▒〖(w_0+w^T x_((i))-y_((i) ))〗^2
我们的目标没变,依旧是求 Loss 函数的极小值,以及对应的 w^*=[■(w_1^*@⋮@w_m^* )]和 w_0^*。因此,我们只需求解方程组
∂Loss/(∂w_j ) |_(w_0=w_0^*,w=w^* )=2/N ∑_(i=1)^N▒〖x_((i),j) (w_0^*+〖w^*〗^T x_((i))-y_((i) ))〗=0,j=1,⋯,m
∂Loss/(∂w_0 ) |_(w_0=w_0^*,w=w^* )=2/N ∑_(i=1)^N▒〖(w_0^*+w^* x_((i))-y_((i) ))〗=0
共计 m+1 个方程,m+1 个未知数。
理论上,我们可以求解 m+1 元1次方程,但在实际应用中,m 一般可以非常大,这时候求解方程就会遇到计算上的困难。既然求解方程行不通,是否还有其他的方法呢?
我们可以随机初始化 w_0=w_0^((0)) 和 w=w^((0)),即向量中每个元素都是随机产生的。其
中,∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) ) 表示 w_j 变化引起 Loss 变化的方向。下面我们分三种情况对 ∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) ) 进行讨论。
∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) )>0,此时函数关于 w_j 为增函数,则表示 w_j 变小,Loss 变小。
∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) )<0,此时函数关于 w_j 为减函数,则表示 w_j 变大,Loss 变小。
∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) )=0,则表示 Loss 已经达到最小值,w_j 无需变化。
综合上述三点,可以发现 w_j 朝 ∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) ) 的反方向变化,就可以使 Loss 变小。需要注意的是,∂Loss/(∂w_j ) |_(w_0=w_0^((0)),w=w^((0)) ) 仅指明了 w_j 变化的方向,并没有指出需要变化多
少。因此,我们可以进行如下更新。
w_j^((1))=w_j^((0))-μ ∂Loss/(∂w_j ) |_(w_0=w_0^((0) ),w=w^((0) ) ),j=0,1,⋯,m
其中,μ 为学习因子,用来控制 w_j 变化的幅度。更新后的 Loss(w_0=w_0^((1)),w=w^((1)) )≤Loss(w_0=w_0^((0)),w=w^((0)) ),w 的变化起到了减小 Loss 的作用。
因此,求解函数 Loss(w_0,w) 的极小值,可以使用如下方法。
随机初始化 w_0=w_0^((0)) 和 w=w^((0)),t=0。
同时,更新参数
w_j^((t+1))=w_j^((t))-μ ∂Loss/(∂w_j ) |_(w_0=w_0^((t) ),w=w^((t) ) ),j=1,⋯,m
和
w_0^((t+1))=w_0^((t))-μ ∂Loss/(∂w_0 ) |_(w_0=w_0^((t)),w=w^((t)) )
如果 t>T(指定迭代次数),或者 Loss 已经足够小了,或者 Loss 的变化已经很小,则任务结束,w^*=w^((t)) 和 w_0^*=w_0^((t))。否则,t=t+1,返回。
上述方法就是梯度下降法。相比于直接求解方程,梯度下降法有如下优点。
避免了方程无解析解,或者计算过于复杂的缺点。
更为通用,任何一个函数,只要存在一阶导数,都可以使用梯度下降法求解极小值。
这里说一下 μ 不能太大的原因。因为我们求解的梯度是在 w^((t)) 和 w_0^((t)) 这个点上的,在这个点周围可以近似认为梯度变化较小,而如果 μ 过大,导致远离该点,那么梯度本身就会发生变化,因此,移动方向就不准了。这就好比给人指路,指路的方向仅在短距离有效,距离越远,方向就越不准。
4.1.2 泰勒公式和梯度下降法
在数学中,我们研究的函数有无数个,如果要全部研究,几乎是一件不可能完成的事情。那么,函数是否有共性呢?例如,各类函数有没有可能都由基础元素组成,只是比例不同。这就好比一家果汁店,有十几种水果,通过不同的组合和比例,可以勾兑出很多种果汁,但是万变不离其宗,基础元素始终就是那十几种水果。泰勒公式就是一把解剖函数的手术刀,它将函数进行分解,找到对应的基本水果,便于我们研究。
泰勒公式的意思是,任何一个光滑的函数都可以用 n 阶多项式函数去逼近,即
f(x)=f(x0)/0!+(f^' (x0))/1! (x-x0)+(f^'' (x0))/2! (x-x0)^2+⋯+(f^((n) ) (x0))/n! (x-x0)^n+R_n (x)
=∑_(i=0)^n▒〖(f^((i) ) (x0))/i! (x-x0)^i 〗+R_n (x)
我们称上式为 f(x) 在 x0 上的泰勒展开,其中 x0 为定义域上各阶导数都存在的任意点。R_n (x) 是一个高阶无穷小,表示展开后的误差,它的大小与 n 和 x 有关。自变量 x 离 x0 越近,R_n (x) 越小,多项式逼近就越准。n 越大,R_n (x) 越小,多项式次数越高,逼近函数就越精确。为了研究方便,一般会直接忽略 R_n (x)。
泰勒公式给了我们一个启示:在机器学习中,无论需要逼近的函数形式有多复杂,最终都可以由 n 阶多项式进行逼近。
当 x=x0 时,对应的函数值为 f(x0)。我们给 x0 添加一个变化,即变为 x0+Δx,函数值则变为 f(x0+Δx)。如果我们希望 f(x0+Δx)≤f(x0),即函数朝小的方向变化,那么 Δx 应该为多少呢?
我们对函数进行一阶泰勒展开,并省略 R_1 (x),可以看到
f(x0+Δx)≈f(x0)+f^' (x0)Δx
为了满足 f(x0+Δx)≤f(x0),易得 f^' (x0)Δx<0,即 Δx 的符号和 f^' (x0) 相反,所以,x 的移动方向为 -f^' (x0)。不过,需要注意的是,我们之所以能够忽略 R_1 (x),是因为 Δx 足够小,从而保证了 x0+Δx 在 x0 附近,忽略 R_1 (x) 不会有太大误差。因此,x0 的移动不能过大,即真实的移动为
x0-μf^' (x0)
μ 通常较小,以保证泰勒展开误差不大。但是,μ 也不宜过小,如果过小,就会导致更新效率变低。以上即为梯度下降法的理论基础。
4.1.3 牛顿迭代法
在求解方程的时候,一些特定的如一元二次方程都有特殊的解析解,即方程解和各项系数有显示的关系,如一元二次方程
ax^2+bx+c=0
对应的解为
x=(-b±√(b^2-4ac))/2a
但是,很多方程复杂的方程很难找到其对应的解析解。例如,对方程
f(x)=x^7+2x^2+4x+3=0
我们就无法找出上面类似的公式直接算出 x。
我们可以使用一种特殊的迭代法来解方程 f(x)=0。设 x^* 为方程的解,即 f(x^* )=0。首先,假设一个初始点 x^((k)),在它附近进行泰勒展开,忽略 R_1 (x),可以得到
f(x)≈f(x^((k)) )+f^' (x^((k) ) )(x-x^((k) ))
令 f(x)=0,可以求得
x=x^((k) )-f(x^((k)) )/(f^' (x^((k) ) ) )
但是,一般来说,x≠x^*,即 x 并不是 f(x)=0 的解。这是因为泰勒展开式仅在 x^((k) ) 附近有效,如果 x^((k) ) 离 x^* 较远,自然就不准确。这只是一个粗略的估计,但相比 x^((k) ) 和 x^* 的距离,x 更靠近 x^*。如果 x^((k) ) 越来越靠近 x^*,那么使用泰勒展开式求解的结果会越来越准。因此,我们使用如下迭代过程求解方程。
随机初始化 x^((0) ),k=0。
计算 x^((k+1) )=x^((k) )-f(x^((k)) )/(f^' (x^((k) ) ) )。
验算 f(x^((k+1) ) )。如果 f(x^((k+1) ) )=0,则迭代结束,x^*=x^((k+1) )。否则,k=k+1,返回。
上述解方程的方法称为牛顿迭代法。只要方程存在解,那么无论方程本身多复杂,通过牛顿迭代法一定能找到。需要注意的是,如果方程有多个解,我们只能找到离初始值 x^((0) ) 最近的解。例如,求解方程
f(x)=x^7+2x^2+4x+3=0
的迭代过程如表4-1所示,初始化 x^((0) )=2。
表4-1
迭代次数 x^((k) ) f(x)
k=0 2.0 147.0
k=1 1.68 53.21
k=2 1.364 20.981
k=3 0.98 9.711
k =4 0.293 4.343
k =5 -0.546 1.397
k =6 -1.245 -3.506
k =7 -1.105 -0.984
k =8 -1.025 -0.184
k =9 -1.002 -0.011
k =10 -1.0 0.0
经过10次迭代,牛顿迭代法找到了 x^7+2x^2+4x+3=0 对应的解 x^*=-1。下面我们看看如何在神经网络中应用牛顿迭代法。
在神经网络中,训练的目的就是找到函数的极小值,而极小值进一步转变为求解方程
f^' (x)=0
我们依然可以使用牛顿迭代法求解。令 〖g(x)=f〗^' (x),那么
g(x^((k) ) )=f^' (x^((k) ) )
g^' (x^((k) ) )=f^'' (x^((k) ) )
因此,求解 f^' (x)=0 其实就是解方程 g(x)=0,迭代过程如下。
随机初始化 x^((0) ),k=0。
计算 x^((k+1) )=x^((k) )-g(x^((k) ) )/(g^' (x^((k) ) ) )=x^((k) )-(f^' (x^((k) ) ))/(f^'' (x^((k) ) ) )。
验算 f^' (x^((k+1) ) )。如果 f^' (x^((k+1) ) )=0,则迭代结束,x^*=x^((k+1) )。否则,k=k+1,返回。
可以看出,使用牛顿迭代法找函数的极值和梯度下降法类似,只不过学习因子 μ 被替换成了 1/(f^'' (x^((k) ) ) )。相比于固定的学习因子 μ,1/(f^'' (x^((k) ) ) ) 更加灵活,可以根据函数当前所在位置动态调整加快收敛速度。例如,对函数
f(x)=x^2
我们求解它的极小值。假设初始值为 x^((0) ),那么