前馈神经网络(feedforward neural network)
在这种神经网络中,各神经元从输入层开始,接收前一级输入,并输入到下一级,直至输出层。整个网络中无反馈,可用一个有向无环图(derected acyclic graph,DAG)表示。
通常我们说的前馈神经网络有两种:一种叫 Back Propagation Networks——反向传播网络(简称BP网络),一种叫做 RBF Networks ——径向基函数神经网络。
神经网络本身就有很多种设计模式,并且会在不同的模式下产生不同的训练效果和运用特点。
损失函数(Cost/Loss)
- 恒非负
- 误差越小函数值越小
- 收敛快
神经网络的训练
这个网络用函数表达式去写的话会是这样的:
zh=ωhx+bh,  yh=11+e−zhzo=ωoyh+bo,  yo=11+e−zo\begin{array}{lcl}
z_h = \omega_hx+b_h,\;y_h=\dfrac{1}{1+e^{-z_h}} \\\\
z_o = \omega_oy_h + b_o,\;y_o=\dfrac{1}{1+e^{-z_o}}
\end{array}zh=ωhx+bh,yh=1+e−zh1zo=ωoyh+bo,yo=1+e−zo1
- 准备样本
在一个复杂的网络中,我们准备用一定数量的用来训练的 xxx 向量,可以是文本,可以是图片,可以是音频,甚至可以是音视频结合的更为复杂的训练样本,当然只要是输入到网络中作为训练样本的一定是向量化的。
输入层x | 输出层y | 输入层x | 输出层y |
---|---|---|---|
1 | 0.1 | 6 | 0.6 |
2 | 0.2 | 7 | 0.7 |
3 | 0.3 | 8 | 0.8 |
4 | 0.4 | 9 | 0.9 |
5 | 0.5 | 10 | 1.0 |
- 清洗处理
在放入网络进行训练之前,需要进行一定处理,处理的目的是为了帮助网络更有效的、更准确地做好分类。 - 正式训练
在前面的工作基本做好的情况下,我们就可以开始训练模型了。
将上面表格中的数据丢进网络中,根据网络中两个神经元的表达式描述:
zh=ωhx+bh,  yh=11+e−zhzo=ωoyh+bo,  yo=11+e−zo\begin{array}{lcl} z_h = \omega_hx+b_h,\;y_h=\dfrac{1}{1+e^{-z_h}} \\\\ z_o = \omega_oy_h + b_o,\;y_o=\dfrac{1}{1+e^{-z_o}} \end{array}zh=ωhx+bh,yh=1+e−zh1zo=ωoyh+bo,yo=1+e−zo1
x1x_1x1 一旦代入之后,就会是这样一个映射关系了:
zh1=ωhx1+bh,  yh1=11+e−zh1zo1=ωoyh1+bo,  yo1=11+e−zo1\begin{array}{lcl} z_{h_1} = \omega_hx_1+b_h,\;y_{h_1}=\dfrac{1}{1+e^{-z_{h_1}}} \\\\ z_{o_1} = \omega_oy_{h_1} + b_o,\;y_{o_1}=\dfrac{1}{1+e^{-z_{o_1}}} \end{array}zh1=ωhx1+bh,yh1=1+e−zh11zo1=ωoyh1+bo,yo1=1+e−zo11
那么由 x1x_1x1 和 y1y_1y1 带来的误差值也可以定义了,也就是:
Loss1=(yo1−y1)2Loss_1 = (y_{o_1}-y_1)^2Loss1=(yo1−y1)2
由 10 个训练数据共同带来的误差值就变成了:
Loss=∑i=110(yoi−yi)2Loss = \sum_{i=1}^{10}(y_{o_i}-y_i)^2Loss=i=1∑10(yoi−yi)2
不论初始化 ωh\omega_hωh、bhb_hbh、ωo\omega_oωo、bob_obo 是什么值,这个损失函数 LossLossLoss 都是恒为非负数的,现在就开始 “挪动” ωh\omega_hωh、bhb_hbh、ωo\omega_oωo、bob_obo 这四个待定系数来逐步减小 LossLossLoss 的过程了,也就是需要有这样四个表达式来做更新:
(ωh)n=(ωh)n−1−η∂Loss∂ωh(bh)n=(bh)n−1−η∂Loss∂bh(ωo)n=(ωo)n−1−η∂Loss∂ωo(bo)n=(bo)n−1−η∂Loss∂bo\begin{array}{lcl} (\omega_h)^n= (\omega_h)^{n-1}-\eta\dfrac{\partial Loss}{\partial \omega_h}\\\\ (b_h)^n=(b_h)^{n-1}-\eta\dfrac{\partial Loss}{\partial b_h}\\\\ (\omega_o)^n=(\omega_o)^{n-1}-\eta\dfrac{\partial Loss}{\partial \omega_o}\\\\ (b_o)^n=(b_o)^{n-1}-\eta\dfrac{\partial Loss}{\partial b_o} \end{array}(ωh)n=(ωh)n−1−η∂ωh∂Loss(bh)n=(bh)n−1−η∂bh∂Loss(ωo)n=(ωo)n−1−η∂ωo∂Loss(bo)n=(bo)n−1−η∂bo∂Loss
即 ⟹\Longrightarrow⟹
Loss=∑i=110(yoi−yi)2⇒Loss=12∑i=110(yoi−yi)2∂Loss∂bo=∂∑i=110(yoi−yi)∂bo=∂∑i=110yoi∂bo=∑i=110∂yoi∂zo⋅∂zo∂bo∂Loss∂ωo=∂∑i=110(yoi−yi)∂ωo=∂∑i=110yoi∂ωo=∑i=110∂yoi∂zo⋅∂zo∂ωo∂Loss∂ωh=∂∑i=110(yoi−yi)∂ωh=∂∑i=110yoi∂ωh=∑i=110∂yoi∂zo⋅∂zo∂yh⋅∂yh∂zh⋅∂zh∂ωh∂Loss∂bh=∂∑i=110(yoi−yi)∂bh=∂∑i=110yoi∂bh=∑i=110∂yoi∂zo⋅∂zo∂yh⋅∂yh∂zh⋅∂zh∂bh\begin{array}{lcl} Loss=\displaystyle\sum_{i=1}^{10}(y_{oi}-y_i)^2 \Rightarrow Loss=\displaystyle\frac12 \sum_{i=1}^{10}(y_{oi}-y_i)^2\\\\ \dfrac{\partial Loss}{\partial b_o}=\dfrac{\displaystyle\partial\sum_{i=1}^{10}(y_{oi}-y_i)}{\partial b_o}=\dfrac{\displaystyle\partial\sum_{i=1}^{10}y_{oi}}{\partial b_o}=\displaystyle\sum_{i=1}^{10}\dfrac{\partial y_{oi}}{\partial z_o}\cdot\dfrac{\partial z_o}{\partial b_o}\\\\ \dfrac{\partial Loss}{\partial \omega_o}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}(y_{oi}-y_i)}{\partial \omega_o}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}y_{oi}}{\partial \omega_o}=\displaystyle\sum_{i=1}^{10}\dfrac{\partial y_{oi}}{\partial z_o}\cdot\dfrac{\partial z_o}{\partial \omega_o}\\\\ \dfrac{\partial Loss}{\partial \omega_h}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}(y_{oi}-y_i)}{\partial \omega_h}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}y_{oi}}{\partial \omega_h}=\displaystyle\sum_{i=1}^{10}\dfrac{\partial y_{oi}}{\partial z_o}\cdot\dfrac{\partial z_o}{\partial y_h}\cdot\dfrac{\partial y_h}{\partial z_h}\cdot\dfrac{\partial z_h}{\partial \omega_h}\\\\ \dfrac{\partial Loss}{\partial b_h}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}(y_{oi}-y_i)}{\partial b_h}=\dfrac{\partial \displaystyle\sum_{i=1}^{10}y_{oi}}{\partial b_h}=\displaystyle\sum_{i=1}^{10}\dfrac{\partial y_{oi}}{\partial z_o}\cdot\dfrac{\partial z_o}{\partial y_h}\cdot\dfrac{\partial y_h}{\partial z_h}\cdot\dfrac{\partial z_h}{\partial b_h} \end{array}Loss=i=1∑10(yoi−yi)2⇒Loss=21i=1∑10(yoi−yi)2∂bo∂Loss=∂bo∂i=1∑10(yoi−yi)=∂bo∂i=1∑10yoi=i=1∑10∂zo∂yoi⋅∂bo∂zo∂ωo∂Loss=∂ωo∂i=1∑10(yoi−yi)=∂ωo∂i=1∑10yoi=i=1∑10∂zo∂yoi⋅∂ωo∂zo∂ωh∂Loss=∂ωh∂i=1∑10(yoi−yi)=∂ωh∂i=1∑10yoi=i=1∑10∂zo∂yoi⋅∂yh∂zo⋅∂zh∂yh⋅∂ωh∂zh∂bh∂Loss=∂bh∂i=1∑10(yoi−yi)=∂bh∂i=1∑10yoi=i=1∑10∂zo∂yoi⋅∂yh∂zo⋅∂zh∂yh⋅∂bh∂zh
这样子,我们就可以把每次更新的这 4 个表达式的具体值都可以求出来了。
其他结构的网络中,可能会有一些小的区别。
区别1: 在训练样本很多的情况下 ∑\sum∑ 加和的次数会更多一些,有 1000 个样本就是 1000 次,有 10000 个样本就是 10000 次。
区别2: 如果网络层数更深,则算出的偏导数连乘的项就很长,在这里我们看到 2 层就出现 4 个,而如果有 10 层,那就是 20 个连乘。
区别3: 如果网络更为复杂,比如一层网络不止一个节点,那么其中一个节点上系数的偏导数则会从多个路径传播过去,因为在这个节点的后面会有不止一个节点把它的输出当成自己的输入,从而形成多个 “嵌套型关系”。