白话机器学习:神经网络


​ 现在的深度学习大行其道,深度学习就是利用深度神经网络来进行学习。而什么是深度网络呢,就是隐层大于1的网络(实际上远远大于1)。那啥时候又是隐层呢?这都需要从神经元开始说起。

神经元

​ 看看下面这样图:
在这里插入图片描述

​ 这就是神经网络中最基本的单元:M-P 神经元。神经元是模仿人类的神经单元组织出现的。

​ 神经元将输入转成输出:

  • 输入。输入又包含两个部分,输入数值 x 1 , x 2 . . . x n {x_1, x_2 ... x_n} x1,x2...xn和每个输入对应的权值 w 1 , w 2 . . . w n {w_1, w_2 ... w_n} w1,w2...wn

  • 输出。输出 y y y包含了包含了计算方式 f f f和阈值 θ \theta θ两个部分。

  • 激活函数。一般来说,输出通过 f f f计算之后,为了模仿人类神经元的“兴奋”、“抑制”的二值状态,会再 f f f之后增加一个激活函数。

    最简单的激活函数是 s g n ( x ) = { 1 , x ≥ 0 0 , x < 0 sgn(x) = \begin{cases} 1, x \geq 0 \\ 0, x<0 \end{cases} sgn(x)={1,x00,x<0,但是一般来说会使用数学性质更好的Sigmoid函数: s i g m o i d ( x ) = 1 1 + e − x sigmoid(x) = \frac{1}{1+e^{-x}} sigmoid(x)=1+ex1

在这里插入图片描述

​ 把这样的神经元前后连到一起,就形成了神经网络。

感知机 & 多层神经网络

​ 感知机是一种最简单的神经元连接方法:
在这里插入图片描述

神经网络学习

​ 神经网络的学习是通过一个学习率来调整各个参数。

​ 对于一个最简单的M-P神经元模型来说,假设有n个输入,那么对应了n个权重: w 1 , w 2 . . . w n {w_1, w_2 ... w_n} w1,w2...wn。还有一个阈值 θ \theta θ。假设把这个 θ \theta θ也放入到 w w w的向量中去,就可以统一的写成,对于每一个训练样本,我们要计算获得:
w i = w i + Δ w i Δ w i = η ( y − y ~ ) x i w_i = w_i + \Delta w_i \\ \Delta w_i = \eta(y-\tilde{y})x_i wi=wi+ΔwiΔwi=η(yy~)xi
​ 也就是说,根据每次训练样本中的 f f f的输入 y ~ \tilde y y~和真实值 y y y的差值,然后再乘以学习率 η \eta η来计算得到每个 w w w分量的调整量。根据这个调整量来调整模型中的 w w w。通过大量的训练样本迭代来获得最优化的 w w w向量。这就是神经网络的学习过程。

多层神经网络

​ 在这个模型中,只有两层神经元。《机器学习》的书上是提出了这个可以用于“与”、“或”、“非”三种逻辑运算的。但是如果碰到像“异或”这种线性不可分的问题,感知机(二层网络)就无法进行区分了。

在这里插入图片描述

​ 这时候,就需要在输入层和输出层之间增加其他的层:就是多层神经网络,除了输入层和输出层,其他的层统一叫做:“隐层”。

​ 像上面的异或问题,加上一层神经元节点就可以搞定这个问题:

在这里插入图片描述

​ 那么如果碰到更复杂的问题,可能就需要加上更多的隐层:

在这里插入图片描述

​ 上面所有的网络,因为我们的计算方向都是从输入层 -> 隐层 -> 输出层,可以说都是“往前“的,所以都叫做前馈网络

​ 一直增加隐层的数量,比如100层,200层,网络的结构越来越深,这样就演变成了深度神经网络,用深度神经网络来进行学习的方式就叫做深度学习

误差逆传播算法:BP(BackPropagation)

​ 针对多隐层的神经网络,不像感知机一样只有两层,也就是说不止一层的 w w w向量需要进行学习。那么对于这种神经网络,需要更加厉害一点的学习算法来进行。

​ 误差逆传播,也就是把这个误差一层一层从输出层往输入层传播。

​ 我们来看一下是怎么个一层一层的传播法,拿单隐层的网络来看,多隐层的类推:

在这里插入图片描述

  • l l l表示输出层的节点数, y 1 , y 2 , . . . y l {y_1, y_2, ... y_l} y1,y2,...yl表示每个输出层节点。
  • q q q表示隐层的节点数, b 1 , b 2 . . . b q b_1, b_2 ... b_q b1,b2...bq表示每个隐层节点。
  • d d d表示输入层的节点数, x 1 , x 2 . . . x d x_1, x_2 ... x_d x1,x2...xd表示每个输入层节点。
  • θ j , j ∈ ( 1 , 2... l ) \theta_{j}, j \in (1,2...l) θj,j(1,2...l)表示每个输出层节点中的阈值。
  • γ h , h ∈ ( 1 , 2... q ) \gamma_h, h \in (1,2...q) γh,h(1,2...q)表示每个隐层节点中的阈值。
  • 每个输出层的输入就是 q q q个隐层节点的链接,那么对于第 j j j的输入节点的输入就是 β j = ∑ h = 1 q w h j b h \beta_j = \sum_{h=1}^q{w_{hj}b{_h}} βj=h=1qwhjbh,其中 w h j w_{hj} whj为第 h h h的隐层节点到第 j j j个输出层的权重。 b h b_h bh则为第 h h h个隐层节点的输出值。
  • 类似地,每个隐层的输出值 b h b_h bh由与第 h h h个隐层节点的所有输入层节点来决定: α j = ∑ i = 1 d v i h x i \alpha_j = \sum_{i=1}^d{v_{ih}x_i} αj=i=1dvihxi,其中 v i h v_{ih} vih为第 i i i个输入层节点到第 h h h个隐层的权重。 x i x_i xi则为每个输入层节点的输入。
  • 如果有多个隐层,就一层一层的推下去。
  • 隐层和输出层的 f f f都定义为Sigmoid函数。

​ 基于上面的一些定义,可以得到:

  • 对于每个训练样本 ( x k , y k ) (x_k, y_k) (xk,yk)输出层的输出向量: y k ~ = ( y 1 k ~ , y 2 k ~ . . . y l k ~ ) \tilde{y_k} = (\tilde{y_1^k}^, \tilde{y_2^k}... \tilde{y_l^k}) yk~=(y1k~,y2k~...ylk~)。其中 y j k = f ( β j − θ j ) , j ∈ ( 1 , 2... l ) y_j^k = f(\beta_j-\theta_j), j \in (1,2...l) yjk=f(βjθj),j(1,2...l)。那么这个网络在这个样本上的均方误差就是: E k = 1 2 ∑ j = 1 l ( y j k ~ − y j k ) 2 E_k = \frac{1}{2}\sum_{j=1}^l{(\tilde{y_j^k} - y_j^k)^2} Ek=21j=1l(yjk~yjk)2

  • 如果针对上面公式里面的 y j k ~ \tilde{y_j^k} yjk~进行展开,代入上面的 β \beta β α \alpha α的话,总共就有 ( d + l + 1 ) q + l (d+l+1)q+l (d+l+1)q+l个参数需要进行学习。才能确定网络模型。

  • 对上述的所有的参数,我们需要计算出每次的调整量 Δ v \Delta v Δv,然后进行调整: v ← v + Δ v v\leftarrow v + \Delta v vv+Δv

  • Δ v \Delta v Δv使用梯度下降的策略去对参数进行计算。给定一个学习率 η \eta η,对其中一个参数 w h j w_{hj} whj的调整计算为(用 E E E去对这个参数 w h j w_{hj} whj求偏导,梯度下降就是找梯度最大,加个负号就是找下降最快的方向): Δ w h j = − η ∂ E k ∂ w h j \Delta{w_{hj}} = -\eta\frac{\partial E_k}{\partial w_{hj}} Δwhj=ηwhjEk,然后通过链式法则去一层层推导。我理解这里就体现除了逆传播这个概念吧。具体通过链式法则怎么一步一步推导的,因为自己数学水平有限,有兴趣的朋友可以自己去搜一搜。

  • 最终可以算出来几个值为:

    Δ w h j = η g j b h \Delta w_{hj} = \eta g_j b_h Δwhj=ηgjbh

    Δ θ j = − η g j \Delta \theta_j = -\eta g_j Δθj=ηgj

    Δ v i h = η e h x i \Delta v_{ih} = \eta e_h x_i Δvih=ηehxi

    Δ γ h = − η e h \Delta \gamma_h = -\eta e_h Δγh=ηeh

    其中:

    g j = y j k ~ ( 1 − y j k ~ ) ( y j k − y j k ) g_j = \tilde{y_j^k}(1-\tilde{y_j^k})(y_j^k-y_j^k) gj=yjk~(1yjk~)(yjkyjk)

    e h = b h ( 1 − b h ) ∑ j = 1 w h j g j e_h = b_h(1-b_h)\sum_{j=1}{w_{hj}g_j} eh=bh(1bh)j=1whjgj

  • 这里一个关键的点在于学习率 η \eta η,每个参数都可以使用不同的 η \eta η来确定,因为过大的 η \eta η会导致震荡,过小又过收敛过慢,导致大量的计算。

在这里插入图片描述

​ 一般把停止条件设置为损失达到某个较小的值。

​ 上面讲的是针对一个样本 ( x k , y k ) (x_k, y_k) (xk,yk)的均方误差计算,也就是说假设有 m m m个样本的数据集 D D D,针对每一个样本都进行一次误差反向传播,来进行参数更新。这样参数会及时更新,但是问题在于:参数可能会来回震荡,因为样本之间的误差可能会相互抵消。但实际上可能就是前 k k k个样本计算后,基本上就稳定收敛了。

​ 也可以将 m m m个样本分成 n n n个批次,每个批次是有 t = m / n t = m/n t=m/n个样本,但是BP算法的目标是要最小化训练集上的累积误差 E = 1 t ∑ j = 1 t E j E=\frac{1}{t}\sum_{j=1}^t{E_j} E=t1j=1tEj。根据你这个公式去做上述的推导和计算。

  • 一个一个样本计算的称为:标准BP算法
  • 一批一批样本计算的称为:累积BP算法

神经网络过拟合问题

​ 因为多层神经网络的拟合能力非常强,一些复杂的关系也可以通过增加隐层的层数来达到拟合。所以是需要解决过拟合的问题。

​ 一般采用两种策略来解决这个过拟合的问题:

  • 早停。顾名思义,就是让这个反向传播算法的参数更新早点停止,不需要把所有的样本全部训练完。将数据分成训练集和验证集(不是测试集,测试集是用于训练完成后评估网络的泛化误差的,这里的验证集我理解是用于在不断更新参数的过程中来控制过拟合的)。训练批次完成后(标准BP或者是累积BP),就用验证集数据评估一下误差,如果误差比之前升高了,就停止继续迭代。

  • 正则化。通过引入一个参数: λ \lambda λ,然后把网络学习的参数向量 w w w也纳入到误差计算公式 E E E中,并且通过 λ \lambda λ控制之前的 E E E和向量 w w w
    E = λ 1 m ∑ k = 1 m E k + ( 1 − λ ) ∑ i w i 2 E = \lambda\frac{1}{m}\sum_{k=1}^m{E_k} + (1-\lambda)\sum_{i}w_i^2 E=λm1k=1mEk+(1λ)iwi2
    书上说是通过 λ \lambda λ来控制,让反向传播的过程中会挑选较小的 w w w,网络的权重会比较光滑,从而降低过拟合的概率,不太懂是为什么。先这么记着吧。

局部最小与全局最小

​ 使用梯度下降方法来找最小值,假设上面的 E k E_k Ek函数在坐标系中的曲线为:

在这里插入图片描述

​ 网络的参数往往刚开始都是设置一个随机值开始,假设是从左边的某个点开始下降,很容易就陷入到局部最小的情况,然后算法停止。当然也有可能有右边开始下降,就可以找到全局最小。我们需要找到一个更有效的方法,防止梯度下降的时候尽可能小的陷入局部最小的情况。

  • 既然随机的话,就多选机组随机参数值开始进行下降算法,选其中让均方误差 E k E_k Ek最小的那一个,可以降低。
  • 模拟退火算法,在每一次的计算中,按照一定的概率选择次选方案进行下降。
  • 随机梯度下降,在梯度下降的时候,加入随机因素。